diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..1e13c8996 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +## Contributing guidelines + +All guidelines for contributing to the OpenCV repository can be found at [`How to contribute guideline`](https://github.com/Itseez/opencv/wiki/How_to_contribute). diff --git a/modules/README.md b/modules/README.md index 2633ce3e6..1844f2905 100644 --- a/modules/README.md +++ b/modules/README.md @@ -52,4 +52,4 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=/modules -D BUILD_opencv_re 22. **opencv_xphoto**: Additional photo processing algorithms: Color balance / Denoising / Inpainting. -23. **opencv_stereo**: Stereo Correspondence done with different descriptors: Census / CS-Census / MCT / BRIEF / MV / RT. +23. **opencv_stereo**: Stereo Correspondence done with different descriptors: Census / CS-Census / MCT / BRIEF / MV. diff --git a/modules/adas/CMakeLists.txt b/modules/adas/CMakeLists.txt deleted file mode 100644 index fb122143a..000000000 --- a/modules/adas/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -if(IOS) - ocv_module_disable(adas) -endif() - -set(the_description "Automatic driver assistance algorithms") -ocv_define_module(adas opencv_xobjdetect) - -add_subdirectory(tools) diff --git a/modules/adas/README.md b/modules/adas/README.md deleted file mode 100644 index 7ccfb3a0f..000000000 --- a/modules/adas/README.md +++ /dev/null @@ -1,2 +0,0 @@ -ADAS: Advanced Driver Assistance Systems module with Forward Collision Warning -============================================================================== \ No newline at end of file diff --git a/modules/adas/src/adas.cpp b/modules/adas/src/adas.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/modules/adas/tools/CMakeLists.txt b/modules/adas/tools/CMakeLists.txt deleted file mode 100644 index 3cf5d7763..000000000 --- a/modules/adas/tools/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(fcw_train) -add_subdirectory(fcw_detect) diff --git a/modules/adas/tools/fcw_detect/CMakeLists.txt b/modules/adas/tools/fcw_detect/CMakeLists.txt deleted file mode 100644 index d2f2a2e11..000000000 --- a/modules/adas/tools/fcw_detect/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -set(name fcw_detect) -set(the_target opencv_${name}) - -set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio - opencv_highgui opencv_xobjdetect) - -ocv_check_dependencies(${OPENCV_${the_target}_DEPS}) - -if(NOT OCV_DEPENDENCIES_FOUND) - return() -endif() - -project(${the_target}) - -ocv_include_directories("${OpenCV_SOURCE_DIR}/include/opencv") -ocv_include_modules_recurse(${OPENCV_${the_target}_DEPS}) - -file(GLOB ${the_target}_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) - -add_executable(${the_target} ${${the_target}_SOURCES}) - -target_link_libraries(${the_target} ${OPENCV_${the_target}_DEPS}) - -set_target_properties(${the_target} PROPERTIES - DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" - ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} - RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} - INSTALL_NAME_DIR lib - OUTPUT_NAME ${the_target}) - -if(ENABLE_SOLUTION_FOLDERS) - set_target_properties(${the_target} PROPERTIES FOLDER "applications") -endif() - -install(TARGETS ${the_target} OPTIONAL RUNTIME DESTINATION bin COMPONENT main) diff --git a/modules/adas/tools/fcw_detect/fcw_detect.cpp b/modules/adas/tools/fcw_detect/fcw_detect.cpp deleted file mode 100644 index 318393a55..000000000 --- a/modules/adas/tools/fcw_detect/fcw_detect.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include -using std::string; - -#include -using std::vector; - -#include -using std::cerr; -using std::endl; - -#include -using cv::Rect; -using cv::Size; -using cv::Mat; -using cv::Mat_; -using cv::Vec3b; - -#include -using cv::imread; -using cv::imwrite; - -#include -using cv::CommandLineParser; -using cv::FileStorage; - -#include -using cv::xobjdetect::ICFDetector; - -static Mat visualize(const Mat &image, const vector &objects) -{ - CV_Assert(image.type() == CV_8UC3); - Mat_ img = image.clone(); - for( size_t j = 0; j < objects.size(); ++j ) - { - Rect obj = objects[j]; - int x = obj.x; - int y = obj.y; - int width = obj.width; - int height = obj.height; - for( int i = y; i <= y + height; ++i ) { - img(i, x) = Vec3b(255, 0, 0); - img(i, x + width) = Vec3b(255, 0, 0); - } - for( int i = x; i <= x + width; ++i) { - img(y, i) = Vec3b(255, 0, 0); - img(y + height, i) = Vec3b(255, 0, 0); - } - } - return img; -} -static bool read_window_size(const char *str, int *rows, int *cols) -{ - int pos = 0; - if( sscanf(str, "%dx%d%n", rows, cols, &pos) != 2 || str[pos] != '\0' || - *rows <= 0 || *cols <= 0) - { - return false; - } - return true; -} - -int main(int argc, char *argv[]) -{ - const string keys = - "{help | | print this message}" - "{model_filename | model.xml | filename for reading model}" - "{image_path | test.png | path to image for detection}" - "{out_image_path | out.png | path to image for output}" - "{threshold | 0.0 | threshold for cascade}" - "{step | 8 | sliding window step}" - "{min_window_size | 40x40 | min window size in pixels}" - "{max_window_size | 300x300 | max window size in pixels}" - "{is_grayscale | false | read the image as grayscale}" - ; - - CommandLineParser parser(argc, argv, keys); - parser.about("FCW detection"); - - if( parser.has("help") || argc == 1) - { - parser.printMessage(); - return 0; - } - - string model_filename = parser.get("model_filename"); - string image_path = parser.get("image_path"); - string out_image_path = parser.get("out_image_path"); - bool is_grayscale = parser.get("is_grayscale"); - float threshold = parser.get("threshold"); - int step = parser.get("step"); - - int min_rows, min_cols, max_rows, max_cols; - string min_window_size = parser.get("min_window_size"); - if( !read_window_size(min_window_size.c_str(), &min_rows, - &min_cols) ) - { - cerr << "Error reading min window size from `" << min_window_size << "`" << endl; - return 1; - } - string max_window_size = parser.get("max_window_size"); - if( !read_window_size(max_window_size.c_str(), &max_rows, - &max_cols) ) - { - cerr << "Error reading max window size from `" << max_window_size << "`" << endl; - return 1; - } - - int color; - if(is_grayscale == false) - color = cv::IMREAD_COLOR; - else - color = cv::IMREAD_GRAYSCALE; - - - if( !parser.check() ) - { - parser.printErrors(); - return 1; - } - - ICFDetector detector; - FileStorage fs(model_filename, FileStorage::READ); - detector.read(fs["icfdetector"]); - fs.release(); - vector objects; - Mat img = imread(image_path, color); - std::vector values; - detector.detect(img, objects, 1.1f, Size(min_cols, min_rows), Size(max_cols, max_rows), threshold, step, values); - imwrite(out_image_path, visualize(img, objects)); - - -} diff --git a/modules/adas/tools/fcw_train/fcw_train.cpp b/modules/adas/tools/fcw_train/fcw_train.cpp deleted file mode 100644 index a7f0e81d0..000000000 --- a/modules/adas/tools/fcw_train/fcw_train.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include - -#include -using std::string; - -#include -using std::vector; - -#include -using std::ifstream; -using std::getline; - -#include -using std::stringstream; - -#include -using std::cerr; -using std::endl; - -#include -using cv::Rect; -using cv::Size; -#include -using cv::imread; -#include -using cv::CommandLineParser; -using cv::FileStorage; -#include - -#include // std::time -#include // std::rand, std::srand - -#include - - -using cv::xobjdetect::ICFDetectorParams; -using cv::xobjdetect::ICFDetector; -using cv::xobjdetect::WaldBoost; -using cv::xobjdetect::WaldBoostParams; -using cv::Mat; - -static bool read_model_size(const char *str, int *rows, int *cols) -{ - int pos = 0; - if( sscanf(str, "%dx%d%n", rows, cols, &pos) != 2 || str[pos] != '\0' || - *rows <= 0 || *cols <= 0) - { - return false; - } - return true; -} - -static int randomPred (int i) { return std::rand()%i;} - -int main(int argc, char *argv[]) -{ - - const string keys = - "{help | | print this message}" - "{pos_path | pos | path to training object samples}" - "{bg_path | bg | path to background images}" - "{bg_per_image | 5 | number of windows to sample per bg image}" - "{feature_count | 10000 | number of features to generate}" - "{weak_count | 100 | number of weak classifiers in cascade}" - "{model_size | 40x40 | model size in pixels}" - "{model_filename | model.xml | filename for saving model}" - "{features_type | icf | features type, \"icf\" or \"acf\"}" - "{alpha | 0.02 | alpha value}" - "{is_grayscale | false | read the image as grayscale}" - "{use_fast_log | false | use fast log function}" - "{limit_ps | -1 | limit to positive samples (-1 means all)}" - "{limit_bg | -1 | limit to negative samples (-1 means all)}" - ; - - - CommandLineParser parser(argc, argv, keys); - parser.about("FCW trainer"); - - if( parser.has("help") || argc == 1) - { - parser.printMessage(); - return 0; - } - - string pos_path = parser.get("pos_path"); - string bg_path = parser.get("bg_path"); - string model_filename = parser.get("model_filename"); - - ICFDetectorParams params; - params.feature_count = parser.get("feature_count"); - params.weak_count = parser.get("weak_count"); - params.bg_per_image = parser.get("bg_per_image"); - params.features_type = parser.get("features_type"); - params.alpha = parser.get("alpha"); - params.is_grayscale = parser.get("is_grayscale"); - params.use_fast_log = parser.get("use_fast_log"); - - int limit_ps = parser.get("limit_ps"); - int limit_bg = parser.get("limit_bg"); - - string model_size = parser.get("model_size"); - if( !read_model_size(model_size.c_str(), ¶ms.model_n_rows, - ¶ms.model_n_cols) ) - { - cerr << "Error reading model size from `" << model_size << "`" << endl; - return 1; - } - - if( params.feature_count <= 0 ) - { - cerr << "feature_count must be positive number" << endl; - return 1; - } - - if( params.weak_count <= 0 ) - { - cerr << "weak_count must be positive number" << endl; - return 1; - } - - if( params.features_type != "icf" && params.features_type != "acf" ) - { - cerr << "features_type must be \"icf\" or \"acf\"" << endl; - return 1; - } - if( params.alpha <= 0 ) - { - cerr << "alpha must be positive float number" << endl; - return 1; - } - if( !parser.check() ) - { - parser.printErrors(); - return 1; - } - - std::vector pos_filenames; - glob(pos_path, pos_filenames); - - std::vector bg_filenames; - glob(bg_path, bg_filenames); - - if(limit_ps != -1 && (int)pos_filenames.size() > limit_ps) - pos_filenames.erase(pos_filenames.begin()+limit_ps, pos_filenames.end()); - if(limit_bg != -1 && (int)bg_filenames.size() > limit_bg) - bg_filenames.erase(bg_filenames.begin()+limit_bg, bg_filenames.end()); - - //random pick input images - bool random_shuffle = false; - if(random_shuffle) - { - std::srand ( unsigned ( std::time(0) ) ); - std::random_shuffle ( pos_filenames.begin(), pos_filenames.end(), randomPred ); - std::random_shuffle ( bg_filenames.begin(), bg_filenames.end(), randomPred ); - } - - int samples_size = (int)((params.bg_per_image * bg_filenames.size()) + pos_filenames.size()); - int features_size = params.feature_count; - int max_features_allowed = (int)(INT_MAX/(sizeof(int)* samples_size)); - int max_samples_allowed = (int)(INT_MAX/(sizeof(int)* features_size)); - int total_samples = (int)((params.bg_per_image * bg_filenames.size()) + pos_filenames.size()); - - - if(total_samples >max_samples_allowed) - { - CV_Error_(1, ("exceeded maximum number of samples. Maximum number of samples with %d features is %d, you have %d (%d positive samples + (%d bg * %d bg_per_image))\n",features_size,max_samples_allowed,total_samples,pos_filenames.size(),bg_filenames.size(),params.bg_per_image )); - } - - if(params.feature_count >max_features_allowed) - { - CV_Error_(1, ("exceeded maximum number of features. Maximum number of features with %d samples is %d, you have %d\n",samples_size,max_features_allowed, features_size )); - } - - std::cout<>). + * @param rvecs array of output rotation vectors (@sa Rodrigues) (e.g. std::vector>). * Each element in rvecs corresponds to the specific marker in imgPoints. - * @param tvecs array of output translation vectors (e.g. std::vector>). + * @param tvecs array of output translation vectors (e.g. std::vector>). * Each element in tvecs corresponds to the specific marker in imgPoints. * * This function receives the detected markers and returns their pose estimation respect to diff --git a/modules/aruco/include/opencv2/aruco/dictionary.hpp b/modules/aruco/include/opencv2/aruco/dictionary.hpp index 36a3a27ad..52bcf6772 100644 --- a/modules/aruco/include/opencv2/aruco/dictionary.hpp +++ b/modules/aruco/include/opencv2/aruco/dictionary.hpp @@ -51,6 +51,12 @@ namespace aruco { /** * @brief Dictionary/Set of markers. It contains the inner codification * + * bytesList contains the marker codewords where + * - bytesList.rows is the dictionary size + * - each marker is encoded using `nbytes = ceil(markerSize*markerSize/8.)` + * - each row contains all 4 rotations of the marker, so its length is `4*nbytes` + * + * `bytesList.ptr(i)[k*nbytes + j]` is then the j-th byte of i-th marker, in its k-th rotation. */ class CV_EXPORTS Dictionary { @@ -62,8 +68,7 @@ class CV_EXPORTS Dictionary { /** */ - Dictionary(const unsigned char *bytes = 0, int _markerSize = 0, int dictsize = 0, - int _maxcorr = 0); + Dictionary(const Mat &_bytesList = Mat(), int _markerSize = 0, int _maxcorr = 0); diff --git a/modules/aruco/samples/detect_board.cpp b/modules/aruco/samples/detect_board.cpp index 57288bdaa..73c9da436 100644 --- a/modules/aruco/samples/detect_board.cpp +++ b/modules/aruco/samples/detect_board.cpp @@ -207,7 +207,7 @@ int main(int argc, char *argv[]) { vector< int > ids; vector< vector< Point2f > > corners, rejected; - Mat rvec, tvec; + Vec3d rvec, tvec; // detect markers aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected); diff --git a/modules/aruco/samples/detect_board_charuco.cpp b/modules/aruco/samples/detect_board_charuco.cpp index a8fe581c5..36524bd01 100644 --- a/modules/aruco/samples/detect_board_charuco.cpp +++ b/modules/aruco/samples/detect_board_charuco.cpp @@ -204,7 +204,7 @@ int main(int argc, char *argv[]) { vector< int > markerIds, charucoIds; vector< vector< Point2f > > markerCorners, rejectedMarkers; vector< Point2f > charucoCorners; - Mat rvec, tvec; + Vec3d rvec, tvec; // detect markers aruco::detectMarkers(image, dictionary, markerCorners, markerIds, detectorParams, diff --git a/modules/aruco/samples/detect_diamonds.cpp b/modules/aruco/samples/detect_diamonds.cpp index e1aa3a06c..f350b2f6a 100644 --- a/modules/aruco/samples/detect_diamonds.cpp +++ b/modules/aruco/samples/detect_diamonds.cpp @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) { vector< int > markerIds; vector< Vec4i > diamondIds; vector< vector< Point2f > > markerCorners, rejectedMarkers, diamondCorners; - vector< Mat > rvecs, tvecs; + vector< Vec3d > rvecs, tvecs; // detect markers aruco::detectMarkers(image, dictionary, markerCorners, markerIds, detectorParams, diff --git a/modules/aruco/samples/detect_markers.cpp b/modules/aruco/samples/detect_markers.cpp index 052db1ca5..ffae81312 100644 --- a/modules/aruco/samples/detect_markers.cpp +++ b/modules/aruco/samples/detect_markers.cpp @@ -194,7 +194,7 @@ int main(int argc, char *argv[]) { vector< int > ids; vector< vector< Point2f > > corners, rejected; - vector< Mat > rvecs, tvecs; + vector< Vec3d > rvecs, tvecs; // detect markers and estimate pose aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected); diff --git a/modules/aruco/src/aruco.cpp b/modules/aruco/src/aruco.cpp index 89563cc94..17e49776c 100644 --- a/modules/aruco/src/aruco.cpp +++ b/modules/aruco/src/aruco.cpp @@ -71,7 +71,7 @@ DetectorParameters::DetectorParameters() markerBorderBits(1), perspectiveRemovePixelPerCell(4), perspectiveRemoveIgnoredMarginPerCell(0.13), - maxErroneousBitsInBorderRate(0.5), + maxErroneousBitsInBorderRate(0.35), minOtsuStdDev(5.0), errorCorrectionRate(0.6) {} @@ -123,7 +123,7 @@ static void _findMarkerContours(InputArray _in, vector< vector< Point2f > > &can Mat contoursImg; _in.getMat().copyTo(contoursImg); vector< vector< Point > > contours; - findContours(contoursImg, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); + findContours(contoursImg, contours, RETR_LIST, CHAIN_APPROX_NONE); // now filter list of contours for(unsigned int i = 0; i < contours.size(); i++) { // check perimeter @@ -315,57 +315,31 @@ static void _detectInitialCandidates(const Mat &grey, vector< vector< Point2f > int nScales = (params.adaptiveThreshWinSizeMax - params.adaptiveThreshWinSizeMin) / params.adaptiveThreshWinSizeStep + 1; - // if only one scale - if(nScales == 1) { - int scale = params.adaptiveThreshWinSizeMin; - // treshold - Mat thresh; - _threshold(grey, thresh, scale, params.adaptiveThreshConstant); - - // detect rectangles - vector< vector< Point2f > > currentCandidates; - vector< vector< Point > > currentContours; - _findMarkerContours(thresh, currentCandidates, currentContours, - params.minMarkerPerimeterRate, params.maxMarkerPerimeterRate, - params.polygonalApproxAccuracyRate, params.minCornerDistanceRate, - params.minDistanceToBorder); - - // join candidates - for(unsigned int i = 0; i < currentCandidates.size(); i++) { - candidates.push_back(currentCandidates[i]); - contours.push_back(currentContours[i]); - } - } - - // if more than one scale, do it in parallel - else { - - vector< vector< vector< Point2f > > > candidatesArrays(nScales); - vector< vector< vector< Point > > > contoursArrays(nScales); - - ////for each value in the interval of thresholding window sizes - // for(int i = 0; i < nScales; i++) { - // int currScale = params.adaptiveThreshWinSizeMin + i*params.adaptiveThreshWinSizeStep; - // // treshold - // Mat thresh; - // _threshold(grey, thresh, currScale, params.adaptiveThreshConstant); - // // detect rectangles - // _findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i], - // params.minMarkerPerimeterRate, - // params.maxMarkerPerimeterRate, params.polygonalApproxAccuracyRate, - // params.minCornerDistance, params.minDistanceToBorder); - //} + vector< vector< vector< Point2f > > > candidatesArrays(nScales); + vector< vector< vector< Point > > > contoursArrays(nScales); + + ////for each value in the interval of thresholding window sizes + // for(int i = 0; i < nScales; i++) { + // int currScale = params.adaptiveThreshWinSizeMin + i*params.adaptiveThreshWinSizeStep; + // // treshold + // Mat thresh; + // _threshold(grey, thresh, currScale, params.adaptiveThreshConstant); + // // detect rectangles + // _findMarkerContours(thresh, candidatesArrays[i], contoursArrays[i], + // params.minMarkerPerimeterRate, + // params.maxMarkerPerimeterRate, params.polygonalApproxAccuracyRate, + // params.minCornerDistance, params.minDistanceToBorder); + //} - // this is the parallel call for the previous commented loop (result is equivalent) - parallel_for_(Range(0, nScales), DetectInitialCandidatesParallel(&grey, &candidatesArrays, - &contoursArrays, ¶ms)); - - // join candidates - for(int i = 0; i < nScales; i++) { - for(unsigned int j = 0; j < candidatesArrays[i].size(); j++) { - candidates.push_back(candidatesArrays[i][j]); - contours.push_back(contoursArrays[i][j]); - } + // this is the parallel call for the previous commented loop (result is equivalent) + parallel_for_(Range(0, nScales), DetectInitialCandidatesParallel(&grey, &candidatesArrays, + &contoursArrays, ¶ms)); + + // join candidates + for(int i = 0; i < nScales; i++) { + for(unsigned int j = 0; j < candidatesArrays[i].size(); j++) { + candidates.push_back(candidatesArrays[i][j]); + contours.push_back(contoursArrays[i][j]); } } } @@ -847,9 +821,9 @@ void detectMarkers(InputArray _image, Dictionary dictionary, OutputArrayOfArrays */ class SinglePoseEstimationParallel : public ParallelLoopBody { public: - SinglePoseEstimationParallel(Mat *_markerObjPoints, InputArrayOfArrays _corners, + SinglePoseEstimationParallel(Mat& _markerObjPoints, InputArrayOfArrays _corners, InputArray _cameraMatrix, InputArray _distCoeffs, - OutputArrayOfArrays _rvecs, OutputArrayOfArrays _tvecs) + Mat& _rvecs, Mat& _tvecs) : markerObjPoints(_markerObjPoints), corners(_corners), cameraMatrix(_cameraMatrix), distCoeffs(_distCoeffs), rvecs(_rvecs), tvecs(_tvecs) {} @@ -858,18 +832,18 @@ class SinglePoseEstimationParallel : public ParallelLoopBody { const int end = range.end; for(int i = begin; i < end; i++) { - solvePnP(*markerObjPoints, corners.getMat(i), cameraMatrix, distCoeffs, rvecs.getMat(i), - tvecs.getMat(i)); + solvePnP(markerObjPoints, corners.getMat(i), cameraMatrix, distCoeffs, + rvecs.at(0, i), tvecs.at(0, i)); } } private: SinglePoseEstimationParallel &operator=(const SinglePoseEstimationParallel &); // to quiet MSVC - Mat *markerObjPoints; + Mat& markerObjPoints; InputArrayOfArrays corners; InputArray cameraMatrix, distCoeffs; - OutputArrayOfArrays rvecs, tvecs; + Mat& rvecs, tvecs; }; @@ -886,13 +860,10 @@ void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength, Mat markerObjPoints; _getSingleMarkerObjectPoints(markerLength, markerObjPoints); int nMarkers = (int)_corners.total(); - _rvecs.create(nMarkers, 1, CV_32FC1); - _tvecs.create(nMarkers, 1, CV_32FC1); + _rvecs.create(nMarkers, 1, CV_64FC3); + _tvecs.create(nMarkers, 1, CV_64FC3); - for(int i = 0; i < nMarkers; i++) { - _rvecs.create(3, 1, CV_64FC1, i, true); - _tvecs.create(3, 1, CV_64FC1, i, true); - } + Mat rvecs = _rvecs.getMat(), tvecs = _tvecs.getMat(); //// for each marker, calculate its pose // for (int i = 0; i < nMarkers; i++) { @@ -902,8 +873,8 @@ void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength, // this is the parallel call for the previous commented loop (result is equivalent) parallel_for_(Range(0, nMarkers), - SinglePoseEstimationParallel(&markerObjPoints, _corners, _cameraMatrix, - _distCoeffs, _rvecs, _tvecs)); + SinglePoseEstimationParallel(markerObjPoints, _corners, _cameraMatrix, + _distCoeffs, rvecs, tvecs)); } diff --git a/modules/aruco/src/dictionary.cpp b/modules/aruco/src/dictionary.cpp index f286787db..c1d9d68e0 100644 --- a/modules/aruco/src/dictionary.cpp +++ b/modules/aruco/src/dictionary.cpp @@ -38,9 +38,9 @@ the use of this software, even if advised of the possibility of such damage. #include "precomp.hpp" #include "opencv2/aruco/dictionary.hpp" -#include "predefined_dictionaries.cpp" #include #include +#include "predefined_dictionaries.hpp" namespace cv { @@ -48,41 +48,12 @@ namespace aruco { using namespace std; - - -/** - * Hamming weight look up table from 0 to 255 - */ -const unsigned char hammingWeightLUT[] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 -}; - - - /** */ -Dictionary::Dictionary(const unsigned char *bytes, int _markerSize, int dictsize, int _maxcorr) { +Dictionary::Dictionary(const Mat &_bytesList, int _markerSize, int _maxcorr) { markerSize = _markerSize; maxCorrectionBits = _maxcorr; - int nbytes = (markerSize * markerSize) / 8; - if((markerSize * markerSize) % 8 != 0) nbytes++; - - // save bytes in internal format - // bytesList.at(i, j)[k] is j-th byte of i-th marker, in its k-th rotation - bytesList = Mat(dictsize, nbytes, CV_8UC4); - for(int i = 0; i < dictsize; i++) { - for(int j = 0; j < nbytes; j++) { - for(int k = 0; k < 4; k++) - bytesList.at< Vec4b >(i, j)[k] = bytes[i * (4 * nbytes) + k * nbytes + j]; - } - } + bytesList = _bytesList; } @@ -106,13 +77,10 @@ bool Dictionary::identify(const Mat &onlyBits, int &idx, int &rotation, int currentMinDistance = markerSize * markerSize + 1; int currentRotation = -1; for(unsigned int r = 0; r < 4; r++) { - int currentHamming = 0; - // for each byte, calculate XOR result and then sum the Hamming weight from the LUT - for(unsigned int b = 0; b < candidateBytes.total(); b++) { - unsigned char xorRes = - bytesList.ptr< Vec4b >(m)[b][r] ^ candidateBytes.ptr< Vec4b >(0)[b][0]; - currentHamming += hammingWeightLUT[xorRes]; - } + int currentHamming = hal::normHamming( + bytesList.ptr(m)+r*candidateBytes.cols, + candidateBytes.ptr(), + candidateBytes.cols); if(currentHamming < currentMinDistance) { currentMinDistance = currentHamming; @@ -128,10 +96,7 @@ bool Dictionary::identify(const Mat &onlyBits, int &idx, int &rotation, } } - if(idx != -1) - return true; - else - return false; + return idx != -1; } @@ -147,12 +112,10 @@ int Dictionary::getDistanceToId(InputArray bits, int id, bool allRotations) cons Mat candidateBytes = getByteListFromBits(bits.getMat()); int currentMinDistance = int(bits.total() * bits.total()); for(unsigned int r = 0; r < nRotations; r++) { - int currentHamming = 0; - for(unsigned int b = 0; b < candidateBytes.total(); b++) { - unsigned char xorRes = - bytesList.ptr< Vec4b >(id)[b][r] ^ candidateBytes.ptr< Vec4b >(0)[b][0]; - currentHamming += hammingWeightLUT[xorRes]; - } + int currentHamming = hal::normHamming( + bytesList.ptr(id) + r*candidateBytes.cols, + candidateBytes.ptr(), + candidateBytes.cols); if(currentHamming < currentMinDistance) { currentMinDistance = currentHamming; @@ -195,33 +158,31 @@ void Dictionary::drawMarker(int id, int sidePixels, OutputArray _img, int border * @brief Transform matrix of bits to list of bytes in the 4 rotations */ Mat Dictionary::getByteListFromBits(const Mat &bits) { - - int nbytes = (bits.cols * bits.rows) / 8; - if((bits.cols * bits.rows) % 8 != 0) nbytes++; + // integer ceil + int nbytes = (bits.cols * bits.rows + 8 - 1) / 8; Mat candidateByteList(1, nbytes, CV_8UC4, Scalar::all(0)); unsigned char currentBit = 0; int currentByte = 0; + + // the 4 rotations + uchar* rot0 = candidateByteList.ptr(); + uchar* rot1 = candidateByteList.ptr() + 1*nbytes; + uchar* rot2 = candidateByteList.ptr() + 2*nbytes; + uchar* rot3 = candidateByteList.ptr() + 3*nbytes; + for(int row = 0; row < bits.rows; row++) { for(int col = 0; col < bits.cols; col++) { // circular shift - candidateByteList.ptr< Vec4b >(0)[currentByte][0] = - candidateByteList.ptr< Vec4b >(0)[currentByte][0] << 1; - candidateByteList.ptr< Vec4b >(0)[currentByte][1] = - candidateByteList.ptr< Vec4b >(0)[currentByte][1] << 1; - candidateByteList.ptr< Vec4b >(0)[currentByte][2] = - candidateByteList.ptr< Vec4b >(0)[currentByte][2] << 1; - candidateByteList.ptr< Vec4b >(0)[currentByte][3] = - candidateByteList.ptr< Vec4b >(0)[currentByte][3] << 1; - // increment if bit is 1 - if(bits.at< unsigned char >(row, col)) - candidateByteList.ptr< Vec4b >(0)[currentByte][0]++; - if(bits.at< unsigned char >(col, bits.cols - 1 - row)) - candidateByteList.ptr< Vec4b >(0)[currentByte][1]++; - if(bits.at< unsigned char >(bits.rows - 1 - row, bits.cols - 1 - col)) - candidateByteList.ptr< Vec4b >(0)[currentByte][2]++; - if(bits.at< unsigned char >(bits.rows - 1 - col, row)) - candidateByteList.ptr< Vec4b >(0)[currentByte][3]++; + rot0[currentByte] <<= 1; + rot1[currentByte] <<= 1; + rot2[currentByte] <<= 1; + rot3[currentByte] <<= 1; + // set bit + rot0[currentByte] |= bits.at(row, col); + rot1[currentByte] |= bits.at(col, bits.cols - 1 - row); + rot2[currentByte] |= bits.at(bits.rows - 1 - row, bits.cols - 1 - col); + rot3[currentByte] |= bits.at(bits.rows - 1 - col, row); currentBit++; if(currentBit == 8) { // next byte @@ -247,7 +208,7 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) { unsigned char base2List[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; int currentByteIdx = 0; // we only need the bytes in normal rotation - unsigned char currentByte = byteList.ptr< Vec4b >(0)[0][0]; + unsigned char currentByte = byteList.ptr()[0]; int currentBit = 0; for(int row = 0; row < bits.rows; row++) { for(int col = 0; col < bits.cols; col++) { @@ -258,7 +219,7 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) { currentBit++; if(currentBit == 8) { currentByteIdx++; - currentByte = byteList.ptr< Vec4b >(0)[currentByteIdx][0]; + currentByte = byteList.ptr()[currentByteIdx]; // if not enough bits for one more byte, we are in the end // update bit position accordingly if(8 * (currentByteIdx + 1) > (int)bits.total()) @@ -275,27 +236,27 @@ Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) { // DictionaryData constructors calls -const Dictionary DICT_ARUCO_DATA = Dictionary(&(DICT_ARUCO_BYTES[0][0][0]), 5, 1024, 1); +const Dictionary DICT_ARUCO_DATA = Dictionary(Mat(1024, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_ARUCO_BYTES), 5, 0); -const Dictionary DICT_4X4_50_DATA = Dictionary(&(DICT_4X4_1000_BYTES[0][0][0]), 4, 50, 1); -const Dictionary DICT_4X4_100_DATA = Dictionary(&(DICT_4X4_1000_BYTES[0][0][0]), 4, 100, 1); -const Dictionary DICT_4X4_250_DATA = Dictionary(&(DICT_4X4_1000_BYTES[0][0][0]), 4, 250, 1); -const Dictionary DICT_4X4_1000_DATA = Dictionary(&(DICT_4X4_1000_BYTES[0][0][0]), 4, 1000, 0); +const Dictionary DICT_4X4_50_DATA = Dictionary(Mat(50, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1); +const Dictionary DICT_4X4_100_DATA = Dictionary(Mat(100, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1); +const Dictionary DICT_4X4_250_DATA = Dictionary(Mat(250, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1); +const Dictionary DICT_4X4_1000_DATA = Dictionary(Mat(1000, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 0); -const Dictionary DICT_5X5_50_DATA = Dictionary(&(DICT_5X5_1000_BYTES[0][0][0]), 5, 50, 3); -const Dictionary DICT_5X5_100_DATA = Dictionary(&(DICT_5X5_1000_BYTES[0][0][0]), 5, 100, 3); -const Dictionary DICT_5X5_250_DATA = Dictionary(&(DICT_5X5_1000_BYTES[0][0][0]), 5, 250, 2); -const Dictionary DICT_5X5_1000_DATA = Dictionary(&(DICT_5X5_1000_BYTES[0][0][0]), 5, 1000, 2); +const Dictionary DICT_5X5_50_DATA = Dictionary(Mat(50, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 3); +const Dictionary DICT_5X5_100_DATA = Dictionary(Mat(100, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 3); +const Dictionary DICT_5X5_250_DATA = Dictionary(Mat(250, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 2); +const Dictionary DICT_5X5_1000_DATA = Dictionary(Mat(1000, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 2); -const Dictionary DICT_6X6_50_DATA = Dictionary(&(DICT_6X6_1000_BYTES[0][0][0]), 6, 50, 6); -const Dictionary DICT_6X6_100_DATA = Dictionary(&(DICT_6X6_1000_BYTES[0][0][0]), 6, 100, 5); -const Dictionary DICT_6X6_250_DATA = Dictionary(&(DICT_6X6_1000_BYTES[0][0][0]), 6, 250, 5); -const Dictionary DICT_6X6_1000_DATA = Dictionary(&(DICT_6X6_1000_BYTES[0][0][0]), 6, 1000, 4); +const Dictionary DICT_6X6_50_DATA = Dictionary(Mat(50, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 6); +const Dictionary DICT_6X6_100_DATA = Dictionary(Mat(100, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 5); +const Dictionary DICT_6X6_250_DATA = Dictionary(Mat(250, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 5); +const Dictionary DICT_6X6_1000_DATA = Dictionary(Mat(1000, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 4); -const Dictionary DICT_7X7_50_DATA = Dictionary(&(DICT_7X7_1000_BYTES[0][0][0]), 7, 50, 9); -const Dictionary DICT_7X7_100_DATA = Dictionary(&(DICT_7X7_1000_BYTES[0][0][0]), 7, 100, 8); -const Dictionary DICT_7X7_250_DATA = Dictionary(&(DICT_7X7_1000_BYTES[0][0][0]), 7, 250, 8); -const Dictionary DICT_7X7_1000_DATA = Dictionary(&(DICT_7X7_1000_BYTES[0][0][0]), 7, 1000, 6); +const Dictionary DICT_7X7_50_DATA = Dictionary(Mat(50, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 9); +const Dictionary DICT_7X7_100_DATA = Dictionary(Mat(100, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8); +const Dictionary DICT_7X7_250_DATA = Dictionary(Mat(250, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8); +const Dictionary DICT_7X7_1000_DATA = Dictionary(Mat(1000, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 6); const Dictionary &getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) { @@ -369,12 +330,8 @@ static Mat _generateRandomMarker(int markerSize) { static int _getSelfDistance(const Mat &marker) { Mat bytes = Dictionary::getByteListFromBits(marker); int minHamming = (int)marker.total() + 1; - for(int i = 1; i < 4; i++) { - int currentHamming = 0; - for(int j = 0; j < bytes.cols; j++) { - unsigned char xorRes = bytes.ptr< Vec4b >()[j][0] ^ bytes.ptr< Vec4b >()[j][i]; - currentHamming += hammingWeightLUT[xorRes]; - } + for(int r = 1; r < 4; r++) { + int currentHamming = hal::normHamming(bytes.ptr(), bytes.ptr() + bytes.cols*r, bytes.cols); if(currentHamming < minHamming) minHamming = currentHamming; } return minHamming; diff --git a/modules/aruco/src/predefined_dictionaries.cpp b/modules/aruco/src/predefined_dictionaries.hpp similarity index 99% rename from modules/aruco/src/predefined_dictionaries.cpp rename to modules/aruco/src/predefined_dictionaries.hpp index 421ee4495..6abc4a5f9 100644 --- a/modules/aruco/src/predefined_dictionaries.cpp +++ b/modules/aruco/src/predefined_dictionaries.hpp @@ -36,8 +36,7 @@ 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. */ -namespace cv { -namespace aruco { +namespace { @@ -53,7 +52,7 @@ namespace aruco { * Each rotation implies a 90 degree rotation of the marker in anticlockwise direction. */ -const unsigned char DICT_ARUCO_BYTES[][4][4] = { +static unsigned char DICT_ARUCO_BYTES[][4][4] = { { { 132, 33, 8, 0 }, { 0, 0, 15, 1 }, { 8, 66, 16, 1 }, @@ -4152,7 +4151,7 @@ const unsigned char DICT_ARUCO_BYTES[][4][4] = { { 7, 255, 240, 0 }, }, }; -const unsigned char DICT_4X4_1000_BYTES[][4][2] = +static unsigned char DICT_4X4_1000_BYTES[][4][2] = { { { 181, 50 }, { 235, 72 }, { 76, 173 }, @@ -8154,7 +8153,7 @@ const unsigned char DICT_4X4_1000_BYTES[][4][2] = { 253, 239 }, { 219, 255 }, }, }; -const unsigned char DICT_5X5_1000_BYTES[][4][4] = +static unsigned char DICT_5X5_1000_BYTES[][4][4] = { { { 162, 217, 94, 0 }, { 82, 46, 217, 1 }, { 61, 77, 162, 1 }, @@ -12156,7 +12155,7 @@ const unsigned char DICT_5X5_1000_BYTES[][4][4] = { 184, 73, 239, 1 }, { 204, 238, 57, 1 }, }, }; -const unsigned char DICT_6X6_1000_BYTES[][4][5] = +static unsigned char DICT_6X6_1000_BYTES[][4][5] = { { { 30, 61, 216, 42, 6 }, { 227, 186, 70, 49, 9 }, { 101, 65, 187, 199, 8 }, @@ -16158,7 +16157,7 @@ const unsigned char DICT_6X6_1000_BYTES[][4][5] = { 255, 135, 198, 183, 15 }, { 174, 219, 251, 231, 3 }, }, }; -const unsigned char DICT_7X7_1000_BYTES[][4][7] = +static unsigned char DICT_7X7_1000_BYTES[][4][7] = { { { 221, 92, 108, 165, 202, 10, 1 }, { 99, 179, 173, 228, 49, 180, 0 }, { 168, 41, 210, 155, 29, 93, 1 }, @@ -20160,4 +20159,3 @@ const unsigned char DICT_7X7_1000_BYTES[][4][7] = { 252, 176, 35, 180, 179, 243, 1 }, { 31, 47, 190, 169, 27, 97, 1 }, }, }; } -} diff --git a/modules/aruco/test/test_charucodetection.cpp b/modules/aruco/test/test_charucodetection.cpp index df63e4ee1..c8bbc914c 100644 --- a/modules/aruco/test/test_charucodetection.cpp +++ b/modules/aruco/test/test_charucodetection.cpp @@ -515,7 +515,7 @@ void CV_CharucoDiamondDetection::run(int) { } // estimate diamond pose - vector< Mat > estimatedRvec, estimatedTvec; + vector< Vec3d > estimatedRvec, estimatedTvec; aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, cameraMatrix, distCoeffs, estimatedRvec, estimatedTvec); diff --git a/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown b/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown index e17c3d9bc..279bc3244 100644 --- a/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown +++ b/modules/aruco/tutorials/aruco_board_detection/aruco_board_detection.markdown @@ -64,7 +64,7 @@ The aruco module provides a specific function, ```estimatePoseBoard()```, to per cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds); // if at least one marker detected if(markerIds.size() > 0) { - cv::Mat rvec, tvec; + cv::Vec3d rvec, tvec; int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec); } ``` @@ -181,7 +181,7 @@ Finally, a full example of board detection: if (ids.size() > 0) { cv::aruco::drawDetectedMarkers(imageCopy, corners, ids); - cv::Mat rvec, tvec; + cv::Vec3d rvec, tvec; int valid = estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec); // if at least one board marker detected diff --git a/modules/aruco/tutorials/aruco_detection/aruco_detection.markdown b/modules/aruco/tutorials/aruco_detection/aruco_detection.markdown index a63538352..c3e197f7e 100644 --- a/modules/aruco/tutorials/aruco_detection/aruco_detection.markdown +++ b/modules/aruco/tutorials/aruco_detection/aruco_detection.markdown @@ -256,7 +256,7 @@ The aruco module provides a function to estimate the poses of all the detected m ``` c++ Mat cameraMatrix, distCoeffs; ... - vector< Mat > rvecs, tvecs; + vector< Vec3d > rvecs, tvecs; cv::aruco::estimatePoseSingleMarkers(corners, 0.05, cameraMatrix, distCoeffs, rvecs, tvecs); ``` @@ -665,7 +665,7 @@ The bits of the marker border should be black. This parameter specifies the allo bits in the border, i.e. the maximum number of white bits in the border. It is represented relative to the total number of bits in the marker. -Default value: 0.5 +Default value: 0.35 - ```double errorCorrectionRate``` diff --git a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown index 8affec463..65ffefc4f 100644 --- a/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown +++ b/modules/aruco/tutorials/charuco_detection/charuco_detection.markdown @@ -294,7 +294,7 @@ A full example of ChArUco detection with pose estimation: // if at least one charuco corner detected if(charucoIds.size() > 0) { cv::aruco::drawDetectedCornersCharuco(imageCopy, charucoCorners, charucoIds, cv::Scalar(255, 0, 0)); - cv::Mat rvec, tvec; + cv::Vec3d rvec, tvec; bool valid = cv::aruco::estimatePoseCharucoBoard(charucoCorners, charucoIds, board, cameraMatrix, distCoeffs, rvec, tvec); // if charuco pose is valid if(valid) diff --git a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown index 0c5936611..e1212f8fc 100644 --- a/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown +++ b/modules/aruco/tutorials/charuco_diamond_detection/charuco_diamond_detection.markdown @@ -133,7 +133,7 @@ i.e. using the ```estimatePoseSingleMarkers()``` function. For instance: cv::aruco::detectCharucoDiamond(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds); // estimate poses - std::vector rvecs, tvecs; + std::vector rvecs, tvecs; cv::aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, camMatrix, distCoeffs, rvecs, tvecs); // draw axis diff --git a/modules/bioinspired/src/transientareassegmentationmodule.cpp b/modules/bioinspired/src/transientareassegmentationmodule.cpp index 90da718a3..185cc11f5 100644 --- a/modules/bioinspired/src/transientareassegmentationmodule.cpp +++ b/modules/bioinspired/src/transientareassegmentationmodule.cpp @@ -454,7 +454,7 @@ void TransientAreasSegmentationModuleImpl::_run(const std::valarray &inpu // first square the input in order to increase the signal to noise ratio // get motion local energy - _squaringSpatiotemporalLPfilter(&inputToSegment[channelIndex*getNBpixels()], &_localMotion[0]); + _squaringSpatiotemporalLPfilter(&const_cast&>(inputToSegment)[channelIndex*getNBpixels()], &_localMotion[0]); // second low pass filter: access to the neighborhood motion energy _spatiotemporalLPfilter(&_localMotion[0], &_neighborhoodMotion[0], 1); diff --git a/modules/ccalib/README.md b/modules/ccalib/README.md index 5b6289961..9d6d2ee6c 100644 --- a/modules/ccalib/README.md +++ b/modules/ccalib/README.md @@ -1,2 +1,6 @@ Custom Calibration Pattern for 3D reconstruction ================================================ +1. Custom calibration pattern for 3D reconstruction +2. Omnidirectional camera calibration +3. random pattern calibration object +4. multi-camera calibration \ No newline at end of file diff --git a/modules/ccalib/include/opencv2/ccalib/multicalib.hpp b/modules/ccalib/include/opencv2/ccalib/multicalib.hpp new file mode 100644 index 000000000..686d7a52b --- /dev/null +++ b/modules/ccalib/include/opencv2/ccalib/multicalib.hpp @@ -0,0 +1,212 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_MULTICAMERACALIBRATION_HPP__ +#define __OPENCV_MULTICAMERACALIBRATION_HPP__ + +#include "opencv2/ccalib/randpattern.hpp" +#include "opencv2/ccalib/omnidir.hpp" +#include +#include + +namespace cv { namespace multicalib { + +//! @addtogroup ccalib +//! @{ + +#define HEAD -1 +#define INVALID -2 + +/** @brief Class for multiple camera calibration that supports pinhole camera and omnidirection camera. +For omnidirectional camera model, please refer to omnidir.hpp in ccalib module. +It first calibrate each camera individually, then a bundle adjustment like optimization is applied to +refine extrinsic parameters. So far, it only support "random" pattern for calibration, +see randomPattern.hpp in ccalib module for details. +Images that are used should be named by "cameraIdx-timestamp.*", several images with the same timestamp +means that they are the same pattern that are photographed. cameraIdx should start from 0. + +For more details, please refer to paper + B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System + Calibration Toolbox Using A Feature Descriptor-Based Calibration + Pattern", in IROS 2013. +*/ + +class CV_EXPORTS MultiCameraCalibration +{ +public: + enum { + PINHOLE, + OMNIDIRECTIONAL + //FISHEYE + }; + + // an edge connects a camera and pattern + struct edge + { + int cameraVertex; // vertex index for camera in this edge + int photoVertex; // vertex index for pattern in this edge + int photoIndex; // photo index among photos for this camera + Mat transform; // transform from pattern to camera + + edge(int cv, int pv, int pi, Mat trans) + { + cameraVertex = cv; + photoVertex = pv; + photoIndex = pi; + transform = trans; + } + }; + + struct vertex + { + Mat pose; // relative pose to the first camera. For camera vertex, it is the + // transform from the first camera to this camera, for pattern vertex, + // it is the transform from pattern to the first camera + int timestamp; // timestamp of photo, only available for photo vertex + + vertex(Mat po, int ts) + { + pose = po; + timestamp = ts; + } + + vertex() + { + pose = Mat::eye(4, 4, CV_32F); + timestamp = -1; + } + }; + /* @brief Constructor + @param cameraType camera type, PINHOLE or OMNIDIRECTIONAL + @param nCameras number of cameras + @fileName filename of string list that are used for calibration, the file is generated + by imagelist_creator from OpenCv samples. The first one in the list is the pattern filename. + @patternWidth the physical width of pattern, in user defined unit. + @patternHeight the physical height of pattern, in user defined unit. + @showExtration whether show extracted features and feature filtering. + @nMiniMatches minimal number of matched features for a frame. + @flags Calibration flags + @criteria optimization stopping criteria. + @detector feature detector that detect feature points in pattern and images. + @descriptor feature descriptor. + @matcher feature matcher. + */ + MultiCameraCalibration(int cameraType, int nCameras, const std::string& fileName, float patternWidth, + float patternHeight, int verbose = 0, int showExtration = 0, int nMiniMatches = 20, int flags = 0, + TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 200, 1e-7), + Ptr detector = AKAZE::create(AKAZE::DESCRIPTOR_MLDB, 0, 3, 0.006f), + Ptr descriptor = AKAZE::create(AKAZE::DESCRIPTOR_MLDB,0, 3, 0.006f), + Ptr matcher = DescriptorMatcher::create("BruteForce-L1")); + + /* @brief load images + */ + void loadImages(); + + /* @brief initialize multiple camera calibration. It calibrates each camera individually. + */ + void initialize(); + + /* @brief optimization extrinsic parameters + */ + double optimizeExtrinsics(); + + /* @brief run multi-camera camera calibration, it runs loadImage(), initialize() and optimizeExtrinsics() + */ + double run(); + + /* @brief write camera parameters to file. + */ + void writeParameters(const std::string& filename); + +private: + std::vector readStringList(); + + int getPhotoVertex(int timestamp); + + void graphTraverse(const Mat& G, int begin, std::vector& order, std::vector& pre); + + void findRowNonZero(const Mat& row, Mat& idx); + + void computeJacobianExtrinsic(const Mat& extrinsicParams, Mat& JTJ_inv, Mat& JTE); + + void computePhotoCameraJacobian(const Mat& rvecPhoto, const Mat& tvecPhoto, const Mat& rvecCamera, + const Mat& tvecCamera, Mat& rvecTran, Mat& tvecTran, const Mat& objectPoints, const Mat& imagePoints, const Mat& K, + const Mat& distort, const Mat& xi, Mat& jacobianPhoto, Mat& jacobianCamera, Mat& E); + + void compose_motion(InputArray _om1, InputArray _T1, InputArray _om2, InputArray _T2, Mat& om3, Mat& T3, Mat& dom3dom1, + Mat& dom3dT1, Mat& dom3dom2, Mat& dom3dT2, Mat& dT3dom1, Mat& dT3dT1, Mat& dT3dom2, Mat& dT3dT2); + + void JRodriguesMatlab(const Mat& src, Mat& dst); + void dAB(InputArray A, InputArray B, OutputArray dABdA, OutputArray dABdB); + + double computeProjectError(Mat& parameters); + + void vector2parameters(const Mat& parameters, std::vector& rvecVertex, std::vector& tvecVertexs); + void parameters2vector(const std::vector& rvecVertex, const std::vector& tvecVertex, Mat& parameters); + + int _camType; //PINHOLE, FISHEYE or OMNIDIRECTIONAL + int _nCamera; + int _nMiniMatches; + int _flags; + int _verbose; + double _error; + float _patternWidth, _patternHeight; + TermCriteria _criteria; + std::string _filename; + int _showExtraction; + Ptr _detector; + Ptr _descriptor; + Ptr _matcher; + + std::vector _edgeList; + std::vector _vertexList; + std::vector > _objectPointsForEachCamera; + std::vector > _imagePointsForEachCamera; + std::vector _cameraMatrix; + std::vector _distortCoeffs; + std::vector _xi; + std::vector > _omEachCamera, _tEachCamera; +}; + +//! @} + +}} // namespace multicalib, cv +#endif \ No newline at end of file diff --git a/modules/ccalib/include/opencv2/ccalib/omnidir.hpp b/modules/ccalib/include/opencv2/ccalib/omnidir.hpp new file mode 100644 index 000000000..25c41bfa7 --- /dev/null +++ b/modules/ccalib/include/opencv2/ccalib/omnidir.hpp @@ -0,0 +1,312 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include +#include + +#ifndef __OPENCV_OMNIDIR_HPP__ +#define __OPENCV_OMNIDIR_HPP__ + +namespace cv +{ +namespace omnidir +{ + //! @addtogroup ccalib + //! @{ + + enum { + CALIB_USE_GUESS = 1, + CALIB_FIX_SKEW = 2, + CALIB_FIX_K1 = 4, + CALIB_FIX_K2 = 8, + CALIB_FIX_P1 = 16, + CALIB_FIX_P2 = 32, + CALIB_FIX_XI = 64, + CALIB_FIX_GAMMA = 128, + CALIB_FIX_CENTER = 256 + }; + + enum{ + RECTIFY_PERSPECTIVE = 1, + RECTIFY_CYLINDRICAL = 2, + RECTIFY_LONGLATI = 3, + RECTIFY_STEREOGRAPHIC = 4 + }; + + enum{ + XYZRGB = 1, + XYZ = 2 + }; +/** + * This module was accepted as a GSoC 2015 project for OpenCV, authored by + * Baisheng Lai, mentored by Bo Li. + */ + + /** @brief Projects points for omnidirectional camera using CMei's model + + @param objectPoints Object points in world coordinate, vector of vector of Vec3f or Mat of + 1xN/Nx1 3-channel of type CV_32F and N is the number of points. 64F is also acceptable. + @param imagePoints Output array of image points, vector of vector of Vec2f or + 1xN/Nx1 2-channel of type CV_32F. 64F is also acceptable. + @param rvec vector of rotation between world coordinate and camera coordinate, i.e., om + @param tvec vector of translation between pattern coordinate and camera coordinate + @param K Camera matrix \f$K = \vecthreethree{f_x}{s}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, p_1, p_2)\f$. + @param xi The parameter xi for CMei's model + @param jacobian Optional output 2Nx16 of type CV_64F jacobian matrix, contains the derivatives of + image pixel points wrt parameters including \f$om, T, f_x, f_y, s, c_x, c_y, xi, k_1, k_2, p_1, p_2\f$. + This matrix will be used in calibration by optimization. + + The function projects object 3D points of world coordinate to image pixels, parameter by intrinsic + and extrinsic parameters. Also, it optionally compute a by-product: the jacobian matrix containing + contains the derivatives of image pixel points wrt intrinsic and extrinsic parameters. + */ + CV_EXPORTS_W void projectPoints(InputArray objectPoints, OutputArray imagePoints, InputArray rvec, InputArray tvec, + InputArray K, double xi, InputArray D, OutputArray jacobian = noArray()); + + /** @brief Undistort 2D image points for omnidirectional camera using CMei's model + + @param distorted Array of distorted image points, vector of Vec2f + or 1xN/Nx1 2-channel Mat of type CV_32F, 64F depth is also acceptable + @param K Camera matrix \f$K = \vecthreethree{f_x}{s}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Distortion coefficients \f$(k_1, k_2, p_1, p_2)\f$. + @param xi The parameter xi for CMei's model + @param R Rotation trainsform between the original and object space : 3x3 1-channel, or vector: 3x1/1x3 + 1-channel or 1x1 3-channel + @param undistorted array of normalized object points, vector of Vec2f/Vec2d or 1xN/Nx1 2-channel Mat with the same + depth of distorted points. + */ + CV_EXPORTS_W void undistortPoints(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray xi, InputArray R); + + /** @brief Computes undistortion and rectification maps for omnidirectional camera image transform by a rotation R. + It output two maps that are used for cv::remap(). If D is empty then zero distortion is used, + if R or P is empty then identity matrices are used. + + @param K Camera matrix \f$K = \vecthreethree{f_x}{s}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$, with depth CV_32F or CV_64F + @param D Input vector of distortion coefficients \f$(k_1, k_2, p_1, p_2)\f$, with depth CV_32F or CV_64F + @param xi The parameter xi for CMei's model + @param R Rotation transform between the original and object space : 3x3 1-channel, or vector: 3x1/1x3, with depth CV_32F or CV_64F + @param P New camera matrix (3x3) or new projection matrix (3x4) + @param size Undistorted image size. + @param mltype Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() + for details. + @param map1 The first output map. + @param map2 The second output map. + @param flags Flags indicates the rectification type, RECTIFY_PERSPECTIVE, RECTIFY_CYLINDRICAL, RECTIFY_LONGLATI and RECTIFY_STEREOGRAPHIC + are supported. + */ + CV_EXPORTS_W void initUndistortRectifyMap(InputArray K, InputArray D, InputArray xi, InputArray R, InputArray P, const cv::Size& size, + int mltype, OutputArray map1, OutputArray map2, int flags); + + /** @brief Undistort omnidirectional images to perspective images + + @param distorted The input omnidirectional image. + @param undistorted The output undistorted image. + @param K Camera matrix \f$K = \vecthreethree{f_x}{s}{c_x}{0}{f_y}{c_y}{0}{0}{_1}\f$. + @param D Input vector of distortion coefficients \f$(k_1, k_2, p_1, p_2)\f$. + @param xi The parameter xi for CMei's model. + @param flags Flags indicates the rectification type, RECTIFY_PERSPECTIVE, RECTIFY_CYLINDRICAL, RECTIFY_LONGLATI and RECTIFY_STEREOGRAPHIC + @param Knew Camera matrix of the distorted image. If it is not assigned, it is just K. + @param new_size The new image size. By default, it is the size of distorted. + @param R Rotation matrix between the input and output images. By default, it is identity matrix. + */ + CV_EXPORTS_W void undistortImage(InputArray distorted, OutputArray undistorted, InputArray K, InputArray D, InputArray xi, int flags, + InputArray Knew = cv::noArray(), const Size& new_size = Size(), InputArray R = Mat::eye(3, 3, CV_64F)); + + /** @brief Perform omnidirectional camera calibration, the default depth of outputs is CV_64F. + + @param objectPoints Vector of vector of Vec3f object points in world (pattern) coordinate. + It also can be vector of Mat with size 1xN/Nx1 and type CV_32FC3. Data with depth of 64_F is also acceptable. + @param imagePoints Vector of vector of Vec2f corresponding image points of objectPoints. It must be the same + size and the same type with objectPoints. + @param size Image size of calibration images. + @param K Output calibrated camera matrix. + @param xi Output parameter xi for CMei's model + @param D Output distortion parameters \f$(k_1, k_2, p_1, p_2)\f$ + @param rvecs Output rotations for each calibration images + @param tvecs Output translation for each calibration images + @param flags The flags that control calibrate + @param criteria Termination criteria for optimization + @param idx Indices of images that pass initialization, which are really used in calibration. So the size of rvecs is the + same as idx.total(). + */ + CV_EXPORTS_W double calibrate(InputArray objectPoints, InputArray imagePoints, Size size, + InputOutputArray K, InputOutputArray xi, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, + int flags, TermCriteria criteria, OutputArray idx=noArray()); + + /** @brief Stereo calibration for omnidirectional camera model. It computes the intrinsic parameters for two + cameras and the extrinsic parameters between two cameras. The default depth of outputs is CV_64F. + + @param objectPoints Object points in world (pattern) coordinate. Its type is vector >. + It also can be vector of Mat with size 1xN/Nx1 and type CV_32FC3. Data with depth of 64_F is also acceptable. + @param imagePoints1 The corresponding image points of the first camera, with type vector >. + It must be the same size and the same type as objectPoints. + @param imagePoints2 The corresponding image points of the second camera, with type vector >. + It must be the same size and the same type as objectPoints. + @param imageSize1 Image size of calibration images of the first camera. + @param imageSize2 Image size of calibration images of the second camera. + @param K1 Output camera matrix for the first camera. + @param xi1 Output parameter xi of Mei's model for the first camera + @param D1 Output distortion parameters \f$(k_1, k_2, p_1, p_2)\f$ for the first camera + @param K2 Output camera matrix for the first camera. + @param xi2 Output parameter xi of CMei's model for the second camera + @param D2 Output distortion parameters \f$(k_1, k_2, p_1, p_2)\f$ for the second camera + @param rvec Output rotation between the first and second camera + @param tvec Output translation between the first and second camera + @param rvecsL Output rotation for each image of the first camera + @param tvecsL Output translation for each image of the first camera + @param flags The flags that control stereoCalibrate + @param criteria Termination criteria for optimization + @param idx Indices of image pairs that pass initialization, which are really used in calibration. So the size of rvecs is the + same as idx.total(). + @ + */ + CV_EXPORTS_W double stereoCalibrate(InputOutputArrayOfArrays objectPoints, InputOutputArrayOfArrays imagePoints1, InputOutputArrayOfArrays imagePoints2, + const Size& imageSize1, const Size& imageSize2, InputOutputArray K1, InputOutputArray xi1, InputOutputArray D1, InputOutputArray K2, InputOutputArray xi2, + InputOutputArray D2, OutputArray rvec, OutputArray tvec, OutputArrayOfArrays rvecsL, OutputArrayOfArrays tvecsL, int flags, TermCriteria criteria, OutputArray idx=noArray()); + + /** @brief Stereo rectification for omnidirectional camera model. It computes the rectification rotations for two cameras + + @param R Rotation between the first and second camera + @param T Translation between the first and second camera + @param R1 Output 3x3 rotation matrix for the first camera + @param R2 Output 3x3 rotation matrix for the second camera + */ + CV_EXPORTS_W void stereoRectify(InputArray R, InputArray T, OutputArray R1, OutputArray R2); + + /** @brief Stereo 3D reconstruction from a pair of images + + @param image1 The first input image + @param image2 The second input image + @param K1 Input camera matrix of the first camera + @param D1 Input distortion parameters \f$(k_1, k_2, p_1, p_2)\f$ for the first camera + @param xi1 Input parameter xi for the first camera for CMei's model + @param K2 Input camera matrix of the second camera + @param D2 Input distortion parameters \f$(k_1, k_2, p_1, p_2)\f$ for the second camera + @param xi2 Input parameter xi for the second camera for CMei's model + @param R Rotation between the first and second camera + @param T Translation between the first and second camera + @param flag Flag of rectification type, RECTIFY_PERSPECTIVE or RECTIFY_LONGLATI + @param numDisparities The parameter 'numDisparities' in StereoSGBM, see StereoSGBM for details. + @param SADWindowSize The parameter 'SADWindowSize' in StereoSGBM, see StereoSGBM for details. + @param disparity Disparity map generated by stereo matching + @param image1Rec Rectified image of the first image + @param image2Rec rectified image of the second image + @param newSize Image size of rectified image, see omnidir::undistortImage + @param Knew New camera matrix of rectified image, see omnidir::undistortImage + @param pointCloud Point cloud of 3D reconstruction, with type CV_64FC3 + @param pointType Point cloud type, it can be XYZRGB or XYZ + */ + CV_EXPORTS_W void stereoReconstruct(InputArray image1, InputArray image2, InputArray K1, InputArray D1, InputArray xi1, + InputArray K2, InputArray D2, InputArray xi2, InputArray R, InputArray T, int flag, int numDisparities, int SADWindowSize, + OutputArray disparity, OutputArray image1Rec, OutputArray image2Rec, const Size& newSize = Size(), InputArray Knew = cv::noArray(), + OutputArray pointCloud = cv::noArray(), int pointType = XYZRGB); + +namespace internal +{ + void initializeCalibration(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, Size size, OutputArrayOfArrays omAll, + OutputArrayOfArrays tAll, OutputArray K, double& xi, OutputArray idx = noArray()); + + void initializeStereoCalibration(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + const Size& size1, const Size& size2, OutputArray om, OutputArray T, OutputArrayOfArrays omL, OutputArrayOfArrays tL, OutputArray K1, OutputArray D1, OutputArray K2, OutputArray D2, + double &xi1, double &xi2, int flags, OutputArray idx); + + void computeJacobian(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, InputArray parameters, Mat& JTJ_inv, Mat& JTE, int flags, + double epsilon); + + void computeJacobianStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputArray parameters, Mat& JTJ_inv, Mat& JTE, int flags, double epsilon); + + void encodeParameters(InputArray K, InputArrayOfArrays omAll, InputArrayOfArrays tAll, InputArray distoaration, double xi, OutputArray parameters); + + void encodeParametersStereo(InputArray K1, InputArray K2, InputArray om, InputArray T, InputArrayOfArrays omL, InputArrayOfArrays tL, + InputArray D1, InputArray D2, double xi1, double xi2, OutputArray parameters); + + void decodeParameters(InputArray paramsters, OutputArray K, OutputArrayOfArrays omAll, OutputArrayOfArrays tAll, OutputArray distoration, double& xi); + + void decodeParametersStereo(InputArray parameters, OutputArray K1, OutputArray K2, OutputArray om, OutputArray T, OutputArrayOfArrays omL, + OutputArrayOfArrays tL, OutputArray D1, OutputArray D2, double& xi1, double& xi2); + + void estimateUncertainties(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, InputArray parameters, Mat& errors, Vec2d& std_error, double& rms, int flags); + + void estimateUncertaintiesStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputArray parameters, Mat& errors, + Vec2d& std_error, double& rms, int flags); + + double computeMeanReproErr(InputArrayOfArrays imagePoints, InputArrayOfArrays proImagePoints); + + double computeMeanReproErr(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, InputArray K, InputArray D, double xi, InputArrayOfArrays omAll, + InputArrayOfArrays tAll); + + double computeMeanReproErrStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputArray K1, InputArray K2, + InputArray D1, InputArray D2, double xi1, double xi2, InputArray om, InputArray T, InputArrayOfArrays omL, InputArrayOfArrays TL); + + void checkFixed(Mat &G, int flags, int n); + + void subMatrix(const Mat& src, Mat& dst, const std::vector& cols, const std::vector& rows); + + void flags2idx(int flags, std::vector& idx, int n); + + void flags2idxStereo(int flags, std::vector& idx, int n); + + void fillFixed(Mat&G, int flags, int n); + + void fillFixedStereo(Mat& G, int flags, int n); + + double findMedian(const Mat& row); + + Vec3d findMedian3(InputArray mat); + + void getInterset(InputArray idx1, InputArray idx2, OutputArray inter1, OutputArray inter2, OutputArray inter_ori); + + void compose_motion(InputArray _om1, InputArray _T1, InputArray _om2, InputArray _T2, Mat& om3, Mat& T3, Mat& dom3dom1, + Mat& dom3dT1, Mat& dom3dom2, Mat& dom3dT2, Mat& dT3dom1, Mat& dT3dT1, Mat& dT3dom2, Mat& dT3dT2); + + //void JRodriguesMatlab(const Mat& src, Mat& dst); + + //void dAB(InputArray A, InputArray B, OutputArray dABdA, OutputArray dABdB); +} // internal + +//! @} + +} // omnidir + +} //cv +#endif \ No newline at end of file diff --git a/modules/ccalib/include/opencv2/ccalib/randpattern.hpp b/modules/ccalib/include/opencv2/ccalib/randpattern.hpp new file mode 100644 index 000000000..9fc08f84e --- /dev/null +++ b/modules/ccalib/include/opencv2/ccalib/randpattern.hpp @@ -0,0 +1,177 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_RANDOMPATTERN_HPP__ +#define __OPENCV_RANDOMPATTERN_HPP__ + +#include "opencv2/features2d.hpp" +#include "opencv2/highgui.hpp" + +namespace cv { namespace randpattern { + + +//! @addtogroup ccalib +//! @{ + +/** @brief Class for finding features points and corresponding 3D in world coordinate of +a "random" pattern, which can be to be used in calibration. It is useful when pattern is +partly occluded or only a part of pattern can be observed in multiple cameras calibration. +The pattern can be generated by RandomPatternGenerator class described in this file. + +Please refer to paper + B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System + Calibration Toolbox Using A Feature Descriptor-Based Calibration + Pattern", in IROS 2013. +*/ + +class CV_EXPORTS RandomPatternCornerFinder +{ +public: + + /* @brief Construct RandomPatternCornerFinder object + + @param patternWidth the real width of "random" pattern in a user defined unit. + @param patternHeight the real height of "random" pattern in a user defined unit. + @param nMiniMatch number of minimal matches, otherwise that image is abandoned + @depth depth of output objectPoints and imagePoints, set it to be CV_32F or CV_64F. + @showExtraction whether show feature extraction, 0 for no and 1 for yes. + @detector feature detector to detect feature points in pattern and images. + @descriptor feature descriptor. + @matcher feature matcher. + */ + RandomPatternCornerFinder(float patternWidth, float patternHeight, + int nminiMatch = 20, int depth = CV_32F, int verbose = 0, int showExtraction = 0, + Ptr detector = AKAZE::create(AKAZE::DESCRIPTOR_MLDB, 0, 3, 0.005f), + Ptr descriptor = AKAZE::create(AKAZE::DESCRIPTOR_MLDB,0, 3, 0.005f), + Ptr matcher = DescriptorMatcher::create("BruteForce-L1")); + + /* @brief Load pattern image and compute features for pattern + @param patternImage image for "random" pattern generated by RandomPatternGenerator, run it first. + */ + void loadPattern(cv::Mat patternImage); + + /* @brief Compute matched object points and image points which are used for calibration + The objectPoints (3D) and imagePoints (2D) are stored inside the class. Run getObjectPoints() + and getImagePoints() to get them. + + @param inputImages vector of 8-bit grayscale images containing "random" pattern + that are used for calibration. + */ + void computeObjectImagePoints(std::vector inputImages); + + //void computeObjectImagePoints2(std::vector inputImages); + + /* @brief Compute object and image points for a single image. It returns a vector that + the first element stores the imagePoints and the second one stores the objectPoints. + + @param inputImage single input image for calibration + */ + std::vector computeObjectImagePointsForSingle(cv::Mat inputImage); + + /* @brief Get object(3D) points + */ + std::vector getObjectPoints(); + + /* @brief and image(2D) points + */ + std::vector getImagePoints(); + +private: + + std::vector _objectPonits, _imagePoints; + float _patternWidth, _patternHeight; + cv::Size _patternImageSize; + int _nminiMatch; + int _depth; + int _verbose; + + Ptr _detector; + Ptr _descriptor; + Ptr _matcher; + Mat _descriptorPattern; + std::vector _keypointsPattern; + Mat _patternImage; + int _showExtraction; + + void keyPoints2MatchedLocation(const std::vector& imageKeypoints, + const std::vector& patternKeypoints, const std::vector matchces, + cv::Mat& matchedImagelocation, cv::Mat& matchedPatternLocation); + void getFilteredLocation(cv::Mat& imageKeypoints, cv::Mat& patternKeypoints, const cv::Mat mask); + void getObjectImagePoints(const cv::Mat& imageKeypoints, const cv::Mat& patternKeypoints); + void crossCheckMatching( cv::Ptr& descriptorMatcher, + const Mat& descriptors1, const Mat& descriptors2, + std::vector& filteredMatches12, int knn=1 ); + void drawCorrespondence(const Mat& image1, const std::vector keypoint1, + const Mat& image2, const std::vector keypoint2, const std::vector matchces, + const Mat& mask1, const Mat& mask2, const int step); +}; + +/* @brief Class to generate "random" pattern image that are used for RandomPatternCornerFinder +Please refer to paper +B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System +Calibration Toolbox Using A Feature Descriptor-Based Calibration +Pattern", in IROS 2013. +*/ +class CV_EXPORTS RandomPatternGenerator +{ +public: + /* @brief Construct RandomPatternGenerator + + @param imageWidth image width of the generated pattern image + @param imageHeight image height of the generated pattern image + */ + RandomPatternGenerator(int imageWidth, int imageHeight); + + /* @brief Generate pattern + */ + void generatePattern(); + /* @brief Get pattern + */ + cv::Mat getPattern(); +private: + cv::Mat _pattern; + int _imageWidth, _imageHeight; +}; + +//! @} + +}} //namespace randpattern, cv +#endif \ No newline at end of file diff --git a/modules/ccalib/samples/multi_cameras_calibration.cpp b/modules/ccalib/samples/multi_cameras_calibration.cpp new file mode 100644 index 000000000..ff643e655 --- /dev/null +++ b/modules/ccalib/samples/multi_cameras_calibration.cpp @@ -0,0 +1,120 @@ +#include "opencv2/ccalib/omnidir.hpp" +#include "opencv2/ccalib/multicalib.hpp" +#include "opencv2/ccalib/randpattern.hpp" + +using namespace std; +using namespace cv; + +const char * usage = +"\n example command line for multi-camera calibration by using random pattern \n" +" multi_cameras_calibration -nc 5 -pw 800 -ph 600 -ct 1 -fe 0 -nm 25 -v 0 multi_camera_omnidir.xml \n" +"\n" +" the file multi_camera_omnidir.xml is generated by imagelist_creator as \n" +" imagelist_creator multi_camera_omnidir.xml *.* \n" +" note the first filename in multi_camera_omnidir.xml is the pattern, the rest are photo names,\n" +" photo names should be in form of cameraIdx-timestamp.*, and cameraIdx starts from 0"; + +static void help() +{ + printf("\n This is a sample for multi-camera calibration, so far it only support random pattern,\n" + "see randomPattern.hpp for detail. Pinhole and omnidirectional cameras are both supported, \n" + "for omnidirectional camera, see omnidir.hpp for detail.\n" + "Usage: mutiCamCalib \n" + " -nc # number of cameras \n" + " -pw # physical width of random pattern \n" + " -ph # physical height of random pattern \n" + " -ct # camera type, 0 for pinhole and 1 for omnidirectional \n" + " -fe # whether show feature extraction\n" + " -nm # number of minimal matches of an image \n" + " -v # whether show verbose information \n" + " input_data # text file with pattern file names and a list of photo names, the file is generated by imagelist_creator \n"); + printf("\n %s", usage); +} + + +int main(int argc, char** argv) +{ + float patternWidth = 0.0f, patternHeight = 0.0f; + int nCamera = 0, nMiniMatches = 0, cameraType = 0; + const char* outputFilename = "multi-camera-results.xml"; + const char* inputFilename = 0; + int showFeatureExtraction = 0, verbose = 0; + if (argc < 2) + { + help(); + return 1; + } + + for (int i = 1; i < argc; ++i) + { + const char* s = argv[i]; + if (strcmp( s, "-nc") == 0) + { + if (sscanf( argv[++i], "%u", &nCamera) != 1 || nCamera <= 0) + { + return fprintf(stderr, "Invalid number of cameras \n"), -1; + } + } + else if ( strcmp( s, "-pw" ) == 0 ) + { + if (sscanf( argv[++i], "%f", &patternWidth) != 1 || patternWidth <=0 ) + { + return fprintf(stderr, "Invalid pattern width \n"), -1; + } + } + else if ( strcmp( s, "-ph" ) == 0 ) + { + if (sscanf( argv[++i], "%f", &patternHeight) != 1 || patternHeight <=0 ) + { + return fprintf(stderr, "Invalid pattern height \n"), -1; + } + } + else if ( strcmp( s, "-ct" ) == 0 ) + { + if (sscanf( argv[++i], "%u", &cameraType) != 1 || (cameraType !=0 && cameraType !=1 && cameraType !=2) ) + { + return fprintf(stderr, "Invalid camera type, 0 for pinhole and 1 for omnidirectional \n"), -1; + } + } + else if ( strcmp( s, "-fe" ) == 0 ) + { + if (sscanf( argv[++i], "%u", &showFeatureExtraction) != 1 || (showFeatureExtraction !=1 && showFeatureExtraction !=0) ) + { + return fprintf(stderr, "Not bool value, set to 0 or 1 \n"), -1; + } + } + else if ( strcmp( s, "-nm" ) == 0 ) + { + if (sscanf( argv[++i], "%u", &nMiniMatches) != 1 || nMiniMatches <=0 ) + { + return fprintf(stderr, "Invalid number of minimal matches \n"), -1; + } + } + else if ( strcmp( s, "-v" ) == 0 ) + { + if (sscanf( argv[++i], "%u", &verbose) != 1 || (verbose !=1 && verbose !=0) ) + { + return fprintf(stderr, "verbose is not bool value, set to 0 or 1 \n"), -1; + } + } + else if( s[0] != '-') + { + inputFilename = s; + } + else + { + return fprintf( stderr, "Unknown option %s\n", s ), -1; + } + } + + // do multi-camera calibration + multicalib::MultiCameraCalibration multiCalib(cameraType, nCamera, inputFilename, patternWidth, patternHeight, verbose, showFeatureExtraction, nMiniMatches); + + multiCalib.loadImages(); + multiCalib.initialize(); + multiCalib.optimizeExtrinsics(); + // the above three lines can be replaced by multiCalib.run(); + + + multiCalib.writeParameters(outputFilename); +} \ No newline at end of file diff --git a/modules/ccalib/samples/omni_calibration.cpp b/modules/ccalib/samples/omni_calibration.cpp new file mode 100644 index 000000000..578a8803b --- /dev/null +++ b/modules/ccalib/samples/omni_calibration.cpp @@ -0,0 +1,257 @@ +#include "opencv2/ccalib/omnidir.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/calib3d.hpp" +#include "opencv2/highgui.hpp" +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +const char * usage = +"\n example command line for omnidirectional camera calibration.\n" +" omni_calibration -w 6 -h 9 -sw 80 -sh 80 imagelist.xml \n" +" \n" +" the file imagelist.xml is generated by imagelist_creator as\n" +"imagelist_creator imagelist.xml *.*"; + +static void help() +{ + printf("\n This is a sample for omnidirectional camera calibration.\n" + "Usage: omni_calibration\n" + " -w # the number of inner corners per one of board dimension\n" + " -h # the number of inner corners per another board dimension\n" + " [-sw ] # the width of square in some user-defined units (1 by default)\n" + " [-sh ] # the height of square in some user-defined units (1 by default)\n" + " [-o ] # the output filename for intrinsic [and extrinsic] parameters\n" + " [-fs ] # fix skew\n" + " [-fp ] # fix the principal point at the center\n" + " input_data # input data - text file with a list of the images of the board, which is generated by imagelist_creator" + ); + printf("\n %s", usage); +} + +static void calcChessboardCorners(Size boardSize, double square_width, double square_height, + Mat& corners) +{ + // corners has type of CV_64FC3 + corners.release(); + int n = boardSize.width * boardSize.height; + corners.create(n, 1, CV_64FC3); + Vec3d *ptr = corners.ptr(); + for (int i = 0; i < boardSize.height; ++i) + { + for (int j = 0; j < boardSize.width; ++j) + { + ptr[i*boardSize.width + j] = Vec3d(double(j * square_width), double(i * square_height), 0.0); + } + } +} + +static bool detecChessboardCorners(const vector& list, vector& list_detected, + vector& imagePoints, Size boardSize, Size& imageSize) +{ + imagePoints.resize(0); + list_detected.resize(0); + int n_img = (int)list.size(); + Mat img; + for(int i = 0; i < n_img; ++i) + { + Mat points; + img = imread(list[i], IMREAD_GRAYSCALE); + bool found = findChessboardCorners( img, boardSize, points); + if (found) + { + if (points.type() != CV_64FC2) + points.convertTo(points, CV_64FC2); + imagePoints.push_back(points); + list_detected.push_back(list[i]); + } + } + if (!img.empty()) + imageSize = img.size(); + if (imagePoints.size() < 3) + return false; + else + return true; +} + +static bool readStringList( const string& filename, vector& l ) +{ + l.resize(0); + FileStorage fs(filename, FileStorage::READ); + if( !fs.isOpened() ) + return false; + FileNode n = fs.getFirstTopLevelNode(); + if( n.type() != FileNode::SEQ ) + return false; + FileNodeIterator it = n.begin(), it_end = n.end(); + for( ; it != it_end; ++it ) + l.push_back((string)*it); + return true; +} + +static void saveCameraParams( const string & filename, int flags, const Mat& cameraMatrix, + const Mat& distCoeffs, const double xi, const vector& rvecs, const vector& tvecs, + vector detec_list, const Mat& idx, const double rms, const vector& imagePoints) +{ + FileStorage fs( filename, FileStorage::WRITE ); + + time_t tt; + time( &tt ); + struct tm *t2 = localtime( &tt ); + char buf[1024]; + strftime( buf, sizeof(buf)-1, "%c", t2 ); + + fs << "calibration_time" << buf; + + if ( !rvecs.empty()) + fs << "nFrames" << (int)rvecs.size(); + + if ( flags != 0) + { + sprintf( buf, "flags: %s%s%s%s%s%s%s%s%s", + flags & omnidir::CALIB_USE_GUESS ? "+use_intrinsic_guess" : "", + flags & omnidir::CALIB_FIX_SKEW ? "+fix_skew" : "", + flags & omnidir::CALIB_FIX_K1 ? "+fix_k1" : "", + flags & omnidir::CALIB_FIX_K2 ? "+fix_k2" : "", + flags & omnidir::CALIB_FIX_P1 ? "+fix_p1" : "", + flags & omnidir::CALIB_FIX_P2 ? "+fix_p2" : "", + flags & omnidir::CALIB_FIX_XI ? "+fix_xi" : "", + flags & omnidir::CALIB_FIX_GAMMA ? "+fix_gamma" : "", + flags & omnidir::CALIB_FIX_CENTER ? "+fix_center" : ""); + //cvWriteComment( *fs, buf, 0 ); + } + + fs << "flags" << flags; + + fs << "camera_matrix" << cameraMatrix; + fs << "distortion_coefficients" << distCoeffs; + fs << "xi" << xi; + + //cvWriteComment( *fs, "names of images that are acturally used in calibration", 0 ); + fs << "used_imgs" << "["; + for (int i = 0; i < (int)idx.total(); ++i) + { + fs << detec_list[(int)idx.at(i)]; + } + fs << "]"; + + if ( !rvecs.empty() && !tvecs.empty() ) + { + Mat rvec_tvec((int)rvecs.size(), 6, CV_64F); + for (int i = 0; i < (int)rvecs.size(); ++i) + { + Mat(rvecs[i]).reshape(1, 1).copyTo(rvec_tvec(Rect(0, i, 3, 1))); + Mat(tvecs[i]).reshape(1, 1).copyTo(rvec_tvec(Rect(3, i, 3, 1))); + } + //cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 ); + fs << "extrinsic_parameters" << rvec_tvec; + } + + fs << "rms" << rms; + + if ( !imagePoints.empty() ) + { + Mat imageMat((int)imagePoints.size(), (int)imagePoints[0].total(), CV_64FC2); + for (int i = 0; i < (int)imagePoints.size(); ++i) + { + Mat r = imageMat.row(i).reshape(2, imageMat.cols); + Mat imagei(imagePoints[i]); + imagei.copyTo(r); + } + fs << "image_points" << imageMat; + } +} + +int main(int argc, char** argv) +{ + Size boardSize, imageSize; + int flags = 0; + double square_width = 0.0, square_height = 0.0; + const char* outputFilename = "out_camera_params.xml"; + const char* inputFilename = 0; + vector objectPoints; + vector imagePoints; + + if(argc < 2) + { + help(); + return 1; + } + + for(int i = 1; i < argc; i++) + { + const char* s = argv[i]; + if( strcmp( s, "-w") == 0) + { + if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 ) + return fprintf( stderr, "Invalid board width\n" ), -1; + } + else if( strcmp( s, "-h" ) == 0 ) + { + if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 ) + return fprintf( stderr, "Invalid board height\n" ), -1; + } + else if( strcmp( s, "-sw" ) == 0 ) + { + if( sscanf( argv[++i], "%lf", &square_width ) != 1 || square_width <= 0 ) + return fprintf(stderr, "Invalid square width\n"), -1; + } + else if( strcmp( s, "-sh" ) == 0 ) + { + if( sscanf( argv[++i], "%lf", &square_height) != 1 || square_height <= 0 ) + return fprintf(stderr, "Invalid square height\n"), -1; + } + else if( strcmp( s, "-o" ) == 0 ) + { + outputFilename = argv[++i]; + } + else if( strcmp( s, "-fs" ) == 0 ) + { + flags |= omnidir::CALIB_FIX_SKEW; + } + else if( strcmp( s, "-fp" ) == 0 ) + { + flags |= omnidir::CALIB_FIX_CENTER; + } + else if( s[0] != '-') + { + inputFilename = s; + } + else + { + return fprintf( stderr, "Unknown option %s\n", s ), -1; + } + } + + // get image name list + vector image_list, detec_list; + if(!readStringList(inputFilename, image_list)) + return fprintf( stderr, "Failed to read image list\n"), -1; + + // find corners in images + // some images may be failed in automatic corner detection, passed cases are in detec_list + if(!detecChessboardCorners(image_list, detec_list, imagePoints, boardSize, imageSize)) + return fprintf(stderr, "Not enough corner detected images\n"), -1; + + // calculate object coordinates + Mat object; + calcChessboardCorners(boardSize, square_width, square_height, object); + for(int i = 0; i < (int)detec_list.size(); ++i) + objectPoints.push_back(object); + + // run calibration, some images are discarded in calibration process because they are failed + // in initialization. Retained image indexes are in idx variable. + Mat K, D, xi, idx; + vector rvecs, tvecs; + double _xi, rms; + TermCriteria criteria(3, 200, 1e-8); + rms = omnidir::calibrate(objectPoints, imagePoints, imageSize, K, xi, D, rvecs, tvecs, flags, criteria, idx); + _xi = xi.at(0); + saveCameraParams(outputFilename, flags, K, D, _xi, + rvecs, tvecs, detec_list, idx, rms, imagePoints); +} diff --git a/modules/ccalib/samples/omni_stereo_calibration.cpp b/modules/ccalib/samples/omni_stereo_calibration.cpp new file mode 100644 index 000000000..5755b07e1 --- /dev/null +++ b/modules/ccalib/samples/omni_stereo_calibration.cpp @@ -0,0 +1,317 @@ +#include "opencv2/ccalib/omnidir.hpp" +#include "opencv2/core.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/calib3d.hpp" +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +const char * usage = + "\n example command line for calibrate a pair of omnidirectional camera.\n" + " omni_stereo_calibration -w 8 -h 6 -sw 2.4399 -sh 2.4399 imagelist_left.xml imagelist_right.xml\n" + " \n" + " the file image_list_1.xml and image_list_2.xml generated by imagelist_creator as\n" + "imagelist_creator image_list_1.xml *.*"; + +static void help() +{ + printf("\n This is a sample for omnidirectional camera calibration.\n" + "Usage: omni_calibration\n" + " -w # the number of inner corners per one of board dimension\n" + " -h # the number of inner corners per another board dimension\n" + " [-sw ] # the width of square in some user-defined units (1 by default)\n" + " [-sh ] # the height of square in some user-defined units (1 by default)\n" + " [-o ] # the output filename for intrinsic [and extrinsic] parameters\n" + " [-fs ] # fix skew\n" + " [-fp ] # fix the principal point at the center\n" + " input_data_1 # input data - text file with a list of the images of the first camera, which is generated by imagelist_creator" + " input_data_2 # input data - text file with a list of the images of the second camera, which is generated by imagelist_creator" + ); + printf("\n %s", usage); +} + +static void calcChessboardCorners(Size boardSize, double square_width, double square_height, + Mat& corners) +{ + // corners has type of CV_64FC3 + corners.release(); + int n = boardSize.width * boardSize.height; + corners.create(n, 1, CV_64FC3); + Vec3d *ptr = corners.ptr(); + for (int i = 0; i < boardSize.height; ++i) + { + for (int j = 0; j < boardSize.width; ++j) + { + ptr[i*boardSize.width + j] = Vec3d(double(j * square_width), double(i * square_height), 0.0); + } + } +} + +static bool detecChessboardCorners(const vector& list1, vector& list_detected_1, + const vector& list2, vector& list_detected_2, + vector& image_points_1, vector& image_points_2, Size boardSize, Size& imageSize1, Size& imageSize2) +{ + image_points_1.resize(0); + image_points_2.resize(0); + list_detected_1.resize(0); + list_detected_2.resize(0); + int n_img = (int)list1.size(); + Mat img_l, img_r; + for(int i = 0; i < n_img; ++i) + { + Mat points_1, points_2; + img_l = imread(list1[i], IMREAD_GRAYSCALE); + img_r = imread(list2[i], IMREAD_GRAYSCALE); + bool found_l = findChessboardCorners( img_l, boardSize, points_1); + bool found_r = findChessboardCorners( img_r, boardSize, points_2); + if (found_l && found_r) + { + if (points_1.type() != CV_64FC2) + points_1.convertTo(points_1, CV_64FC2); + if (points_2.type() != CV_64FC2) + points_2.convertTo(points_2, CV_64FC2); + image_points_1.push_back(points_1); + image_points_2.push_back(points_2); + list_detected_1.push_back(list1[i]); + list_detected_2.push_back(list2[i]); + } + } + if (!img_l.empty()) + imageSize1 = img_l.size(); + if (!img_r.empty()) + { + imageSize2 = img_r.size(); + } + + if (image_points_1.size() < 3) + return false; + else + return true; +} + +static bool readStringList( const string& filename, vector& l ) +{ + l.resize(0); + FileStorage fs(filename, FileStorage::READ); + if( !fs.isOpened() ) + return false; + FileNode n = fs.getFirstTopLevelNode(); + if( n.type() != FileNode::SEQ ) + return false; + FileNodeIterator it = n.begin(), it_end = n.end(); + for( ; it != it_end; ++it ) + l.push_back((string)*it); + return true; +} + +static void saveCameraParams( const string & filename, const int flags, const Mat& cameraMatrix1, const Mat& cameraMatrix2, const Mat& distCoeffs1, + const Mat& disCoeffs2, const double xi1, const double xi2, const Vec3d rvec, const Vec3d tvec, + const vector& rvecs, const vector& tvecs, vector detec_list_1, vector detec_list_2, + const Mat& idx, const double rms, const vector& imagePoints1, const vector& imagePoints2) +{ + FileStorage fs( filename, FileStorage::WRITE ); + + time_t tt; + time( &tt ); + struct tm *t2 = localtime( &tt ); + char buf[1024]; + strftime( buf, sizeof(buf)-1, "%c", t2 ); + + fs << "calibration_time" << buf; + + if ( !rvecs.empty()) + fs << "nFrames" << (int)rvecs.size(); + + if ( flags != 0) + { + sprintf( buf, "flags: %s%s%s%s%s%s%s%s%s", + flags & omnidir::CALIB_USE_GUESS ? "+use_intrinsic_guess" : "", + flags & omnidir::CALIB_FIX_SKEW ? "+fix_skew" : "", + flags & omnidir::CALIB_FIX_K1 ? "+fix_k1" : "", + flags & omnidir::CALIB_FIX_K2 ? "+fix_k2" : "", + flags & omnidir::CALIB_FIX_P1 ? "+fix_p1" : "", + flags & omnidir::CALIB_FIX_P2 ? "+fix_p2" : "", + flags & omnidir::CALIB_FIX_XI ? "+fix_xi" : "", + flags & omnidir::CALIB_FIX_GAMMA ? "+fix_gamma" : "", + flags & omnidir::CALIB_FIX_CENTER ? "+fix_center" : ""); + //cvWriteComment( *fs, buf, 0 ); + } + + fs << "flags" << flags; + + fs << "camera_matrix_1" << cameraMatrix1; + fs << "distortion_coefficients_1" << distCoeffs1; + fs << "xi_1" << xi1; + + fs << "camera_matrix_2" << cameraMatrix2; + fs << "distortion_coefficients_2" << disCoeffs2; + fs << "xi_2" << xi2; + + Mat om_t(1, 6, CV_64F); + Mat(rvec).reshape(1, 1).copyTo(om_t.colRange(0, 3)); + Mat(tvec).reshape(1, 1).copyTo(om_t.colRange(3, 6)); + //cvWriteComment( *fs, "6-tuples (rotation vector + translation vector) for each view", 0 ); + fs << "extrinsic_parameters" << om_t; + + if ( !rvecs.empty() && !tvecs.empty() ) + { + Mat rvec_tvec((int)rvecs.size(), 6, CV_64F); + for (int i = 0; i < (int)rvecs.size(); ++i) + { + Mat(rvecs[i]).reshape(1, 1).copyTo(rvec_tvec(Rect(0, i, 3, 1))); + Mat(tvecs[i]).reshape(1, 1).copyTo(rvec_tvec(Rect(3, i, 3, 1))); + } + //cvWriteComment( *fs, "a set of 6-tuples (rotation vector + translation vector) for each view", 0 ); + fs << "extrinsic_parameters_1" << rvec_tvec; + } + + fs << "rms" << rms; + + //cvWriteComment( *fs, "names of images that are acturally used in calibration", 0 ); + fs << "used_imgs_1" << "["; + for (int i = 0; i < (int)idx.total(); ++i) + { + fs << detec_list_1[(int)idx.at(i)]; + } + fs << "]"; + + fs << "used_imgs_2" << "["; + for (int i = 0; i < (int)idx.total(); ++i) + { + fs << detec_list_2[(int)idx.at(i)]; + } + fs << "]"; + + if ( !imagePoints1.empty() ) + { + Mat imageMat((int)imagePoints1.size(), (int)imagePoints1[0].total(), CV_64FC2); + for (int i = 0; i < (int)imagePoints1.size(); ++i) + { + Mat r = imageMat.row(i).reshape(2, imageMat.cols); + Mat imagei(imagePoints1[i]); + imagei.copyTo(r); + } + fs << "image_points_1" << imageMat; + } + + if ( !imagePoints2.empty() ) + { + Mat imageMat((int)imagePoints2.size(), (int)imagePoints2[0].total(), CV_64FC2); + for (int i = 0; i < (int)imagePoints2.size(); ++i) + { + Mat r = imageMat.row(i).reshape(2, imageMat.cols); + Mat imagei(imagePoints2[i]); + imagei.copyTo(r); + } + fs << "image_points_2" << imageMat; + } +} + +int main(int argc, char** argv) +{ + Size boardSize, imageSize1, imageSize2; + int flags = 0; + double square_width = 0.0, square_height = 0.0; + const char* outputFilename = "out_camera_params_stereo.xml"; + const char* inputFilename1 = 0; + const char* inputFilename2 = 0; + vector objectPoints; + vector imagePoints1; + vector imagePoints2; + + if(argc < 2) + { + help(); + return 1; + } + + bool fist_flag = true; + for(int i = 1; i < argc; i++) + { + const char* s = argv[i]; + if( strcmp( s, "-w") == 0) + { + if( sscanf( argv[++i], "%u", &boardSize.width ) != 1 || boardSize.width <= 0 ) + return fprintf( stderr, "Invalid board width\n" ), -1; + } + else if( strcmp( s, "-h" ) == 0 ) + { + if( sscanf( argv[++i], "%u", &boardSize.height ) != 1 || boardSize.height <= 0 ) + return fprintf( stderr, "Invalid board height\n" ), -1; + } + else if( strcmp( s, "-sw" ) == 0 ) + { + if( sscanf( argv[++i], "%lf", &square_width ) != 1 || square_width <= 0 ) + return fprintf(stderr, "Invalid square width\n"), -1; + } + else if( strcmp( s, "-sh" ) == 0 ) + { + if( sscanf( argv[++i], "%lf", &square_height) != 1 || square_height <= 0 ) + return fprintf(stderr, "Invalid square height\n"), -1; + } + else if( strcmp( s, "-o" ) == 0 ) + { + outputFilename = argv[++i]; + } + else if( strcmp( s, "-fs" ) == 0 ) + { + flags |= omnidir::CALIB_FIX_SKEW; + } + else if( strcmp( s, "-fp" ) == 0 ) + { + flags |= omnidir::CALIB_FIX_CENTER; + } + else if( s[0] != '-' && fist_flag) + { + fist_flag = false; + inputFilename1 = s; + } + else if( s[0] != '-' && !fist_flag) + { + inputFilename2 = s; + } + else + { + return fprintf( stderr, "Unknown option %s\n", s ), -1; + } + } + + // get image name list + vector image_list1, detec_list_1, image_list2, detec_list_2; + if((!readStringList(inputFilename1, image_list1)) || (!readStringList(inputFilename2, image_list2))) + return fprintf( stderr, "Failed to read image list\n"), -1; + + // find corners in images + // some images may be failed in automatic corner detection, passed cases are in detec_list + if(!detecChessboardCorners(image_list1, detec_list_1, image_list2, detec_list_2, + imagePoints1, imagePoints2, boardSize, imageSize1, imageSize2)) + return fprintf(stderr, "Not enough corner detected images\n"), -1; + + // calculate object coordinates + Mat object; + calcChessboardCorners(boardSize, square_width, square_height, object); + for(int i = 0; i < (int)detec_list_1.size(); ++i) + { + objectPoints.push_back(object); + } + + // run calibration, some images are discarded in calibration process because they are failed + // in initialization. Retained image indexes are in idx variable. + Mat K1, K2, D1, D2, xi1, xi2, idx; + vector rvecs, tvecs; + Vec3d rvec, tvec; + double _xi1, _xi2, rms; + TermCriteria criteria(3, 200, 1e-8); + rms = omnidir::stereoCalibrate(objectPoints, imagePoints1, imagePoints2, imageSize1, imageSize2, K1, xi1, D1, + K2, xi2, D2, rvec, tvec, rvecs, tvecs, flags, criteria, idx); + _xi1 = xi1.at(0); + _xi2 = xi2.at(0); + + saveCameraParams(outputFilename, flags, K1, K2, D1, D2, _xi1, _xi2, rvec, tvec, rvecs, tvecs, + detec_list_1, detec_list_2, idx, rms, imagePoints1, imagePoints2); +} \ No newline at end of file diff --git a/modules/ccalib/samples/random_pattern_calibration.cpp b/modules/ccalib/samples/random_pattern_calibration.cpp new file mode 100644 index 000000000..272c22289 --- /dev/null +++ b/modules/ccalib/samples/random_pattern_calibration.cpp @@ -0,0 +1,161 @@ +#include "opencv2/ccalib/randpattern.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/calib3d.hpp" +#include +#include +#include +using namespace std; +using namespace cv; + +const char * usage = + "\n example command line for calibrate a camera by random pattern. \n" + " random_pattern_calibration -pw 600 -ph 850 -mm 20 image_list.xml \n" + "\n" + " the file image_list.xml is generated by imagelist_creator as\n" + "imagelist_creator image_list.xml *.*"; +static void help() +{ + printf("\n This is a sample for camera calibration by a random pattern.\n" + "Usage: random_pattern_calibration\n" + " -pw # the physical width of random pattern\n" + " -ph # the physical height of random pattern\n" + " -mm # minimal number of matches\n" + " [-fp ] # fix the principal point at the center \n" + " input_data # input data - text file with a list of the images of the board, which is generated by imagelist_creator" + ); + printf("\n %s", usage); +} + +static bool readStringList( const string& filename, vector& l ) +{ + l.resize(0); + FileStorage fs(filename, FileStorage::READ); + if( !fs.isOpened() ) + return false; + FileNode n = fs.getFirstTopLevelNode(); + if( n.type() != FileNode::SEQ ) + return false; + FileNodeIterator it = n.begin(), it_end = n.end(); + for( ; it != it_end; ++it ) + l.push_back((string)*it); + return true; +} + +static void saveCameraParams(const string& filename, Size imageSize, float patternWidth, + float patternHeight, int flags, const Mat& cameraMatrix, const Mat& distCoeffs, + const vector& rvecs, const vector& tvecs, double rms) +{ + FileStorage fs (filename, FileStorage::WRITE ); + time_t tt; + time( &tt ); + struct tm *t2 = localtime( &tt ); + char buf[1024]; + strftime( buf, sizeof(buf)-1, "%c", t2 ); + + fs << "calibration_time" << buf; + + if( !rvecs.empty()) + fs << "nframes" << (int)rvecs.size(); + + fs << "image_width" << imageSize.width; + fs << "image_height" << imageSize.height; + fs << "pattern_width" << patternWidth; + fs << "pattern_height" << patternHeight; + + fs << "flags" < imglist; + vector vecImg; + int flags = 0; + float patternWidth = 0.0f, patternHeight = 0.0f; + int nMiniMatches = 0; + if(argc < 2) + { + help(); + return 1; + } + + for (int i = 1; i < argc; ++i) + { + const char* s = argv[i]; + if(strcmp(s, "-pw") == 0) + { + if(sscanf(argv[++i], "%f", &patternWidth) != 1 || patternWidth <= 0) + return fprintf( stderr, "Invalid pattern width\n"), -1; + } + else if(strcmp(s, "-ph") == 0) + { + if(sscanf(argv[++i], "%f", &patternHeight) != 1 || patternHeight <= 0) + return fprintf( stderr, "Invalid pattern height\n"), -1; + } + else if (strcmp(s, "-mm") == 0) + { + if (sscanf(argv[++i], "%d", &nMiniMatches) != 1 || nMiniMatches < 15) + return fprintf( stderr, "Invalid number of minimal matches or number is too small"), -1; + } + else if( strcmp( s, "-fp" ) == 0 ) + { + flags |= CALIB_FIX_PRINCIPAL_POINT; + } + else if( s[0] != '-') + { + inputFilename = s; + } + else + { + return fprintf( stderr, "Unknown option %s\n", s ), -1; + } + } + + readStringList(inputFilename, imglist); + // the first image is the pattern + Mat pattern = cv::imread(imglist[0], cv::IMREAD_GRAYSCALE); + for (int i = 1; i < (int)imglist.size(); ++i) + { + Mat img; + img = cv::imread(imglist[i], cv::IMREAD_GRAYSCALE); + vecImg.push_back(img); + } + + randpattern::RandomPatternCornerFinder finder(patternWidth, patternHeight, nMiniMatches); + finder.loadPattern(pattern); + finder.computeObjectImagePoints(vecImg); + vector objectPoints = finder.getObjectPoints(); + vector imagePoints = finder.getImagePoints(); + + Mat K; + Mat D; + vector rvec, tvec; + double rms = calibrateCamera(objectPoints, imagePoints, vecImg[0].size(), K, D, rvec, tvec); + saveCameraParams(outputFilename, vecImg[0].size(), patternWidth, patternHeight, flags, K, D, rvec, tvec, rms); +} diff --git a/modules/ccalib/samples/random_pattern_generator.cpp b/modules/ccalib/samples/random_pattern_generator.cpp new file mode 100644 index 000000000..153f499d1 --- /dev/null +++ b/modules/ccalib/samples/random_pattern_generator.cpp @@ -0,0 +1,59 @@ +#include "opencv2/ccalib/randpattern.hpp" + +using namespace cv; + +const char * usage = + "\n example command line for generating a random pattern. \n" + " random_patterng_generator -iw 600 -ih 850 pattern.png\n" + "\n"; + +static void help() +{ + printf("\n This is a sample for generating a random pattern that can be used for calibration.\n" + "Usage: random_patterng_generator\n" + " -iw # the width of pattern image\n" + " -ih # the height of pattern image\n" + " filename # the filename for pattern image \n" + ); + printf("\n %s", usage); +} + +int main(int argc, char** argv) +{ + const char* filename = 0; + Mat pattern; + int width = 0, height = 0; + if(argc < 2) + { + help(); + return 1; + } + + for (int i = 1; i < argc; ++i) + { + const char* s = argv[i]; + if(strcmp(s, "-iw") == 0) + { + if(sscanf(argv[++i], "%d", &width) != 1 || width <= 0) + return fprintf( stderr, "Invalid pattern image width\n"), -1; + } + else if(strcmp(s, "-ih") == 0) + { + if(sscanf(argv[++i], "%d", &height) != 1 || height <= 0) + return fprintf( stderr, "Invalid pattern image height\n"), -1; + } + else if( s[0] != '-') + { + filename = s; + } + else + { + return fprintf( stderr, "Unknown option %s\n", s ), -1; + } + } + + randpattern::RandomPatternGenerator generator(width, height); + generator.generatePattern(); + pattern = generator.getPattern(); + imwrite(filename, pattern); +} \ No newline at end of file diff --git a/modules/ccalib/src/multicalib.cpp b/modules/ccalib/src/multicalib.cpp new file mode 100644 index 000000000..42866aeb6 --- /dev/null +++ b/modules/ccalib/src/multicalib.cpp @@ -0,0 +1,780 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +/** + * This module was accepted as a GSoC 2015 project for OpenCV, authored by + * Baisheng Lai, mentored by Bo Li. + * + * The omnidirectional camera in this module is denoted by the catadioptric + * model. Please refer to Mei's paper for details of the camera model: + * + * C. Mei and P. Rives, "Single view point omnidirectional camera + * calibration from planar grids", in ICRA 2007. + * + * The implementation of the calibration part is based on Li's calibration + * toolbox: + * + * B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System + * Calibration Toolbox Using A Feature Descriptor-Based Calibration + * Pattern", in IROS 2013. + */ + +#include "precomp.hpp" +#include "opencv2/ccalib/multicalib.hpp" +#include "opencv2/core.hpp" +#include +#include +#include +#include + +namespace cv { namespace multicalib { + +MultiCameraCalibration::MultiCameraCalibration(int cameraType, int nCameras, const std::string& fileName, + float patternWidth, float patternHeight, int verbose, int showExtration, int nMiniMatches, int flags, TermCriteria criteria, + Ptr detector, Ptr descriptor, + Ptr matcher) +{ + _camType = cameraType; + _nCamera = nCameras; + _flags = flags; + _nMiniMatches = nMiniMatches; + _filename = fileName; + _patternWidth = patternWidth; + _patternHeight = patternHeight; + _criteria = criteria; + _showExtraction = showExtration; + _objectPointsForEachCamera.resize(_nCamera); + _imagePointsForEachCamera.resize(_nCamera); + _cameraMatrix.resize(_nCamera); + _distortCoeffs.resize(_nCamera); + _xi.resize(_nCamera); + _omEachCamera.resize(_nCamera); + _tEachCamera.resize(_nCamera); + _detector = detector; + _descriptor = descriptor; + _matcher = matcher; + _verbose = verbose; + for (int i = 0; i < _nCamera; ++i) + { + _vertexList.push_back(vertex()); + } +} + +double MultiCameraCalibration::run() +{ + loadImages(); + initialize(); + double error = optimizeExtrinsics(); + return error; +} + +std::vector MultiCameraCalibration::readStringList() +{ + std::vector l; + l.resize(0); + FileStorage fs(_filename, FileStorage::READ); + + FileNode n = fs.getFirstTopLevelNode(); + + FileNodeIterator it = n.begin(), it_end = n.end(); + for( ; it != it_end; ++it ) + l.push_back((std::string)*it); + + return l; +} + +void MultiCameraCalibration::loadImages() +{ + std::vector file_list; + file_list = readStringList(); + + Ptr detector = _detector; + Ptr descriptor = _descriptor; + Ptr matcher = _matcher; + + randpattern::RandomPatternCornerFinder finder(_patternWidth, _patternHeight, _nMiniMatches, CV_32F, _verbose, this->_showExtraction, detector, descriptor, matcher); + Mat pattern = cv::imread(file_list[0]); + finder.loadPattern(pattern); + + std::vector > filesEachCameraFull(_nCamera); + std::vector > timestampFull(_nCamera); + std::vector > timestampAvailable(_nCamera); + + for (int i = 1; i < (int)file_list.size(); ++i) + { + int cameraVertex, timestamp; + std::string filename = file_list[i].substr(0, file_list[i].find('.')); + size_t spritPosition1 = filename.rfind('/'); + size_t spritPosition2 = filename.rfind('\\'); + if (spritPosition1!=std::string::npos) + { + filename = filename.substr(spritPosition1+1, filename.size() - 1); + } + else if(spritPosition2!= std::string::npos) + { + filename = filename.substr(spritPosition2+1, filename.size() - 1); + } + sscanf(filename.c_str(), "%d-%d", &cameraVertex, ×tamp); + filesEachCameraFull[cameraVertex].push_back(file_list[i]); + timestampFull[cameraVertex].push_back(timestamp); + } + + + // calibrate each camera individually + for (int camera = 0; camera < _nCamera; ++camera) + { + Mat image, cameraMatrix, distortCoeffs; + + // find image and object points + for (int imgIdx = 0; imgIdx < (int)filesEachCameraFull[camera].size(); ++imgIdx) + { + image = imread(filesEachCameraFull[camera][imgIdx], IMREAD_GRAYSCALE); + if (!image.empty() && _verbose) + { + std::cout << "open image " << filesEachCameraFull[camera][imgIdx] << " successfully" << std::endl; + } + else if (image.empty() && _verbose) + { + std::cout << "open image" << filesEachCameraFull[camera][imgIdx] << " failed" << std::endl; + } + std::vector imgObj = finder.computeObjectImagePointsForSingle(image); + if ((int)imgObj[0].total() > _nMiniMatches) + { + _imagePointsForEachCamera[camera].push_back(imgObj[0]); + _objectPointsForEachCamera[camera].push_back(imgObj[1]); + timestampAvailable[camera].push_back(timestampFull[camera][imgIdx]); + } + else if ((int)imgObj[0].total() <= _nMiniMatches && _verbose) + { + std::cout << "image " << filesEachCameraFull[camera][imgIdx] <<" has too few matched points "<< std::endl; + } + } + + // calibrate + Mat idx; + double rms = 0.0; + if (_camType == PINHOLE) + { + rms = cv::calibrateCamera(_objectPointsForEachCamera[camera], _imagePointsForEachCamera[camera], + image.size(), _cameraMatrix[camera], _distortCoeffs[camera], _omEachCamera[camera], + _tEachCamera[camera],_flags); + idx = Mat(1, (int)_omEachCamera[camera].size(), CV_32S); + for (int i = 0; i < (int)idx.total(); ++i) + { + idx.at(i) = i; + } + } + //else if (_camType == FISHEYE) + //{ + // rms = cv::fisheye::calibrate(_objectPointsForEachCamera[camera], _imagePointsForEachCamera[camera], + // image.size(), _cameraMatrix[camera], _distortCoeffs[camera], _omEachCamera[camera], + // _tEachCamera[camera], _flags); + // idx = Mat(1, (int)_omEachCamera[camera].size(), CV_32S); + // for (int i = 0; i < (int)idx.total(); ++i) + // { + // idx.at(i) = i; + // } + //} + else if (_camType == OMNIDIRECTIONAL) + { + rms = cv::omnidir::calibrate(_objectPointsForEachCamera[camera], _imagePointsForEachCamera[camera], + image.size(), _cameraMatrix[camera], _xi[camera], _distortCoeffs[camera], _omEachCamera[camera], + _tEachCamera[camera], _flags, TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 300, 1e-7), + idx); + } + _cameraMatrix[camera].convertTo(_cameraMatrix[camera], CV_32F); + _distortCoeffs[camera].convertTo(_distortCoeffs[camera], CV_32F); + _xi[camera].convertTo(_xi[camera], CV_32F); + //else + //{ + // CV_Error_(CV_StsOutOfRange, "Unknown camera type, use PINHOLE or OMNIDIRECTIONAL"); + //} + + for (int i = 0; i < (int)_omEachCamera[camera].size(); ++i) + { + int cameraVertex, timestamp, photoVertex; + cameraVertex = camera; + timestamp = timestampAvailable[camera][idx.at(i)]; + + photoVertex = this->getPhotoVertex(timestamp); + + if (_omEachCamera[camera][i].type()!=CV_32F) + { + _omEachCamera[camera][i].convertTo(_omEachCamera[camera][i], CV_32F); + } + if (_tEachCamera[camera][i].type()!=CV_32F) + { + _tEachCamera[camera][i].convertTo(_tEachCamera[camera][i], CV_32F); + } + + Mat transform = Mat::eye(4, 4, CV_32F); + Mat R, T; + Rodrigues(_omEachCamera[camera][i], R); + T = (_tEachCamera[camera][i]).reshape(1, 3); + R.copyTo(transform.rowRange(0, 3).colRange(0, 3)); + T.copyTo(transform.rowRange(0, 3).col(3)); + + this->_edgeList.push_back(edge(cameraVertex, photoVertex, idx.at(i), transform)); + } + std::cout << "initialized for camera " << camera << " rms = " << rms << std::endl; + std::cout << "initialized camera matrix for camera " << camera << " is" << std::endl; + std::cout << _cameraMatrix[camera] << std::endl; + std::cout << "xi for camera " << camera << " is " << _xi[camera] << std::endl; + } + +} + +int MultiCameraCalibration::getPhotoVertex(int timestamp) +{ + int photoVertex = INVALID; + + // find in existing photo vertex + for (int i = 0; i < (int)_vertexList.size(); ++i) + { + if (_vertexList[i].timestamp == timestamp) + { + photoVertex = i; + break; + } + } + + // add a new photo vertex + if (photoVertex == INVALID) + { + _vertexList.push_back(vertex(Mat::eye(4, 4, CV_32F), timestamp)); + photoVertex = (int)_vertexList.size() - 1; + } + + return photoVertex; +} + +void MultiCameraCalibration::initialize() +{ + int nVertices = (int)_vertexList.size(); + int nEdges = (int) _edgeList.size(); + + // build graph + Mat G = Mat::zeros(nVertices, nVertices, CV_32S); + for (int edgeIdx = 0; edgeIdx < nEdges; ++edgeIdx) + { + G.at(this->_edgeList[edgeIdx].cameraVertex, this->_edgeList[edgeIdx].photoVertex) = edgeIdx + 1; + } + G = G + G.t(); + + // traverse the graph + std::vector pre, order; + graphTraverse(G, 0, order, pre); + + for (int i = 0; i < _nCamera; ++i) + { + if (pre[i] == INVALID) + { + std::cout << "camera" << i << "is not connected" << std::endl; + } + } + + for (int i = 1; i < (int)order.size(); ++i) + { + int vertexIdx = order[i]; + Mat prePose = this->_vertexList[pre[vertexIdx]].pose; + int edgeIdx = G.at(vertexIdx, pre[vertexIdx]) - 1; + Mat transform = this->_edgeList[edgeIdx].transform; + + if (vertexIdx < _nCamera) + { + this->_vertexList[vertexIdx].pose = transform * prePose.inv(); + this->_vertexList[vertexIdx].pose.convertTo(this->_vertexList[vertexIdx].pose, CV_32F); + if (_verbose) + { + std::cout << "initial pose for camera " << vertexIdx << " is " << std::endl; + std::cout << this->_vertexList[vertexIdx].pose << std::endl; + } + } + else + { + this->_vertexList[vertexIdx].pose = prePose.inv() * transform; + this->_vertexList[vertexIdx].pose.convertTo(this->_vertexList[vertexIdx].pose, CV_32F); + } + } +} + +double MultiCameraCalibration::optimizeExtrinsics() +{ + // get om, t vector + int nVertex = (int)this->_vertexList.size(); + + Mat extrinParam(1, (nVertex-1)*6, CV_32F); + int offset = 0; + // the pose of the vertex[0] is eye + for (int i = 1; i < nVertex; ++i) + { + Mat rvec, tvec; + cv::Rodrigues(this->_vertexList[i].pose.rowRange(0,3).colRange(0, 3), rvec); + this->_vertexList[i].pose.rowRange(0,3).col(3).copyTo(tvec); + + rvec.reshape(1, 1).copyTo(extrinParam.colRange(offset, offset + 3)); + tvec.reshape(1, 1).copyTo(extrinParam.colRange(offset+3, offset +6)); + offset += 6; + } + //double error_pre = computeProjectError(extrinParam); + // optimization + const double alpha_smooth = 0.01; + double change = 1; + for(int iter = 0; ; ++iter) + { + if ((_criteria.type == 1 && iter >= _criteria.maxCount) || + (_criteria.type == 2 && change <= _criteria.epsilon) || + (_criteria.type == 3 && (change <= _criteria.epsilon || iter >= _criteria.maxCount))) + break; + double alpha_smooth2 = 1 - std::pow(1 - alpha_smooth, (double)iter + 1.0); + Mat JTJ_inv, JTError; + this->computeJacobianExtrinsic(extrinParam, JTJ_inv, JTError); + Mat G = alpha_smooth2*JTJ_inv * JTError; + if (G.depth() == CV_64F) + { + G.convertTo(G, CV_32F); + } + + extrinParam = extrinParam + G.reshape(1, 1); + + change = norm(G) / norm(extrinParam); + //double error = computeProjectError(extrinParam); + } + + double error = computeProjectError(extrinParam); + + std::vector rvecVertex, tvecVertex; + vector2parameters(extrinParam, rvecVertex, tvecVertex); + for (int verIdx = 1; verIdx < (int)_vertexList.size(); ++verIdx) + { + Mat R; + Mat pose = Mat::eye(4, 4, CV_32F); + Rodrigues(rvecVertex[verIdx-1], R); + R.copyTo(pose.colRange(0, 3).rowRange(0, 3)); + Mat(tvecVertex[verIdx-1]).reshape(1, 3).copyTo(pose.rowRange(0, 3).col(3)); + _vertexList[verIdx].pose = pose; + if (_verbose && verIdx < _nCamera) + { + std::cout << "final camera pose of camera " << verIdx << " is" << std::endl; + std::cout << pose << std::endl; + } + } + return error; +} + +void MultiCameraCalibration::computeJacobianExtrinsic(const Mat& extrinsicParams, Mat& JTJ_inv, Mat& JTE) +{ + int nParam = (int)extrinsicParams.total(); + int nEdge = (int)_edgeList.size(); + std::vector pointsLocation(nEdge+1, 0); + + for (int edgeIdx = 0; edgeIdx < nEdge; ++edgeIdx) + { + int nPoints = (int)_objectPointsForEachCamera[_edgeList[edgeIdx].cameraVertex][_edgeList[edgeIdx].photoIndex].total(); + pointsLocation[edgeIdx+1] = pointsLocation[edgeIdx] + nPoints*2; + } + + JTJ_inv = Mat(nParam, nParam, CV_64F); + JTE = Mat(nParam, 1, CV_64F); + + Mat J = Mat::zeros(pointsLocation[nEdge], nParam, CV_64F); + Mat E = Mat::zeros(pointsLocation[nEdge], 1, CV_64F); + + for (int edgeIdx = 0; edgeIdx < nEdge; ++edgeIdx) + { + int photoVertex = _edgeList[edgeIdx].photoVertex; + int photoIndex = _edgeList[edgeIdx].photoIndex; + int cameraVertex = _edgeList[edgeIdx].cameraVertex; + + Mat objectPoints = _objectPointsForEachCamera[cameraVertex][photoIndex]; + Mat imagePoints = _imagePointsForEachCamera[cameraVertex][photoIndex]; + + Mat rvecTran, tvecTran; + Mat R = _edgeList[edgeIdx].transform.rowRange(0, 3).colRange(0, 3); + tvecTran = _edgeList[edgeIdx].transform.rowRange(0, 3).col(3); + cv::Rodrigues(R, rvecTran); + + Mat rvecPhoto = extrinsicParams.colRange((photoVertex-1)*6, (photoVertex-1)*6 + 3); + Mat tvecPhoto = extrinsicParams.colRange((photoVertex-1)*6 + 3, (photoVertex-1)*6 + 6); + + Mat rvecCamera, tvecCamera; + if (cameraVertex > 0) + { + rvecCamera = extrinsicParams.colRange((cameraVertex-1)*6, (cameraVertex-1)*6 + 3); + tvecCamera = extrinsicParams.colRange((cameraVertex-1)*6 + 3, (cameraVertex-1)*6 + 6); + } + else + { + rvecCamera = Mat::zeros(3, 1, CV_32F); + tvecCamera = Mat::zeros(3, 1, CV_32F); + } + + Mat jacobianPhoto, jacobianCamera, error; + computePhotoCameraJacobian(rvecPhoto, tvecPhoto, rvecCamera, tvecCamera, rvecTran, tvecTran, + objectPoints, imagePoints, this->_cameraMatrix[cameraVertex], this->_distortCoeffs[cameraVertex], + this->_xi[cameraVertex], jacobianPhoto, jacobianCamera, error); + if (cameraVertex > 0) + { + jacobianCamera.copyTo(J.rowRange(pointsLocation[edgeIdx], pointsLocation[edgeIdx+1]). + colRange((cameraVertex-1)*6, cameraVertex*6)); + } + jacobianPhoto.copyTo(J.rowRange(pointsLocation[edgeIdx], pointsLocation[edgeIdx+1]). + colRange((photoVertex-1)*6, photoVertex*6)); + error.copyTo(E.rowRange(pointsLocation[edgeIdx], pointsLocation[edgeIdx+1])); + } + //std::cout << J.t() * J << std::endl; + JTJ_inv = (J.t() * J + 1e-10).inv(); + JTE = J.t() * E; + +} +void MultiCameraCalibration::computePhotoCameraJacobian(const Mat& rvecPhoto, const Mat& tvecPhoto, const Mat& rvecCamera, + const Mat& tvecCamera, Mat& rvecTran, Mat& tvecTran, const Mat& objectPoints, const Mat& imagePoints, const Mat& K, + const Mat& distort, const Mat& xi, Mat& jacobianPhoto, Mat& jacobianCamera, Mat& E) +{ + Mat drvecTran_drecvPhoto, drvecTran_dtvecPhoto, + drvecTran_drvecCamera, drvecTran_dtvecCamera, + dtvecTran_drvecPhoto, dtvecTran_dtvecPhoto, + dtvecTran_drvecCamera, dtvecTran_dtvecCamera; + + MultiCameraCalibration::compose_motion(rvecPhoto, tvecPhoto, rvecCamera, tvecCamera, rvecTran, tvecTran, + drvecTran_drecvPhoto, drvecTran_dtvecPhoto, drvecTran_drvecCamera, drvecTran_dtvecCamera, + dtvecTran_drvecPhoto, dtvecTran_dtvecPhoto, dtvecTran_drvecCamera, dtvecTran_dtvecCamera); + + if (rvecTran.depth() == CV_64F) + { + rvecTran.convertTo(rvecTran, CV_32F); + } + if (tvecTran.depth() == CV_64F) + { + tvecTran.convertTo(tvecTran, CV_32F); + } + float xif = 0.0f; + if (_camType == OMNIDIRECTIONAL) + { + xif= xi.at(0); + } + + Mat imagePoints2, jacobian, dx_drvecCamera, dx_dtvecCamera, dx_drvecPhoto, dx_dtvecPhoto; + if (_camType == PINHOLE) + { + cv::projectPoints(objectPoints, rvecTran, tvecTran, K, distort, imagePoints2, jacobian); + } + //else if (_camType == FISHEYE) + //{ + // cv::fisheye::projectPoints(objectPoints, imagePoints2, rvecTran, tvecTran, K, distort, 0, jacobian); + //} + else if (_camType == OMNIDIRECTIONAL) + { + cv::omnidir::projectPoints(objectPoints, imagePoints2, rvecTran, tvecTran, K, xif, distort, jacobian); + } + if (objectPoints.depth() == CV_32F) + { + Mat(imagePoints - imagePoints2).convertTo(E, CV_64FC2); + } + else + { + E = imagePoints - imagePoints2; + } + E = E.reshape(1, (int)imagePoints.total()*2); + + dx_drvecCamera = jacobian.colRange(0, 3) * drvecTran_drvecCamera + jacobian.colRange(3, 6) * dtvecTran_drvecCamera; + dx_dtvecCamera = jacobian.colRange(0, 3) * drvecTran_dtvecCamera + jacobian.colRange(3, 6) * dtvecTran_dtvecCamera; + dx_drvecPhoto = jacobian.colRange(0, 3) * drvecTran_drecvPhoto + jacobian.colRange(3, 6) * dtvecTran_drvecPhoto; + dx_dtvecPhoto = jacobian.colRange(0, 3) * drvecTran_dtvecPhoto + jacobian.colRange(3, 6) * dtvecTran_dtvecPhoto; + + jacobianCamera = cv::Mat(dx_drvecCamera.rows, 6, CV_64F); + jacobianPhoto = cv::Mat(dx_drvecPhoto.rows, 6, CV_64F); + + dx_drvecCamera.copyTo(jacobianCamera.colRange(0, 3)); + dx_dtvecCamera.copyTo(jacobianCamera.colRange(3, 6)); + dx_drvecPhoto.copyTo(jacobianPhoto.colRange(0, 3)); + dx_dtvecPhoto.copyTo(jacobianPhoto.colRange(3, 6)); + +} +void MultiCameraCalibration::graphTraverse(const Mat& G, int begin, std::vector& order, std::vector& pre) +{ + CV_Assert(!G.empty() && G.rows == G.cols); + int nVertex = G.rows; + order.resize(0); + pre.resize(nVertex, INVALID); + pre[begin] = -1; + std::vector visited(nVertex, false); + std::queue q; + visited[begin] = true; + q.push(begin); + order.push_back(begin); + + while(!q.empty()) + { + int v = q.front(); + q.pop(); + Mat idx; + // use my findNonZero maybe + findRowNonZero(G.row(v), idx); + for(int i = 0; i < (int)idx.total(); ++i) + { + int neighbor = idx.at(i); + if (!visited[neighbor]) + { + visited[neighbor] = true; + q.push(neighbor); + order.push_back(neighbor); + pre[neighbor] = v; + } + } + } +} + +void MultiCameraCalibration::findRowNonZero(const Mat& row, Mat& idx) +{ + CV_Assert(!row.empty() && row.rows == 1 && row.channels() == 1); + Mat _row; + std::vector _idx; + row.convertTo(_row, CV_32F); + for (int i = 0; i < (int)row.total(); ++i) + { + if (_row.at(i) != 0) + { + _idx.push_back(i); + } + } + idx.release(); + idx.create(1, (int)_idx.size(), CV_32S); + for (int i = 0; i < (int)_idx.size(); ++i) + { + idx.at(i) = _idx[i]; + } +} + +double MultiCameraCalibration::computeProjectError(Mat& parameters) +{ + int nVertex = (int)_vertexList.size(); + CV_Assert((int)parameters.total() == (nVertex-1) * 6 && parameters.depth() == CV_32F); + int nEdge = (int)_edgeList.size(); + + // recompute the transform between photos and cameras + + std::vector edgeList = this->_edgeList; + std::vector rvecVertex, tvecVertex; + vector2parameters(parameters, rvecVertex, tvecVertex); + + float totalError = 0; + int totalNPoints = 0; + for (int edgeIdx = 0; edgeIdx < nEdge; ++edgeIdx) + { + Mat RPhoto, RCamera, TPhoto, TCamera, transform; + int cameraVertex = edgeList[edgeIdx].cameraVertex; + int photoVertex = edgeList[edgeIdx].photoVertex; + int PhotoIndex = edgeList[edgeIdx].photoIndex; + TPhoto = Mat(tvecVertex[photoVertex - 1]).reshape(1, 3); + + //edgeList[edgeIdx].transform = Mat::ones(4, 4, CV_32F); + transform = Mat::eye(4, 4, CV_32F); + cv::Rodrigues(rvecVertex[photoVertex-1], RPhoto); + if (cameraVertex == 0) + { + RPhoto.copyTo(transform.rowRange(0, 3).colRange(0, 3)); + TPhoto.copyTo(transform.rowRange(0, 3).col(3)); + } + else + { + TCamera = Mat(tvecVertex[cameraVertex - 1]).reshape(1, 3); + cv::Rodrigues(rvecVertex[cameraVertex - 1], RCamera); + Mat(RCamera*RPhoto).copyTo(transform.rowRange(0, 3).colRange(0, 3)); + Mat(RCamera * TPhoto + TCamera).copyTo(transform.rowRange(0, 3).col(3)); + } + + transform.copyTo(edgeList[edgeIdx].transform); + Mat rvec, tvec; + cv::Rodrigues(transform.rowRange(0, 3).colRange(0, 3), rvec); + transform.rowRange(0, 3).col(3).copyTo(tvec); + + Mat objectPoints, imagePoints, proImagePoints; + objectPoints = this->_objectPointsForEachCamera[cameraVertex][PhotoIndex]; + imagePoints = this->_imagePointsForEachCamera[cameraVertex][PhotoIndex]; + + if (this->_camType == PINHOLE) + { + cv::projectPoints(objectPoints, rvec, tvec, _cameraMatrix[cameraVertex], _distortCoeffs[cameraVertex], + proImagePoints); + } + //else if (this->_camType == FISHEYE) + //{ + // cv::fisheye::projectPoints(objectPoints, proImagePoints, rvec, tvec, _cameraMatrix[cameraVertex], + // _distortCoeffs[cameraVertex]); + //} + else if (this->_camType == OMNIDIRECTIONAL) + { + float xi = _xi[cameraVertex].at(0); + + cv::omnidir::projectPoints(objectPoints, proImagePoints, rvec, tvec, _cameraMatrix[cameraVertex], + xi, _distortCoeffs[cameraVertex]); + } + Mat error = imagePoints - proImagePoints; + Vec2f* ptr_err = error.ptr(); + for (int i = 0; i < (int)error.total(); ++i) + { + totalError += sqrt(ptr_err[i][0]*ptr_err[i][0] + ptr_err[i][1]*ptr_err[i][1]); + } + totalNPoints += (int)error.total(); + } + double meanReProjError = totalError / totalNPoints; + _error = meanReProjError; + return meanReProjError; +} + +void MultiCameraCalibration::compose_motion(InputArray _om1, InputArray _T1, InputArray _om2, InputArray _T2, Mat& om3, Mat& T3, Mat& dom3dom1, + Mat& dom3dT1, Mat& dom3dom2, Mat& dom3dT2, Mat& dT3dom1, Mat& dT3dT1, Mat& dT3dom2, Mat& dT3dT2) +{ + Mat om1, om2, T1, T2; + _om1.getMat().convertTo(om1, CV_64F); + _om2.getMat().convertTo(om2, CV_64F); + _T1.getMat().reshape(1, 3).convertTo(T1, CV_64F); + _T2.getMat().reshape(1, 3).convertTo(T2, CV_64F); + /*Mat om2 = _om2.getMat(); + Mat T1 = _T1.getMat().reshape(1, 3); + Mat T2 = _T2.getMat().reshape(1, 3);*/ + + //% Rotations: + Mat R1, R2, R3, dR1dom1(9, 3, CV_64FC1), dR2dom2; + cv::Rodrigues(om1, R1, dR1dom1); + cv::Rodrigues(om2, R2, dR2dom2); + /*JRodriguesMatlab(dR1dom1, dR1dom1); + JRodriguesMatlab(dR2dom2, dR2dom2);*/ + dR1dom1 = dR1dom1.t(); + dR2dom2 = dR2dom2.t(); + + R3 = R2 * R1; + Mat dR3dR2, dR3dR1; + //dAB(R2, R1, dR3dR2, dR3dR1); + matMulDeriv(R2, R1, dR3dR2, dR3dR1); + Mat dom3dR3; + cv::Rodrigues(R3, om3, dom3dR3); + //JRodriguesMatlab(dom3dR3, dom3dR3); + dom3dR3 = dom3dR3.t(); + + dom3dom1 = dom3dR3 * dR3dR1 * dR1dom1; + dom3dom2 = dom3dR3 * dR3dR2 * dR2dom2; + dom3dT1 = Mat::zeros(3, 3, CV_64FC1); + dom3dT2 = Mat::zeros(3, 3, CV_64FC1); + + //% Translations: + Mat T3t = R2 * T1; + Mat dT3tdR2, dT3tdT1; + //dAB(R2, T1, dT3tdR2, dT3tdT1); + matMulDeriv(R2, T1, dT3tdR2, dT3tdT1); + + Mat dT3tdom2 = dT3tdR2 * dR2dom2; + T3 = T3t + T2; + dT3dT1 = dT3tdT1; + dT3dT2 = Mat::eye(3, 3, CV_64FC1); + dT3dom2 = dT3tdom2; + dT3dom1 = Mat::zeros(3, 3, CV_64FC1); +} + +void MultiCameraCalibration::vector2parameters(const Mat& parameters, std::vector& rvecVertex, std::vector& tvecVertexs) +{ + int nVertex = (int)_vertexList.size(); + CV_Assert((int)parameters.channels() == 1 && (int)parameters.total() == 6*(nVertex - 1)); + CV_Assert(parameters.depth() == CV_32F); + parameters.reshape(1, 1); + + rvecVertex.reserve(0); + tvecVertexs.resize(0); + + for (int i = 0; i < nVertex - 1; ++i) + { + rvecVertex.push_back(Vec3f(parameters.colRange(i*6, i*6 + 3))); + tvecVertexs.push_back(Vec3f(parameters.colRange(i*6 + 3, i*6 + 6))); + } +} + +void MultiCameraCalibration::parameters2vector(const std::vector& rvecVertex, const std::vector& tvecVertex, Mat& parameters) +{ + CV_Assert(rvecVertex.size() == tvecVertex.size()); + int nVertex = (int)rvecVertex.size(); + // the pose of the first camera is known + parameters.create(1, 6*(nVertex-1), CV_32F); + + for (int i = 0; i < nVertex-1; ++i) + { + Mat(rvecVertex[i]).reshape(1, 1).copyTo(parameters.colRange(i*6, i*6 + 3)); + Mat(tvecVertex[i]).reshape(1, 1).copyTo(parameters.colRange(i*6 + 3, i*6 + 6)); + } +} + +void MultiCameraCalibration::writeParameters(const std::string& filename) +{ + FileStorage fs( filename, FileStorage::WRITE ); + + fs << "nCameras" << _nCamera; + + for (int camIdx = 0; camIdx < _nCamera; ++camIdx) + { + char num[10]; + sprintf(num, "%d", camIdx); + std::string cameraMatrix = "camera_matrix_" + std::string(num); + std::string cameraPose = "camera_pose_" + std::string(num); + std::string cameraDistortion = "camera_distortion_" + std::string(num); + std::string cameraXi = "xi_" + std::string(num); + + fs << cameraMatrix << _cameraMatrix[camIdx]; + fs << cameraDistortion << _distortCoeffs[camIdx]; + if (_camType == OMNIDIRECTIONAL) + { + fs << cameraXi << _xi[camIdx].at(0); + } + + fs << cameraPose << _vertexList[camIdx].pose; + } + + fs << "meanReprojectError" <<_error; + + for (int photoIdx = _nCamera; photoIdx < (int)_vertexList.size(); ++photoIdx) + { + char timestamp[100]; + sprintf(timestamp, "%d", _vertexList[photoIdx].timestamp); + std::string photoTimestamp = "pose_timestamp_" + std::string(timestamp); + + fs << photoTimestamp << _vertexList[photoIdx].pose; + } +} +}} // namespace multicalib, cv \ No newline at end of file diff --git a/modules/ccalib/src/omnidir.cpp b/modules/ccalib/src/omnidir.cpp new file mode 100644 index 000000000..8c9e1d77c --- /dev/null +++ b/modules/ccalib/src/omnidir.cpp @@ -0,0 +1,2310 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +/** + * This module was accepted as a GSoC 2015 project for OpenCV, authored by + * Baisheng Lai, mentored by Bo Li. + * + * The omnidirectional camera in this module is denoted by the catadioptric + * model. Please refer to Mei's paper for details of the camera model: + * + * C. Mei and P. Rives, "Single view point omnidirectional camera + * calibration from planar grids", in ICRA 2007. + * + * The implementation of the calibration part is based on Li's calibration + * toolbox: + * + * B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System + * Calibration Toolbox Using A Feature Descriptor-Based Calibration + * Pattern", in IROS 2013. + */ +#include "precomp.hpp" +#include "opencv2/ccalib/omnidir.hpp" +#include +#include +namespace cv { namespace +{ + struct JacobianRow + { + Matx13d dom,dT; + Matx12d df; + double ds; + Matx12d dc; + double dxi; + Matx14d dkp; // distortion k1,k2,p1,p2 + }; +}} + +///////////////////////////////////////////////////////////////////////////// +//////// projectPoints +void cv::omnidir::projectPoints(InputArray objectPoints, OutputArray imagePoints, + InputArray rvec, InputArray tvec, InputArray K, double xi, InputArray D, OutputArray jacobian) +{ + + CV_Assert(objectPoints.type() == CV_64FC3 || objectPoints.type() == CV_32FC3); + CV_Assert((rvec.depth() == CV_64F || rvec.depth() == CV_32F) && rvec.total() == 3); + CV_Assert((tvec.depth() == CV_64F || tvec.depth() == CV_32F) && tvec.total() == 3); + CV_Assert((K.type() == CV_64F || K.type() == CV_32F) && K.size() == Size(3,3)); + CV_Assert((D.type() == CV_64F || D.type() == CV_32F) && D.total() == 4); + + imagePoints.create(objectPoints.size(), CV_MAKETYPE(objectPoints.depth(), 2)); + + int n = (int)objectPoints.total(); + + Vec3d om = rvec.depth() == CV_32F ? (Vec3d)*rvec.getMat().ptr() : *rvec.getMat().ptr(); + Vec3d T = tvec.depth() == CV_32F ? (Vec3d)*tvec.getMat().ptr() : *tvec.getMat().ptr(); + + Vec2d f,c; + double s; + if (K.depth() == CV_32F) + { + Matx33f Kc = K.getMat(); + f = Vec2f(Kc(0,0), Kc(1,1)); + c = Vec2f(Kc(0,2),Kc(1,2)); + s = (double)Kc(0,1); + } + else + { + Matx33d Kc = K.getMat(); + f = Vec2d(Kc(0,0), Kc(1,1)); + c = Vec2d(Kc(0,2),Kc(1,2)); + s = Kc(0,1); + } + + Vec4d kp = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr() : *D.getMat().ptr(); + //Vec kp= (Vec)*D.getMat().ptr >(); + + const Vec3d* Xw_alld = objectPoints.getMat().ptr(); + const Vec3f* Xw_allf = objectPoints.getMat().ptr(); + Vec2d* xpd = imagePoints.getMat().ptr(); + Vec2f* xpf = imagePoints.getMat().ptr(); + + Matx33d R; + Matx dRdom; + Rodrigues(om, R, dRdom); + + JacobianRow *Jn = 0; + if (jacobian.needed()) + { + int nvars = 2+2+1+4+3+3+1; // f,c,s,kp,om,T,xi + jacobian.create(2*int(n), nvars, CV_64F); + Jn = jacobian.getMat().ptr(0); + } + + double k1=kp[0],k2=kp[1]; + double p1 = kp[2], p2 = kp[3]; + + for (int i = 0; i < n; i++) + { + // convert to camera coordinate + Vec3d Xw = objectPoints.depth() == CV_32F ? (Vec3d)Xw_allf[i] : Xw_alld[i]; + + Vec3d Xc = (Vec3d)(R*Xw + T); + + // convert to unit sphere + Vec3d Xs = Xc/cv::norm(Xc); + + // convert to normalized image plane + Vec2d xu = Vec2d(Xs[0]/(Xs[2]+xi), Xs[1]/(Xs[2]+xi)); + + // add distortion + Vec2d xd; + double r2 = xu[0]*xu[0]+xu[1]*xu[1]; + double r4 = r2*r2; + + xd[0] = xu[0]*(1+k1*r2+k2*r4) + 2*p1*xu[0]*xu[1] + p2*(r2+2*xu[0]*xu[0]); + xd[1] = xu[1]*(1+k1*r2+k2*r4) + p1*(r2+2*xu[1]*xu[1]) + 2*p2*xu[0]*xu[1]; + + // convert to pixel coordinate + Vec2d final; + final[0] = f[0]*xd[0]+s*xd[1]+c[0]; + final[1] = f[1]*xd[1]+c[1]; + + if (objectPoints.depth() == CV_32F) + { + xpf[i] = final; + } + else + { + xpd[i] = final; + } + /*xpd[i][0] = f[0]*xd[0]+s*xd[1]+c[0]; + xpd[i][1] = f[1]*xd[1]+c[1];*/ + + if (jacobian.needed()) + { + double dXcdR_a[] = {Xw[0],Xw[1],Xw[2],0,0,0,0,0,0, + 0,0,0,Xw[0],Xw[1],Xw[2],0,0,0, + 0,0,0,0,0,0,Xw[0],Xw[1],Xw[2]}; + Matx dXcdR(dXcdR_a); + Matx33d dXcdom = dXcdR * dRdom.t(); + double r_1 = 1.0/norm(Xc); + double r_3 = pow(r_1,3); + Matx33d dXsdXc(r_1-Xc[0]*Xc[0]*r_3, -(Xc[0]*Xc[1])*r_3, -(Xc[0]*Xc[2])*r_3, + -(Xc[0]*Xc[1])*r_3, r_1-Xc[1]*Xc[1]*r_3, -(Xc[1]*Xc[2])*r_3, + -(Xc[0]*Xc[2])*r_3, -(Xc[1]*Xc[2])*r_3, r_1-Xc[2]*Xc[2]*r_3); + Matx23d dxudXs(1/(Xs[2]+xi), 0, -Xs[0]/(Xs[2]+xi)/(Xs[2]+xi), + 0, 1/(Xs[2]+xi), -Xs[1]/(Xs[2]+xi)/(Xs[2]+xi)); + // pre-compute some reusable things + double temp1 = 2*k1*xu[0] + 4*k2*xu[0]*r2; + double temp2 = 2*k1*xu[1] + 4*k2*xu[1]*r2; + Matx22d dxddxu(k2*r4+6*p2*xu[0]+2*p1*xu[1]+xu[0]*temp1+k1*r2+1, 2*p1*xu[0]+2*p2*xu[1]+xu[0]*temp2, + 2*p1*xu[0]+2*p2*xu[1]+xu[1]*temp1, k2*r4+2*p2*xu[0]+6*p1*xu[1]+xu[1]*temp2+k1*r2+1); + Matx22d dxpddxd(f[0], s, + 0, f[1]); + Matx23d dxpddXc = dxpddxd * dxddxu * dxudXs * dXsdXc; + + // derivative of xpd respect to om + Matx23d dxpddom = dxpddXc * dXcdom; + Matx33d dXcdT(1.0,0.0,0.0, + 0.0,1.0,0.0, + 0.0,0.0,1.0); + // derivative of xpd respect to T + + Matx23d dxpddT = dxpddXc * dXcdT; + Matx21d dxudxi(-Xs[0]/(Xs[2]+xi)/(Xs[2]+xi), + -Xs[1]/(Xs[2]+xi)/(Xs[2]+xi)); + + // derivative of xpd respect to xi + Matx21d dxpddxi = dxpddxd * dxddxu * dxudxi; + Matx dxddkp(xu[0]*r2, xu[0]*r4, 2*xu[0]*xu[1], r2+2*xu[0]*xu[0], + xu[1]*r2, xu[1]*r4, r2+2*xu[1]*xu[1], 2*xu[0]*xu[1]); + + // derivative of xpd respect to kp + Matx dxpddkp = dxpddxd * dxddkp; + + // derivative of xpd respect to f + Matx22d dxpddf(xd[0], 0, + 0, xd[1]); + + // derivative of xpd respect to c + Matx22d dxpddc(1, 0, + 0, 1); + + Jn[0].dom = dxpddom.row(0); + Jn[1].dom = dxpddom.row(1); + Jn[0].dT = dxpddT.row(0); + Jn[1].dT = dxpddT.row(1); + Jn[0].dkp = dxpddkp.row(0); + Jn[1].dkp = dxpddkp.row(1); + Jn[0].dxi = dxpddxi(0,0); + Jn[1].dxi = dxpddxi(1,0); + Jn[0].df = dxpddf.row(0); + Jn[1].df = dxpddf.row(1); + Jn[0].dc = dxpddc.row(0); + Jn[1].dc = dxpddc.row(1); + Jn[0].ds = xd[1]; + Jn[1].ds = 0; + Jn += 2; + } + } +} + +///////////////////////////////////////////////////////////////////////////// +//////// undistortPoints +void cv::omnidir::undistortPoints( InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray xi, InputArray R) +{ + CV_Assert(distorted.type() == CV_64FC2 || distorted.type() == CV_32FC2); + CV_Assert(R.empty() || (!R.empty() && (R.size() == Size(3, 3) || R.total() * R.channels() == 3) + && (R.depth() == CV_64F || R.depth() == CV_32F))); + CV_Assert((D.depth() == CV_64F || D.depth() == CV_32F) && D.total() == 4); + CV_Assert(K.size() == Size(3, 3) && (K.depth() == CV_64F || K.depth() == CV_32F)); + CV_Assert(xi.total() == 1 && (xi.depth() == CV_64F || xi.depth() == CV_32F)); + + undistorted.create(distorted.size(), distorted.type()); + + cv::Vec2d f, c; + double s = 0.0; + if (K.depth() == CV_32F) + { + Matx33f camMat = K.getMat(); + f = Vec2f(camMat(0,0), camMat(1,1)); + c = Vec2f(camMat(0,2), camMat(1,2)); + s = (double)camMat(0,1); + } + else if (K.depth() == CV_64F) + { + Matx33d camMat = K.getMat(); + f = Vec2d(camMat(0,0), camMat(1,1)); + c = Vec2d(camMat(0,2), camMat(1,2)); + s = camMat(0,1); + } + + Vec4d kp = D.depth()==CV_32F ? (Vec4d)*D.getMat().ptr():(Vec4d)*D.getMat().ptr(); + Vec2d k = Vec2d(kp[0], kp[1]); + Vec2d p = Vec2d(kp[2], kp[3]); + + double _xi = xi.depth() == CV_32F ? (double)*xi.getMat().ptr() : *xi.getMat().ptr(); + cv::Matx33d RR = cv::Matx33d::eye(); + // R is om + if(!R.empty() && R.total()*R.channels() == 3) + { + cv::Vec3d rvec; + R.getMat().convertTo(rvec, CV_64F); + cv::Rodrigues(rvec, RR); + } + else if (!R.empty() && R.size() == Size(3,3)) + { + R.getMat().convertTo(RR, CV_64F); + } + + const cv::Vec2d *srcd = distorted.getMat().ptr(); + const cv::Vec2f *srcf = distorted.getMat().ptr(); + + cv::Vec2d *dstd = undistorted.getMat().ptr(); + cv::Vec2f *dstf = undistorted.getMat().ptr(); + + int n = (int)distorted.total(); + for (int i = 0; i < n; i++) + { + Vec2d pi = distorted.depth() == CV_32F ? (Vec2d)srcf[i]:(Vec2d)srcd[i]; // image point + Vec2d pp((pi[0]*f[1]-c[0]*f[1]-s*(pi[1]-c[1]))/(f[0]*f[1]), (pi[1]-c[1])/f[1]); //plane + Vec2d pu = pp; // points without distortion + + // remove distortion iteratively + for (int j = 0; j < 20; j++) + { + double r2 = pu[0]*pu[0] + pu[1]*pu[1]; + double r4 = r2*r2; + pu[0] = (pp[0] - 2*p[0]*pu[0]*pu[1] - p[1]*(r2+2*pu[0]*pu[0])) / (1 + k[0]*r2 + k[1]*r4); + pu[1] = (pp[1] - 2*p[1]*pu[0]*pu[1] - p[0]*(r2+2*pu[1]*pu[1])) / (1 + k[0]*r2 + k[1]*r4); + } + + // project to unit sphere + double r2 = pu[0]*pu[0] + pu[1]*pu[1]; + double a = (r2 + 1); + double b = 2*_xi*r2; + double cc = r2*_xi*_xi-1; + double Zs = (-b + sqrt(b*b - 4*a*cc))/(2*a); + Vec3d Xw = Vec3d(pu[0]*(Zs + _xi), pu[1]*(Zs +_xi), Zs); + + // rotate + Xw = RR * Xw; + + // project back to sphere + Vec3d Xs = Xw / cv::norm(Xw); + + // reproject to camera plane + Vec3d ppu = Vec3d(Xs[0]/(Xs[2]+_xi), Xs[1]/(Xs[2]+_xi), 1.0); + if (undistorted.depth() == CV_32F) + { + dstf[i] = Vec2f((float)ppu[0], (float)ppu[1]); + } + else if (undistorted.depth() == CV_64F) + { + dstd[i] = Vec2d(ppu[0], ppu[1]); + } + } +} + + +///////////////////////////////////////////////////////////////////////////// +//////// cv::omnidir::initUndistortRectifyMap +void cv::omnidir::initUndistortRectifyMap(InputArray K, InputArray D, InputArray xi, InputArray R, InputArray P, + const cv::Size& size, int m1type, OutputArray map1, OutputArray map2, int flags) +{ + CV_Assert( m1type == CV_16SC2 || m1type == CV_32F || m1type <=0 ); + map1.create( size, m1type <= 0 ? CV_16SC2 : m1type ); + map2.create( size, map1.type() == CV_16SC2 ? CV_16UC1 : CV_32F ); + + CV_Assert((K.depth() == CV_32F || K.depth() == CV_64F) && (D.depth() == CV_32F || D.depth() == CV_64F)); + CV_Assert(K.size() == Size(3, 3) && (D.empty() || D.total() == 4)); + CV_Assert(P.empty()|| (P.depth() == CV_32F || P.depth() == CV_64F)); + CV_Assert(P.empty() || P.size() == Size(3, 3) || P.size() == Size(4, 3)); + CV_Assert(R.empty() || (R.depth() == CV_32F || R.depth() == CV_64F)); + CV_Assert(R.empty() || R.size() == Size(3, 3) || R.total() * R.channels() == 3); + CV_Assert(flags == RECTIFY_PERSPECTIVE || flags == RECTIFY_CYLINDRICAL || flags == RECTIFY_LONGLATI + || flags == RECTIFY_STEREOGRAPHIC); + CV_Assert(xi.total() == 1 && (xi.depth() == CV_32F || xi.depth() == CV_64F)); + + cv::Vec2d f, c; + double s; + if (K.depth() == CV_32F) + { + Matx33f camMat = K.getMat(); + f = Vec2f(camMat(0, 0), camMat(1, 1)); + c = Vec2f(camMat(0, 2), camMat(1, 2)); + s = (double)camMat(0,1); + } + else + { + Matx33d camMat = K.getMat(); + f = Vec2d(camMat(0, 0), camMat(1, 1)); + c = Vec2d(camMat(0, 2), camMat(1, 2)); + s = camMat(0,1); + } + + Vec4d kp = Vec4d::all(0); + if (!D.empty()) + kp = D.depth() == CV_32F ? (Vec4d)*D.getMat().ptr(): *D.getMat().ptr(); + double _xi = xi.depth() == CV_32F ? (double)*xi.getMat().ptr() : *xi.getMat().ptr(); + Vec2d k = Vec2d(kp[0], kp[1]); + Vec2d p = Vec2d(kp[2], kp[3]); + cv::Matx33d RR = cv::Matx33d::eye(); + if (!R.empty() && R.total() * R.channels() == 3) + { + cv::Vec3d rvec; + R.getMat().convertTo(rvec, CV_64F); + cv::Rodrigues(rvec, RR); + } + else if (!R.empty() && R.size() == Size(3, 3)) + R.getMat().convertTo(RR, CV_64F); + + cv::Matx33d PP = cv::Matx33d::eye(); + if (!P.empty()) + P.getMat().colRange(0, 3).convertTo(PP, CV_64F); + else + PP = K.getMat(); + + cv::Matx33d iKR = (PP*RR).inv(cv::DECOMP_SVD); + cv::Matx33d iK = PP.inv(cv::DECOMP_SVD); + cv::Matx33d iR = RR.inv(cv::DECOMP_SVD); + + if (flags == omnidir::RECTIFY_PERSPECTIVE) + { + for (int i = 0; i < size.height; ++i) + { + float* m1f = map1.getMat().ptr(i); + float* m2f = map2.getMat().ptr(i); + short* m1 = (short*)m1f; + ushort* m2 = (ushort*)m2f; + + double _x = i*iKR(0, 1) + iKR(0, 2), + _y = i*iKR(1, 1) + iKR(1, 2), + _w = i*iKR(2, 1) + iKR(2, 2); + for(int j = 0; j < size.width; ++j, _x+=iKR(0,0), _y+=iKR(1,0), _w+=iKR(2,0)) + { + // project back to unit sphere + double r = sqrt(_x*_x + _y*_y + _w*_w); + double Xs = _x / r; + double Ys = _y / r; + double Zs = _w / r; + // project to image plane + double xu = Xs / (Zs + _xi), + yu = Ys / (Zs + _xi); + // add distortion + double r2 = xu*xu + yu*yu; + double r4 = r2*r2; + double xd = (1+k[0]*r2+k[1]*r4)*xu + 2*p[0]*xu*yu + p[1]*(r2+2*xu*xu); + double yd = (1+k[0]*r2+k[1]*r4)*yu + p[0]*(r2+2*yu*yu) + 2*p[1]*xu*yu; + // to image pixel + double u = f[0]*xd + s*yd + c[0]; + double v = f[1]*yd + c[1]; + + if( m1type == CV_16SC2 ) + { + int iu = cv::saturate_cast(u*cv::INTER_TAB_SIZE); + int iv = cv::saturate_cast(v*cv::INTER_TAB_SIZE); + m1[j*2+0] = (short)(iu >> cv::INTER_BITS); + m1[j*2+1] = (short)(iv >> cv::INTER_BITS); + m2[j] = (ushort)((iv & (cv::INTER_TAB_SIZE-1))*cv::INTER_TAB_SIZE + (iu & (cv::INTER_TAB_SIZE-1))); + } + else if( m1type == CV_32FC1 ) + { + m1f[j] = (float)u; + m2f[j] = (float)v; + } + } + } + } + else if(flags == omnidir::RECTIFY_CYLINDRICAL || flags == omnidir::RECTIFY_LONGLATI || + flags == omnidir::RECTIFY_STEREOGRAPHIC) + { + for (int i = 0; i < size.height; ++i) + { + float* m1f = map1.getMat().ptr(i); + float* m2f = map2.getMat().ptr(i); + short* m1 = (short*)m1f; + ushort* m2 = (ushort*)m2f; + + // for RECTIFY_LONGLATI, theta and h are longittude and latitude + double theta = i*iK(0, 1) + iK(0, 2), + h = i*iK(1, 1) + iK(1, 2); + + for (int j = 0; j < size.width; ++j, theta+=iK(0,0), h+=iK(1,0)) + { + double _xt = 0.0, _yt = 0.0, _wt = 0.0; + if (flags == omnidir::RECTIFY_CYLINDRICAL) + { + //_xt = std::sin(theta); + //_yt = h; + //_wt = std::cos(theta); + _xt = std::cos(theta); + _yt = std::sin(theta); + _wt = h; + } + else if (flags == omnidir::RECTIFY_LONGLATI) + { + _xt = -std::cos(theta); + _yt = -std::sin(theta) * std::cos(h); + _wt = std::sin(theta) * std::sin(h); + } + else if (flags == omnidir::RECTIFY_STEREOGRAPHIC) + { + double a = theta*theta + h*h + 4; + double b = -2*theta*theta - 2*h*h; + double c2 = theta*theta + h*h -4; + + _yt = (-b-std::sqrt(b*b - 4*a*c2))/(2*a); + _xt = theta*(1 - _yt) / 2; + _wt = h*(1 - _yt) / 2; + } + double _x = iR(0,0)*_xt + iR(0,1)*_yt + iR(0,2)*_wt; + double _y = iR(1,0)*_xt + iR(1,1)*_yt + iR(1,2)*_wt; + double _w = iR(2,0)*_xt + iR(2,1)*_yt + iR(2,2)*_wt; + + double r = sqrt(_x*_x + _y*_y + _w*_w); + double Xs = _x / r; + double Ys = _y / r; + double Zs = _w / r; + // project to image plane + double xu = Xs / (Zs + _xi), + yu = Ys / (Zs + _xi); + // add distortion + double r2 = xu*xu + yu*yu; + double r4 = r2*r2; + double xd = (1+k[0]*r2+k[1]*r4)*xu + 2*p[0]*xu*yu + p[1]*(r2+2*xu*xu); + double yd = (1+k[0]*r2+k[1]*r4)*yu + p[0]*(r2+2*yu*yu) + 2*p[1]*xu*yu; + // to image pixel + double u = f[0]*xd + s*yd + c[0]; + double v = f[1]*yd + c[1]; + + if( m1type == CV_16SC2 ) + { + int iu = cv::saturate_cast(u*cv::INTER_TAB_SIZE); + int iv = cv::saturate_cast(v*cv::INTER_TAB_SIZE); + m1[j*2+0] = (short)(iu >> cv::INTER_BITS); + m1[j*2+1] = (short)(iv >> cv::INTER_BITS); + m2[j] = (ushort)((iv & (cv::INTER_TAB_SIZE-1))*cv::INTER_TAB_SIZE + (iu & (cv::INTER_TAB_SIZE-1))); + } + else if( m1type == CV_32FC1 ) + { + m1f[j] = (float)u; + m2f[j] = (float)v; + } + } + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// cv::omnidir::undistortImage + +void cv::omnidir::undistortImage(InputArray distorted, OutputArray undistorted, + InputArray K, InputArray D, InputArray xi, int flags, InputArray Knew, const Size& new_size, InputArray R) +{ + Size size = new_size.area() != 0 ? new_size : distorted.size(); + + cv::Mat map1, map2; + omnidir::initUndistortRectifyMap(K, D, xi, R, Knew, size, CV_16SC2, map1, map2, flags); + cv::remap(distorted, undistorted, map1, map2, INTER_LINEAR, BORDER_CONSTANT); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// cv::omnidir::internal::initializeCalibration + +void cv::omnidir::internal::initializeCalibration(InputArrayOfArrays patternPoints, InputArrayOfArrays imagePoints, Size size, + OutputArrayOfArrays omAll, OutputArrayOfArrays tAll, OutputArray K, double& xi, OutputArray idx) +{ + // For details please refer to Section III from Li's IROS 2013 paper + + double u0 = size.width / 2; + double v0 = size.height / 2; + + int n_img = (int)imagePoints.total(); + + std::vector v_omAll(n_img), v_tAll(n_img); + + std::vector gammaAll(n_img); + + K.create(3, 3, CV_64F); + Mat _K; + for (int image_idx = 0; image_idx < n_img; ++image_idx) + { + cv::Mat objPoints, imgPoints; + patternPoints.getMat(image_idx).copyTo(objPoints); + imagePoints.getMat(image_idx).copyTo(imgPoints); + + int n_point = imgPoints.rows * imgPoints.cols; + if (objPoints.rows != n_point) + objPoints = objPoints.reshape(3, n_point); + if (imgPoints.rows != n_point) + imgPoints = imgPoints.reshape(2, n_point); + + // objectPoints should be 3-channel data, imagePoints should be 2-channel data + CV_Assert(objPoints.type() == CV_64FC3 && imgPoints.type() == CV_64FC2 ); + + std::vector xy, uv; + cv::split(objPoints, xy); + cv::split(imgPoints, uv); + + + cv::Mat x = xy[0].reshape(1, n_point), y = xy[1].reshape(1, n_point), + u = uv[0].reshape(1, n_point) - u0, v = uv[1].reshape(1, n_point) - v0; + + cv::Mat sqrRho = u.mul(u) + v.mul(v); + // compute extrinsic parameters + cv::Mat M(n_point, 6, CV_64F); + Mat(-v.mul(x)).copyTo(M.col(0)); + Mat(-v.mul(y)).copyTo(M.col(1)); + Mat(u.mul(x)).copyTo(M.col(2)); + Mat(u.mul(y)).copyTo(M.col(3)); + Mat(-v).copyTo(M.col(4)); + Mat(u).copyTo(M.col(5)); + + Mat W,U,V; + cv::SVD::compute(M, W, U, V,SVD::FULL_UV); + V = V.t(); + + double miniReprojectError = 1e5; + // the signs of r1, r2, r3 are unknown, so they can be flipped. + for (int coef = 1; coef >= -1; coef-=2) + { + double r11 = V.at(0, 5) * coef; + double r12 = V.at(1, 5) * coef; + double r21 = V.at(2, 5) * coef; + double r22 = V.at(3, 5) * coef; + double t1 = V.at(4, 5) * coef; + double t2 = V.at(5, 5) * coef; + + Mat roots; + double r31s; + solvePoly(Matx13d(-(r11*r12+r21*r22)*(r11*r12+r21*r22), r11*r11+r21*r21-r12*r12-r22*r22, 1), roots); + + if (roots.at(0)[0] > 0) + r31s = sqrt(roots.at(0)[0]); + else + r31s = sqrt(roots.at(1)[0]); + + for (int coef2 = 1; coef2 >= -1; coef2-=2) + { + double r31 = r31s * coef2; + double r32 = -(r11*r12 + r21*r22) / r31; + + cv::Vec3d r1(r11, r21, r31); + cv::Vec3d r2(r12, r22, r32); + cv::Vec3d t(t1, t2, 0); + double scale = 1 / cv::norm(r1); + r1 = r1 * scale; + r2 = r2 * scale; + t = t * scale; + + // compute intrisic parameters + // Form equations in Scaramuzza's paper + // A Toolbox for Easily Calibrating Omnidirectional Cameras + Mat A(n_point*2, 3, CV_64F); + Mat((r1[1]*x + r2[1]*y + t[1])/2).copyTo(A.rowRange(0, n_point).col(0)); + Mat((r1[0]*x + r2[0]*y + t[0])/2).copyTo(A.rowRange(n_point, 2*n_point).col(0)); + Mat(-A.col(0).rowRange(0, n_point).mul(sqrRho)).copyTo(A.col(1).rowRange(0, n_point)); + Mat(-A.col(0).rowRange(n_point, 2*n_point).mul(sqrRho)).copyTo(A.col(1).rowRange(n_point, 2*n_point)); + Mat(-v).copyTo(A.rowRange(0, n_point).col(2)); + Mat(-u).copyTo(A.rowRange(n_point, 2*n_point).col(2)); + + // Operation to avoid bad numerical-condition of A + Vec3d maxA, minA; + for (int j = 0; j < A.cols; j++) + { + cv::minMaxLoc(cv::abs(A.col(j)), &minA[j], &maxA[j]); + A.col(j) = A.col(j) / maxA[j]; + } + + Mat B(n_point*2 , 1, CV_64F); + Mat(v.mul(r1[2]*x + r2[2]*y)).copyTo(B.rowRange(0, n_point)); + Mat(u.mul(r1[2]*x + r2[2]*y)).copyTo(B.rowRange(n_point, 2*n_point)); + + Mat res = A.inv(DECOMP_SVD) * B; + res = res.mul(1/Mat(maxA)); + + double gamma = sqrt(res.at(0) / res.at(1)); + t[2] = res.at(2); + + cv::Vec3d r3 = r1.cross(r2); + + Matx33d R(r1[0], r2[0], r3[0], + r1[1], r2[1], r3[1], + r1[2], r2[2], r3[2]); + Vec3d om; + Rodrigues(R, om); + + // project pattern points to images + Mat projedImgPoints; + Matx33d Kc(gamma, 0, u0, 0, gamma, v0, 0, 0, 1); + + // reproject error + cv::omnidir::projectPoints(objPoints, projedImgPoints, om, t, Kc, 1, Matx14d(0, 0, 0, 0), cv::noArray()); + double reprojectError = omnidir::internal::computeMeanReproErr(imgPoints, projedImgPoints); + + // if this reproject error is smaller + if (reprojectError < miniReprojectError) + { + miniReprojectError = reprojectError; + v_omAll[image_idx] = om; + v_tAll[image_idx] = t; + gammaAll[image_idx] = gamma; + } + } + } + } + + // filter initial results whose reproject errors are too large + std::vector reProjErrorFilter,v_gammaFilter; + std::vector omFilter, tFilter; + double gammaFinal = 0; + + // choose median value + size_t n = gammaAll.size() / 2; + std::nth_element(gammaAll.begin(), gammaAll.begin()+n, gammaAll.end()); + gammaFinal = gammaAll[n]; + + _K = Mat(Matx33d(gammaFinal, 0, u0, 0, gammaFinal, v0, 0, 0, 1)); + _K.convertTo(K, CV_64F); + std::vector _idx; + // recompute reproject error using the final gamma + for (int i = 0; i< n_img; i++) + { + Mat _projected; + cv::omnidir::projectPoints(patternPoints.getMat(i), _projected, v_omAll[i], v_tAll[i], _K, 1, Matx14d(0, 0, 0, 0), cv::noArray()); + double _error = omnidir::internal::computeMeanReproErr(imagePoints.getMat(i), _projected); + if(_error < 100) + { + _idx.push_back(i); + omFilter.push_back(v_omAll[i]); + tFilter.push_back(v_tAll[i]); + } + } + + if (idx.needed()) + { + idx.create(1, (int)_idx.size(), CV_32S); + Mat idx_m = idx.getMat(); + for (int j = 0; j < (int)idx_m.total(); j++) + { + idx_m.at(j) = _idx[j]; + } + } + + if(omAll.kind() == _InputArray::STD_VECTOR_MAT) + { + for (int i = 0; i < (int)omFilter.size(); ++i) + { + omAll.getMat(i) = Mat(omFilter[i]); + tAll.getMat(i) = Mat(tFilter[i]); + } + } + else + { + cv::Mat(omFilter).convertTo(omAll, CV_64FC3); + cv::Mat(tFilter).convertTo(tAll, CV_64FC3); + } + xi = 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// cv::omnidir::internal::initializeStereoCalibration + +void cv::omnidir::internal::initializeStereoCalibration(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + const Size& size1, const Size& size2, OutputArray om, OutputArray T, OutputArrayOfArrays omL, OutputArrayOfArrays tL, OutputArray K1, OutputArray D1, OutputArray K2, OutputArray D2, + double &xi1, double &xi2, int flags, OutputArray idx) +{ + Mat idx1, idx2; + Matx33d _K1, _K2; + Matx14d _D1, _D2; + Mat _xi1m, _xi2m; + + std::vector omAllTemp1, omAllTemp2, tAllTemp1, tAllTemp2; + + omnidir::calibrate(objectPoints, imagePoints1, size1, _K1, _xi1m, _D1, omAllTemp1, tAllTemp1, flags, TermCriteria(3, 100, 1e-6), idx1); + omnidir::calibrate(objectPoints, imagePoints2, size2, _K2, _xi2m, _D2, omAllTemp2, tAllTemp2, flags, TermCriteria(3, 100, 1e-6), idx2); + + // find the intersection idx + Mat interIdx1, interIdx2, interOri; + + getInterset(idx1, idx2, interIdx1, interIdx2, interOri); + if (idx.empty()) + idx.create(1, (int)interOri.total(), CV_32S); + interOri.copyTo(idx.getMat()); + + int n_inter = (int)interIdx1.total(); + + std::vector omAll1(n_inter), omAll2(n_inter), tAll1(n_inter), tAll2(n_inter); + for(int i = 0; i < (int)interIdx1.total(); ++i) + { + omAll1[i] = omAllTemp1[interIdx1.at(i)]; + tAll1[i] = tAllTemp1[interIdx1.at(i)]; + omAll2[i] = omAllTemp2[interIdx2.at(i)]; + tAll2[i] = tAllTemp2[interIdx2.at(i)]; + } + + // initialize R,T + Mat omEstAll(1, n_inter, CV_64FC3), tEstAll(1, n_inter, CV_64FC3); + Mat R1, R2, T1, T2, omLR, TLR, RLR; + for (int i = 0; i < n_inter; ++i) + { + Rodrigues(omAll1[i], R1); + Rodrigues(omAll2[i], R2); + T1 = Mat(tAll1[i]).reshape(1, 3); + T2 = Mat(tAll2[i]).reshape(1, 3); + RLR = R2 * R1.t(); + TLR = T2 - RLR*T1; + Rodrigues(RLR, omLR); + omLR.reshape(3, 1).copyTo(omEstAll.col(i)); + TLR.reshape(3, 1).copyTo(tEstAll.col(i)); + } + Vec3d omEst = internal::findMedian3(omEstAll); + Vec3d tEst = internal::findMedian3(tEstAll); + + Mat(omEst).copyTo(om.getMat()); + Mat(tEst).copyTo(T.getMat()); + + if (omL.empty()) + { + omL.create((int)omAll1.size(), 1, CV_64FC3); + } + if (tL.empty()) + { + tL.create((int)tAll1.size(), 1, CV_64FC3); + } + + if(omL.kind() == _InputArray::STD_VECTOR_MAT) + { + for(int i = 0; i < n_inter; ++i) + { + omL.create(3, 1, CV_64F, i, true); + tL.create(3, 1, CV_64F, i, true); + omL.getMat(i) = Mat(omAll1[i]); + tL.getMat(i) = Mat(tAll1[i]); + } + } + else + { + cv::Mat(omAll1).convertTo(omL, CV_64FC3); + cv::Mat(tAll1).convertTo(tL, CV_64FC3); + } + if (K1.empty()) + { + K1.create(3, 3, CV_64F); + K2.create(3, 3, CV_64F); + } + if (D1.empty()) + { + D1.create(1, 4, CV_64F); + D2.create(1, 4, CV_64F); + } + Mat(_K1).copyTo(K1.getMat()); + Mat(_K2).copyTo(K2.getMat()); + + Mat(_D1).copyTo(D1.getMat()); + Mat(_D2).copyTo(D2.getMat()); + + xi1 = _xi1m.at(0); + xi2 = _xi2m.at(0); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// cv::omnidir::internal::computeJacobian + +void cv::omnidir::internal::computeJacobian(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, + InputArray parameters, Mat& JTJ_inv, Mat& JTE, int flags, double epsilon) +{ + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints.empty() && imagePoints.type() == CV_64FC2); + + int n = (int)objectPoints.total(); + + Mat JTJ = Mat::zeros(10 + 6*n, 10 + 6*n, CV_64F); + JTJ_inv = Mat::zeros(10 + 6*n, 10 + 6*n, CV_64F); + JTE = Mat::zeros(10 + 6*n, 1, CV_64F); + + int nPointsAll = 0; + for (int i = 0; i < n; ++i) + { + nPointsAll += (int)objectPoints.getMat(i).total(); + } + + Mat J = Mat::zeros(2*nPointsAll, 10+6*n, CV_64F); + Mat exAll = Mat::zeros(2*nPointsAll, 10+6*n, CV_64F); + double *para = parameters.getMat().ptr(); + Matx33d K(para[6*n], para[6*n+2], para[6*n+3], + 0, para[6*n+1], para[6*n+4], + 0, 0, 1); + Matx14d D(para[6*n+6], para[6*n+7], para[6*n+8], para[6*n+9]); + double xi = para[6*n+5]; + for (int i = 0; i < n; i++) + { + Mat objPoints, imgPoints, om, T; + objectPoints.getMat(i).copyTo(objPoints); + imagePoints.getMat(i).copyTo(imgPoints); + objPoints = objPoints.reshape(3, objPoints.rows*objPoints.cols); + imgPoints = imgPoints.reshape(2, imgPoints.rows*imgPoints.cols); + + om = parameters.getMat().colRange(i*6, i*6+3); + T = parameters.getMat().colRange(i*6+3, (i+1)*6); + Mat imgProj, jacobian; + omnidir::projectPoints(objPoints, imgProj, om, T, K, xi, D, jacobian); + Mat projError = imgPoints - imgProj; + + // The intrinsic part of Jacobian + Mat JIn(jacobian.rows, 10, CV_64F); + Mat JEx(jacobian.rows, 6, CV_64F); + + jacobian.colRange(6, 16).copyTo(JIn); + jacobian.colRange(0, 6).copyTo(JEx); + + JTJ(Rect(6*n, 6*n, 10, 10)) = JTJ(Rect(6*n, 6*n, 10, 10)) + JIn.t()*JIn; + + JTJ(Rect(i*6, i*6, 6, 6)) = JEx.t() * JEx; + + Mat JExTIn = JEx.t() * JIn; + + JExTIn.copyTo(JTJ(Rect(6*n, i*6, 10, 6))); + + Mat(JIn.t()*JEx).copyTo(JTJ(Rect(i*6, 6*n, 6, 10))); + + JTE(Rect(0, 6*n, 1, 10)) = JTE(Rect(0, 6*n,1, 10)) + JIn.t() * projError.reshape(1, 2*(int)projError.total()); + JTE(Rect(0, i*6, 1, 6)) = JEx.t() * projError.reshape(1, 2*(int)projError.total()); + + //int nPoints = objectPoints.getMat(i).total(); + //JIn.copyTo(J(Rect(6*n, i*nPoints*2, 10, nPoints*2))); + //JEx.copyTo(J(Rect(6*i, i*nPoints*2, 6, nPoints*2))); + //projError.reshape(1, 2*projError.rows).copyTo(exAll.rowRange(i*2*nPoints, (i+1)*2*nPoints)); + } + //JTJ = J.t()*J; + //JTE = J.t()*exAll; + std::vector _idx(6*n+10, 1); + flags2idx(flags, _idx, n); + + subMatrix(JTJ, JTJ, _idx, _idx); + subMatrix(JTE, JTE, std::vector(1, 1), _idx); + // in case JTJ is singular + //SVD svd(JTJ, SVD::NO_UV); + //double cond = svd.w.at(0)/svd.w.at(5); + + //if (cond_JTJ.needed()) + //{ + // cond_JTJ.create(1, 1, CV_64F); + // cond_JTJ.getMat().at(0) = cond; + //} + + //double epsilon = 1e-4*std::exp(cond); + JTJ_inv = Mat(JTJ+epsilon).inv(); +} + +void cv::omnidir::internal::computeJacobianStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputArray parameters, Mat& JTJ_inv, Mat& JTE, int flags, double epsilon) +{ + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints1.empty() && imagePoints1.type() == CV_64FC2); + CV_Assert(!imagePoints2.empty() && imagePoints2.type() == CV_64FC2); + CV_Assert((imagePoints1.total() == imagePoints2.total()) && (imagePoints1.total() == objectPoints.total())); + + // compute Jacobian matrix by naive way + int n_img = (int)objectPoints.total(); + int n_points = (int)objectPoints.getMat(0).total(); + Mat J = Mat::zeros(4 * n_points * n_img, 20 + 6 * (n_img + 1), CV_64F); + Mat exAll = Mat::zeros(4 * n_points * n_img, 1, CV_64F); + double *para = parameters.getMat().ptr(); + int offset1 = (n_img + 1) * 6; + int offset2 = offset1 + 10; + Matx33d K1(para[offset1], para[offset1+2], para[offset1+3], + 0, para[offset1+1], para[offset1+4], + 0, 0, 1); + Matx14d D1(para[offset1+6], para[offset1+7], para[offset1+8], para[offset1+9]); + double xi1 = para[offset1+5]; + + Matx33d K2(para[offset2], para[offset2+2], para[offset2+3], + 0, para[offset2+1], para[offset2+4], + 0, 0, 1); + Matx14d D2(para[offset2+6], para[offset2+7], para[offset2+8], para[offset2+9]); + double xi2 = para[offset2+5]; + + Mat om = parameters.getMat().reshape(1, 1).colRange(0, 3); + Mat T = parameters.getMat().reshape(1, 1).colRange(3, 6); + + for (int i = 0; i < n_img; i++) + { + Mat objPointsi, imgPoints1i, imgPoints2i, om1, T1; + objectPoints.getMat(i).copyTo(objPointsi); + imagePoints1.getMat(i).copyTo(imgPoints1i); + imagePoints2.getMat(i).copyTo(imgPoints2i); + objPointsi = objPointsi.reshape(3, objPointsi.rows*objPointsi.cols); + imgPoints1i = imgPoints1i.reshape(2, imgPoints1i.rows*imgPoints1i.cols); + imgPoints2i = imgPoints2i.reshape(2, imgPoints2i.rows*imgPoints2i.cols); + + om1 = parameters.getMat().reshape(1, 1).colRange((1 + i) * 6, (1 + i) * 6 + 3); + T1 = parameters.getMat().reshape(1, 1).colRange((1 + i) * 6 + 3, (i + 1) * 6 + 6); + + + Mat imgProj1, imgProj2, jacobian1, jacobian2; + + // jacobian for left image + cv::omnidir::projectPoints(objPointsi, imgProj1, om1, T1, K1, xi1, D1, jacobian1); + Mat projError1 = imgPoints1i - imgProj1; + //Mat JIn1(jacobian1.rows, 10, CV_64F); + //Mat JEx1(jacobian1.rows, 6, CV_64F); + jacobian1.colRange(6, 16).copyTo(J(Rect(6*(n_img+1), i*n_points*4, 10, n_points*2))); + jacobian1.colRange(0, 6).copyTo(J(Rect(6+i*6, i*n_points*4, 6, n_points*2))); + projError1.reshape(1, 2*n_points).copyTo(exAll.rowRange(i*4*n_points, (i*4+2)*n_points)); + + //jacobian for right image + Mat om2, T2, dom2dom1, dom2dT1, dom2dom, dom2dT, dT2dom1, dT2dT1, dT2dom, dT2dT; + cv::omnidir::internal::compose_motion(om1, T1, om, T, om2, T2, dom2dom1, dom2dT1, dom2dom, dom2dT, dT2dom1, dT2dT1, dT2dom, dT2dT); + cv::omnidir::projectPoints(objPointsi, imgProj2, om2, T2, K2, xi2, D2, jacobian2); + Mat projError2 = imgPoints2i - imgProj2; + projError2.reshape(1, 2*n_points).copyTo(exAll.rowRange((i*4+2)*n_points, (i*4+4)*n_points)); + Mat dxrdom = jacobian2.colRange(0, 3) * dom2dom + jacobian2.colRange(3, 6) * dT2dom; + Mat dxrdT = jacobian2.colRange(0, 3) * dom2dT + jacobian2.colRange(3, 6) * dT2dT; + Mat dxrdom1 = jacobian2.colRange(0, 3) * dom2dom1 + jacobian2.colRange(3, 6) * dT2dom1; + Mat dxrdT1 = jacobian2.colRange(0, 3) * dom2dT1 + jacobian2.colRange(3, 6) * dT2dT1; + + dxrdom.copyTo(J(Rect(0, (i*4+2)*n_points, 3, n_points*2))); + dxrdT.copyTo(J(Rect(3, (i*4+2)*n_points, 3, n_points*2))); + dxrdom1.copyTo(J(Rect(6+i*6, (i*4+2)*n_points, 3, n_points*2))); + dxrdT1.copyTo(J(Rect(6+i*6+3, (i*4+2)*n_points, 3, n_points*2))); + jacobian2.colRange(6, 16).copyTo(J(Rect(6*(n_img+1)+10, (4*i+2)*n_points, 10, n_points*2))); + } + + std::vector _idx(6*(n_img+1)+20, 1); + flags2idxStereo(flags, _idx, n_img); + + Mat JTJ = J.t()*J; + JTE = J.t()*exAll; + subMatrix(JTJ, JTJ, _idx, _idx); + subMatrix(JTE, JTE, std::vector(1, 1), _idx); + + JTJ_inv = Mat(JTJ+epsilon).inv(); +} + +// This function is from fisheye.cpp +void cv::omnidir::internal::compose_motion(InputArray _om1, InputArray _T1, InputArray _om2, InputArray _T2, Mat& om3, Mat& T3, Mat& dom3dom1, + Mat& dom3dT1, Mat& dom3dom2, Mat& dom3dT2, Mat& dT3dom1, Mat& dT3dT1, Mat& dT3dom2, Mat& dT3dT2) +{ + Mat om1 = _om1.getMat(); + Mat om2 = _om2.getMat(); + Mat T1 = _T1.getMat().reshape(1, 3); + Mat T2 = _T2.getMat().reshape(1, 3); + + //% Rotations: + Mat R1, R2, R3, dR1dom1(9, 3, CV_64FC1), dR2dom2; + Rodrigues(om1, R1, dR1dom1); + Rodrigues(om2, R2, dR2dom2); + //JRodriguesMatlab(dR1dom1, dR1dom1); + //JRodriguesMatlab(dR2dom2, dR2dom2); + dR1dom1 = dR1dom1.t(); + dR2dom2 = dR2dom2.t(); + + R3 = R2 * R1; + Mat dR3dR2, dR3dR1; + //dAB(R2, R1, dR3dR2, dR3dR1); + matMulDeriv(R2, R1, dR3dR2, dR3dR1); + + Mat dom3dR3; + Rodrigues(R3, om3, dom3dR3); + //JRodriguesMatlab(dom3dR3, dom3dR3); + dom3dR3 = dom3dR3.t(); + dom3dom1 = dom3dR3 * dR3dR1 * dR1dom1; + dom3dom2 = dom3dR3 * dR3dR2 * dR2dom2; + dom3dT1 = Mat::zeros(3, 3, CV_64FC1); + dom3dT2 = Mat::zeros(3, 3, CV_64FC1); + + //% Translations: + Mat T3t = R2 * T1; + Mat dT3tdR2, dT3tdT1; + //dAB(R2, T1, dT3tdR2, dT3tdT1); + matMulDeriv(R2, T1, dT3tdR2, dT3tdT1); + Mat dT3tdom2 = dT3tdR2 * dR2dom2; + T3 = T3t + T2; + dT3dT1 = dT3tdT1; + dT3dT2 = Mat::eye(3, 3, CV_64FC1); + dT3dom2 = dT3tdom2; + dT3dom1 = Mat::zeros(3, 3, CV_64FC1); +} + +double cv::omnidir::calibrate(InputArray patternPoints, InputArray imagePoints, Size size, + InputOutputArray K, InputOutputArray xi, InputOutputArray D, OutputArrayOfArrays omAll, OutputArrayOfArrays tAll, + int flags, TermCriteria criteria, OutputArray idx) +{ + CV_Assert(!patternPoints.empty() && !imagePoints.empty() && patternPoints.total() == imagePoints.total()); + CV_Assert((patternPoints.type() == CV_64FC3 && imagePoints.type() == CV_64FC2) || + (patternPoints.type() == CV_32FC3 && imagePoints.type() == CV_32FC2)); + CV_Assert(patternPoints.getMat(0).channels() == 3 && imagePoints.getMat(0).channels() == 2); + CV_Assert((!K.empty() && K.size() == Size(3,3)) || K.empty()); + CV_Assert((!D.empty() && D.total() == 4) || D.empty()); + CV_Assert((!xi.empty() && xi.total() == 1) || xi.empty()); + CV_Assert((!omAll.empty() && omAll.depth() == patternPoints.depth()) || omAll.empty()); + CV_Assert((!tAll.empty() && tAll.depth() == patternPoints.depth()) || tAll.empty()); + int depth = patternPoints.depth(); + + std::vector _patternPoints, _imagePoints; + + for (int i = 0; i < (int)patternPoints.total(); ++i) + { + _patternPoints.push_back(patternPoints.getMat(i)); + _imagePoints.push_back(imagePoints.getMat(i)); + if (depth == CV_32F) + { + _patternPoints[i].convertTo(_patternPoints[i], CV_64FC3); + _imagePoints[i].convertTo(_imagePoints[i], CV_64FC2); + } + } + + double _xi; + // initialization + std::vector _omAll, _tAll; + Matx33d _K; + Matx14d _D; + Mat _idx; + cv::omnidir::internal::initializeCalibration(_patternPoints, _imagePoints, size, _omAll, _tAll, _K, _xi, _idx); + std::vector _patternPointsTmp = _patternPoints; + std::vector _imagePointsTmp = _imagePoints; + + _patternPoints.clear(); + _imagePoints.clear(); + // erase + for (int i = 0; i < (int)_idx.total(); i++) + { + _patternPoints.push_back(_patternPointsTmp[_idx.at(i)]); + _imagePoints.push_back(_imagePointsTmp[_idx.at(i)]); + } + + int n = (int)_patternPoints.size(); + Mat finalParam(1, 10 + 6*n, CV_64F); + Mat currentParam(1, 10 + 6*n, CV_64F); + cv::omnidir::internal::encodeParameters(_K, _omAll, _tAll, Mat::zeros(1,4,CV_64F), _xi, currentParam); + + // optimization + const double alpha_smooth = 0.01; + //const double thresh_cond = 1e6; + double change = 1; + for(int iter = 0; ; ++iter) + { + if ((criteria.type == 1 && iter >= criteria.maxCount) || + (criteria.type == 2 && change <= criteria.epsilon) || + (criteria.type == 3 && (change <= criteria.epsilon || iter >= criteria.maxCount))) + break; + double alpha_smooth2 = 1 - std::pow(1 - alpha_smooth, (double)iter + 1.0); + Mat JTJ_inv, JTError; + double epsilon = 0.01 * std::pow(0.9, (double)iter/10); + cv::omnidir::internal::computeJacobian(_patternPoints, _imagePoints, currentParam, JTJ_inv, JTError, flags, epsilon); + + // Gauss¨CNewton + Mat G = alpha_smooth2*JTJ_inv * JTError; + + omnidir::internal::fillFixed(G, flags, n); + + finalParam = currentParam + G.t(); + + change = norm(G) / norm(currentParam); + + currentParam = finalParam.clone(); + + cv::omnidir::internal::decodeParameters(currentParam, _K, _omAll, _tAll, _D, _xi); + //double repr = internal::computeMeanReproErr(_patternPoints, _imagePoints, _K, _D, _xi, _omAll, _tAll); + } + cv::omnidir::internal::decodeParameters(currentParam, _K, _omAll, _tAll, _D, _xi); + + //double repr = internal::computeMeanReproErr(_patternPoints, _imagePoints, _K, _D, _xi, _omAll, _tAll); + + if (omAll.needed()) + { + omAll.create((int)_omAll.size(), 1, CV_64FC3); + } + if (tAll.needed()) + { + tAll.create((int)_tAll.size(), 1, CV_64FC3); + } + if (omAll.kind() == _InputArray::STD_VECTOR_MAT) + { + for (int i = 0; i < n; ++i) + { + omAll.create(3, 1, CV_64F, i, true); + tAll.create(3, 1, CV_64F, i, true); + Mat tmpom = Mat(_omAll[i]); + Mat tmpt = Mat(_tAll[i]); + tmpom.convertTo(tmpom, CV_64F); + tmpt.convertTo(tmpt, CV_64F); + tmpom.copyTo(omAll.getMat(i)); + tmpt.copyTo(tAll.getMat(i)); + } + } + else + { + Mat(_omAll).convertTo(omAll, CV_64FC3); + Mat(_tAll).convertTo(tAll, CV_64FC3); + } + + if(K.empty()) + { + K.create(3, 3, CV_64F); + } + if (D.empty()) + { + D.create(1, 4, CV_64F); + } + + Mat(_K).convertTo(K.getMat(), K.empty()? CV_64F : K.type()); + Mat(_D).convertTo(D.getMat(), D.empty() ? CV_64F: D.type()); + + if (xi.empty()) + { + xi.create(1, 1, CV_64F); + } + Mat xi_m = Mat(1, 1, CV_64F); + xi_m.at(0) = _xi; + xi_m.convertTo(xi.getMat(), xi.empty() ? CV_64F : xi.type()); + + if (idx.needed()) + { + idx.create(1, (int)_idx.total(), CV_32S); + _idx.copyTo(idx.getMat()); + } + + Vec2d std_error; + double rms; + Mat errors; + cv::omnidir::internal::estimateUncertainties(_patternPoints, _imagePoints, finalParam, errors, std_error, rms, flags); + return rms; +} + +double cv::omnidir::stereoCalibrate(InputOutputArrayOfArrays objectPoints, InputOutputArrayOfArrays imagePoints1, InputOutputArrayOfArrays imagePoints2, + const Size& imageSize1, const Size& imageSize2, InputOutputArray K1, InputOutputArray xi1, InputOutputArray D1, InputOutputArray K2, InputOutputArray xi2, + InputOutputArray D2, OutputArray om, OutputArray T, OutputArrayOfArrays omL, OutputArrayOfArrays tL, int flags, TermCriteria criteria, OutputArray idx) +{ + CV_Assert(!objectPoints.empty() && (objectPoints.type() == CV_64FC3 || objectPoints.type() == CV_32FC3)); + CV_Assert(!imagePoints1.empty() && (imagePoints1.type() == CV_64FC2 || imagePoints1.type() == CV_32FC2)); + CV_Assert(!imagePoints2.empty() && (imagePoints2.type() == CV_64FC2 || imagePoints2.type() == CV_32FC2)); + + CV_Assert(((flags & CALIB_USE_GUESS) && !K1.empty() && !D1.empty() && !K2.empty() && !D2.empty()) || !(flags & CALIB_USE_GUESS)); + + int depth = objectPoints.depth(); + + std::vector _objectPoints, _imagePoints1, _imagePoints2, + _objectPointsFilt, _imagePoints1Filt, _imagePoints2Filt; + for (int i = 0; i < (int)objectPoints.total(); ++i) + { + _objectPoints.push_back(objectPoints.getMat(i)); + _imagePoints1.push_back(imagePoints1.getMat(i)); + _imagePoints2.push_back(imagePoints2.getMat(i)); + if (depth == CV_32F) + { + _objectPoints[i].convertTo(_objectPoints[i], CV_64FC3); + _imagePoints1[i].convertTo(_imagePoints1[i], CV_64FC2); + _imagePoints2[i].convertTo(_imagePoints2[i], CV_64FC2); + } + } + + Matx33d _K1, _K2; + Matx14d _D1, _D2; + + double _xi1, _xi2; + + std::vector _omL, _TL; + Vec3d _om, _T; + + // initializaition + Mat _idx; + internal::initializeStereoCalibration(_objectPoints, _imagePoints1, _imagePoints2, imageSize1, imageSize2, _om, _T, _omL, _TL, _K1, _D1, _K2, _D2, _xi1, _xi2, flags, _idx); + if(idx.needed()) + { + idx.create(1, (int)_idx.total(), CV_32S); + _idx.copyTo(idx.getMat()); + } + for (int i = 0; i < (int)_idx.total(); ++i) + { + _objectPointsFilt.push_back(_objectPoints[_idx.at(i)]); + _imagePoints1Filt.push_back(_imagePoints1[_idx.at(i)]); + _imagePoints2Filt.push_back(_imagePoints2[_idx.at(i)]); + } + + int n = (int)_objectPointsFilt.size(); + Mat finalParam(1, 10 + 6*n, CV_64F); + Mat currentParam(1, 10 + 6*n, CV_64F); + + //double repr1 = internal::computeMeanReproErrStereo(_objectPoints, _imagePoints1, _imagePoints2, _K1, _K2, _D1, _D2, _xi1, _xi2, _om, + // _T, _omL, _TL); + cv::omnidir::internal::encodeParametersStereo(_K1, _K2, _om, _T, _omL, _TL, _D1, _D2, _xi1, _xi2, currentParam); + + // optimization + const double alpha_smooth = 0.01; + double change = 1; + for(int iter = 0; ; ++iter) + { + if ((criteria.type == 1 && iter >= criteria.maxCount) || + (criteria.type == 2 && change <= criteria.epsilon) || + (criteria.type == 3 && (change <= criteria.epsilon || iter >= criteria.maxCount))) + break; + double alpha_smooth2 = 1 - std::pow(1 - alpha_smooth, (double)iter + 1.0); + Mat JTJ_inv, JTError; + double epsilon = 0.01 * std::pow(0.9, (double)iter/10); + + cv::omnidir::internal::computeJacobianStereo(_objectPointsFilt, _imagePoints1Filt, _imagePoints2Filt, currentParam, + JTJ_inv, JTError, flags, epsilon); + + // Gauss¨CNewton + Mat G = alpha_smooth2*JTJ_inv * JTError; + + omnidir::internal::fillFixedStereo(G, flags, n); + + finalParam = currentParam + G.t(); + + change = norm(G) / norm(currentParam); + + currentParam = finalParam.clone(); + cv::omnidir::internal::decodeParametersStereo(currentParam, _K1, _K2, _om, _T, _omL, _TL, _D1, _D2, _xi1, _xi2); + //double repr = internal::computeMeanReproErrStereo(_objectPoints, _imagePoints1, _imagePoints2, _K1, _K2, _D1, _D2, _xi1, _xi2, _om, + // _T, _omL, _TL); + + } + cv::omnidir::internal::decodeParametersStereo(finalParam, _K1, _K2, _om, _T, _omL, _TL, _D1, _D2, _xi1, _xi2); + //double repr = internal::computeMeanReproErrStereo(_objectPoints, _imagePoints1, _imagePoints2, _K1, _K2, _D1, _D2, _xi1, _xi2, _om, + // _T, _omL, _TL); + + if (K1.empty()) + { + K1.create(3, 3, CV_64F); + D1.create(1, 4, CV_64F); + K2.create(3, 3, CV_64F); + D2.create(1, 4, CV_64F); + } + if (om.empty()) + { + om.create(1, 3, CV_64F); + T.create(1, 3, CV_64F); + } + if (omL.empty()) + { + omL.create(1, n, CV_64FC3); + tL.create(1, n, CV_64FC3); + } + + Mat(_K1).convertTo(K1.getMat(), K1.empty() ? CV_64F : K1.type()); + Mat(_D1).convertTo(D1.getMat(), D1.empty() ? CV_64F : D1.type()); + Mat(_K2).convertTo(K2.getMat(), K2.empty() ? CV_64F : K2.type()); + Mat(_D2).convertTo(D2.getMat(), D2.empty() ? CV_64F : D2.type()); + + Mat(_om).convertTo(om.getMat(), om.empty() ? CV_64F: om.type()); + Mat(_T).convertTo(T.getMat(), T.empty() ? CV_64F: T.type()); + + if (omL.needed()) + { + omL.create((int)_omL.size(), 1, CV_64FC3); + } + if (tL.needed()) + { + tL.create((int)_TL.size(), 1, CV_64FC3); + } + + if (omL.kind() == _InputArray::STD_VECTOR_MAT) + { + for (int i = 0; i < n; ++i) + { + omL.create(3, 1, CV_64F, i, true); + tL.create(3, 1, CV_64F, i, true); + Mat(_omL[i]).copyTo(omL.getMat(i)); + Mat(_TL[i]).copyTo(tL.getMat(i)); + } + } + else + { + Mat(_omL).convertTo(omL, omL.empty() ? CV_64FC3 : omL.type()); + Mat(_TL).convertTo(tL, tL.empty() ? CV_64FC3 : tL.type()); + } + + Mat xi1_m = Mat(1, 1, CV_64F), + xi2_m = Mat(1, 1, CV_64F); + xi1_m.at(0) = _xi1; + xi2_m.at(0) = _xi2; + + if (xi1.empty()) + { + xi1.create(1, 1, CV_64F); + } + if (xi2.empty()) + { + xi2.create(1, 1, CV_64F); + } + xi1_m.convertTo(xi1, xi1.empty() ? CV_64F : xi1.type()); + xi2_m.convertTo(xi2, xi2.empty() ? CV_64F : xi2.type()); + + // compute uncertainty + Vec2d std_error; + double rms; + Mat errors; + + cv::omnidir::internal::estimateUncertaintiesStereo(_objectPointsFilt, _imagePoints1Filt, _imagePoints2Filt, + finalParam, errors, std_error, rms, flags); + return rms; +} + +void cv::omnidir::stereoReconstruct(InputArray image1, InputArray image2, InputArray K1, InputArray D1, + InputArray xi1, InputArray K2, InputArray D2, InputArray xi2, InputArray R, InputArray T, int flag, + int numDisparities, int SADWindowSize, OutputArray disparity, OutputArray image1Rec, OutputArray image2Rec, + const Size& newSize, InputArray Knew, OutputArray pointCloud, int pointType) +{ + CV_Assert(!K1.empty() && K1.size() == Size(3,3) && (K1.type() == CV_64F || K1.type() == CV_32F)); + CV_Assert(!K2.empty() && K2.size() == Size(3,3) && (K2.type() == CV_64F || K2.type() == CV_32F)); + CV_Assert(!D1.empty() && D1.total() == 4 && (D1.type() == CV_64F || D1.type() == CV_32F)); + CV_Assert(!D2.empty() && D2.total() == 4 && (D2.type() == CV_64F || D2.type() == CV_32F)); + CV_Assert(!R.empty() && (R.size() == Size(3,3) || R.total() == 3) && (R.type() == CV_64F || R.type() == CV_32F)); + CV_Assert(!T.empty() && T.total() == 3 && (T.type() == CV_64F || T.type() == CV_32F)); + CV_Assert(!image1.empty() && (image1.type() == CV_8U || image1.type() == CV_8UC3)); + CV_Assert(!image2.empty() && (image2.type() == CV_8U || image2.type() == CV_8UC3)); + CV_Assert(flag == omnidir::RECTIFY_LONGLATI || flag == omnidir::RECTIFY_PERSPECTIVE); + + Mat _K1, _D1, _K2, _D2, _R, _T; + + K1.getMat().convertTo(_K1, CV_64F); + K2.getMat().convertTo(_K2, CV_64F); + D1.getMat().convertTo(_D1, CV_64F); + D2.getMat().convertTo(_D2, CV_64F); + T.getMat().reshape(1, 3).convertTo(_T, CV_64F); + + if (R.size() == Size(3, 3)) + { + R.getMat().convertTo(_R, CV_64F); + } + else if (R.total() == 3) + { + Rodrigues(R.getMat(), _R); + _R.convertTo(_R, CV_64F); + } + // stereo rectify so that stereo matching can be applied in one line + Mat R1, R2; + stereoRectify(_R, _T, R1, R2); + Mat undis1, undis2; + Matx33d _Knew = Matx33d(_K1); + if (!Knew.empty()) + { + Knew.getMat().convertTo(_Knew, CV_64F); + } + + undistortImage(image1.getMat(), undis1, _K1, _D1, xi1, flag, _Knew, newSize, R1); + undistortImage(image2.getMat(), undis2, _K2, _D2, xi2, flag, _Knew, newSize, R2); + + undis1.copyTo(image1Rec); + undis2.copyTo(image2Rec); + + // stereo matching by semi-global + Mat _disMap; + int channel = image1.channels(); + + //cv::StereoSGBM matching(0, numDisparities, SADWindowSize, 8*channel*SADWindowSize*SADWindowSize, 32*channel*SADWindowSize*SADWindowSize); + //matching(undis1, undis2, _depthMap); + Ptr sgbm = StereoSGBM::create(0, numDisparities, SADWindowSize, 8 * channel*SADWindowSize*SADWindowSize, 32 * channel*SADWindowSize*SADWindowSize); + + sgbm->compute(undis1, undis2, _disMap); + + // some regions of image1 is black, the corresponding regions of disparity map is also invalid. + Mat realDis; + _disMap.convertTo(_disMap, CV_32F); + Mat(_disMap/16.0f).convertTo(realDis, CV_32F); + + Mat grayImg, binaryImg, idx; + if (undis1.channels() == 3) + { + cvtColor(undis1, grayImg, COLOR_RGB2GRAY); + } + else + { + grayImg = undis1; + } + + binaryImg = (grayImg <= 0); + findNonZero(binaryImg, idx); + for (int i = 0; i < (int)idx.total(); ++i) + { + Vec2i _idx = idx.at(i); + realDis.at(_idx[1], _idx[0]) = 0.0f; + } + + disparity.create(realDis.size(), realDis.type()); + realDis.copyTo(disparity.getMat()); + + std::vector _pointCloud; + std::vector _pointCloudColor; + double baseline = cv::norm(T); + double f = _Knew(0, 0); + Matx33d K_inv = _Knew.inv(); + + std::vector rgb; + if (undis1.channels() == 3) + { + split(undis1, rgb); + } + + if (pointCloud.needed()) + { + for (int i = 0; i < newSize.width; ++i) + { + for(int j = 0; j < newSize.height; ++j) + { + Vec3f point; + Vec6f pointColor; + if (realDis.at(j, i) > 15) + { + float depth = float(baseline * f /realDis.at(j, i)); + // for RECTIFY_PERSPECTIVE, (x,y) are image plane points, + // for RECTIFY_LONGLATI, (x,y) are (theta, phi) angles + float x = float(K_inv(0,0) * i + K_inv(0,1) * j + K_inv(0,2)); + float y = float(K_inv(1,0) * i + K_inv(1,1) * j + K_inv(1,2)); + if (flag == omnidir::RECTIFY_LONGLATI) + { + point = Vec3f((float)-std::cos(x), (float)(-std::sin(x)*std::cos(y)), (float)(std::sin(x)*std::sin(y))) * depth; + } + else if(flag == omnidir::RECTIFY_PERSPECTIVE) + { + point = Vec3f(float(x), float(y), 1.0f) * depth; + } + if (pointType == XYZ) + { + _pointCloud.push_back(point); + } + else if (pointType == XYZRGB) + { + pointColor[0] = point[0]; + pointColor[1] = point[1]; + pointColor[2] = point[2]; + + if (undis1.channels() == 1) + { + pointColor[3] = float(undis1.at(j, i)); + pointColor[4] = pointColor[3]; + pointColor[5] = pointColor[3]; + } + else if (undis1.channels() == 3) + { + pointColor[3] = rgb[0].at(j, i); + pointColor[4] = rgb[1].at(j, i); + pointColor[5] = rgb[2].at(j, i); + } + _pointCloudColor.push_back(pointColor); + } + } + } + } + + if (pointType == XYZ) + { + Mat(_pointCloud).convertTo(pointCloud, CV_MAKE_TYPE(CV_32F, 3)); + } + else if (pointType == XYZRGB) + { + Mat(_pointCloudColor).convertTo(pointCloud, CV_MAKE_TYPE(CV_32F, 6)); + } + } +} + +void cv::omnidir::internal::encodeParameters(InputArray K, InputArrayOfArrays omAll, InputArrayOfArrays tAll, InputArray distoaration, double xi, OutputArray parameters) +{ + CV_Assert(K.type() == CV_64F && K.size() == Size(3,3)); + CV_Assert(distoaration.total() == 4 && distoaration.type() == CV_64F); + int n = (int)omAll.total(); + Mat _omAll = omAll.getMat(), _tAll = tAll.getMat(); + + Matx33d _K = K.getMat(); + Vec4d _D = (Vec4d)distoaration.getMat(); + parameters.create(1, 10+6*n,CV_64F); + Mat _params = parameters.getMat(); + for (int i = 0; i < n; i++) + { + Mat(_omAll.at(i)).reshape(1, 1).copyTo(_params.colRange(i*6, i*6+3)); + Mat(_tAll.at(i)).reshape(1, 1).copyTo(_params.colRange(i*6+3, (i+1)*6)); + } + + _params.at(0, 6*n) = _K(0,0); + _params.at(0, 6*n+1) = _K(1,1); + _params.at(0, 6*n+2) = _K(0,1); + _params.at(0, 6*n+3) = _K(0,2); + _params.at(0, 6*n+4) = _K(1,2); + _params.at(0, 6*n+5) = xi; + _params.at(0, 6*n+6) = _D[0]; + _params.at(0, 6*n+7) = _D[1]; + _params.at(0, 6*n+8) = _D[2]; + _params.at(0, 6*n+9) = _D[3]; +} + +void cv::omnidir::internal::encodeParametersStereo(InputArray K1, InputArray K2, InputArray om, InputArray T, InputArrayOfArrays omL, InputArrayOfArrays tL, + InputArray D1, InputArray D2, double xi1, double xi2, OutputArray parameters) +{ + CV_Assert(!K1.empty() && K1.type() == CV_64F && K1.size() == Size(3,3)); + CV_Assert(!K2.empty() && K2.type() == CV_64F && K2.size() == Size(3,3)); + CV_Assert(!om.empty() && om.type() == CV_64F && om.total() == 3); + CV_Assert(!T.empty() && T.type() == CV_64F && T.total() == 3); + CV_Assert(omL.total() == tL.total() && omL.type() == CV_64FC3 && tL.type() == CV_64FC3); + CV_Assert(D1.type() == CV_64F && D1.total() == 4 && D2.type() == CV_64F && D2.total() == 4); + + int n = (int)omL.total(); + // om, T, omL, tL, intrinsic left, intrinsic right + parameters.create(1, 20 + 6 * (n + 1), CV_64F); + + Mat _params = parameters.getMat(); + + om.getMat().reshape(1, 1).copyTo(_params.colRange(0, 3)); + T.getMat().reshape(1, 1).copyTo(_params.colRange(3, 6)); + for(int i = 0; i < n; ++i) + { + Mat(omL.getMat().at(i)).reshape(1, 1).copyTo(_params.colRange(6 + i*6, 6 + i*6 + 3)); + Mat(tL.getMat().at(i)).reshape(1, 1).copyTo(_params.colRange(6 + i*6 + 3, 6 + i*6 + 6)); + } + + Matx33d _K1 = K1.getMat(); + Matx33d _K2 = K2.getMat(); + Vec4d _D1 = D1.getMat(); + Vec4d _D2 = D2.getMat(); + _params.at(0, 6*(n+1)) = _K1(0,0); + _params.at(0, 6*(n+1)+1) = _K1(1,1); + _params.at(0, 6*(n+1)+2) = _K1(0,1); + _params.at(0, 6*(n+1)+3) = _K1(0,2); + _params.at(0, 6*(n+1)+4) = _K1(1,2); + _params.at(0, 6*(n+1)+5) = xi1; + _params.at(0, 6*(n+1)+6) = _D1[0]; + _params.at(0, 6*(n+1)+7) = _D1[1]; + _params.at(0, 6*(n+1)+8) = _D1[2]; + _params.at(0, 6*(n+1)+9) = _D1[3]; + + _params.at(0, 6*(n+1)+10) = _K2(0,0); + _params.at(0, 6*(n+1)+11) = _K2(1,1); + _params.at(0, 6*(n+1)+12) = _K2(0,1); + _params.at(0, 6*(n+1)+13) = _K2(0,2); + _params.at(0, 6*(n+1)+14) = _K2(1,2); + _params.at(0, 6*(n+1)+15) = xi2; + _params.at(0, 6*(n+1)+16) = _D2[0]; + _params.at(0, 6*(n+1)+17) = _D2[1]; + _params.at(0, 6*(n+1)+18) = _D2[2]; + _params.at(0, 6*(n+1)+19) = _D2[3]; +} + + + void cv::omnidir::internal::decodeParameters(InputArray parameters, OutputArray K, OutputArrayOfArrays omAll, OutputArrayOfArrays tAll, OutputArray distoration, double& xi) + { + if(K.empty()) + K.create(3,3,CV_64F); + Matx33d _K; + int n = (int)(parameters.total()-10)/6; + if(omAll.empty()) + omAll.create(1, n, CV_64FC3); + if(tAll.empty()) + tAll.create(1, n, CV_64FC3); + if(distoration.empty()) + distoration.create(1, 4, CV_64F); + Matx14d _D = distoration.getMat(); + Mat param = parameters.getMat(); + double *para = param.ptr(); + _K = Matx33d(para[6*n], para[6*n+2], para[6*n+3], + 0, para[6*n+1], para[6*n+4], + 0, 0, 1); + _D = Matx14d(para[6*n+6], para[6*n+7], para[6*n+8], para[6*n+9]); + xi = para[6*n+5]; + std::vector _omAll(n), _tAll(n); + for (int i = 0; i < n; i++) + { + _omAll[i] = Vec3d(param.colRange(i*6, i*6+3)); + _tAll[i] = Vec3d(param.colRange(i*6+3, i*6+6)); + } + Mat(_D).convertTo(distoration, CV_64F); + Mat(_K).convertTo(K, CV_64F); + + if (omAll.kind() == _InputArray::STD_VECTOR_MAT) + { + for (int i = 0; i < n; ++i) + { + Mat(_omAll[i]).copyTo(omAll.getMat(i)); + Mat(_tAll[i]).copyTo(tAll.getMat(i)); + } + } + else + { + Mat(_omAll).convertTo(omAll, CV_64FC3); + Mat(_tAll).convertTo(tAll, CV_64FC3); + } +} + + void cv::omnidir::internal::decodeParametersStereo(InputArray parameters, OutputArray K1, OutputArray K2, OutputArray om, OutputArray T, OutputArrayOfArrays omL, + OutputArrayOfArrays tL, OutputArray D1, OutputArray D2, double& xi1, double& xi2) + { + if(K1.empty()) + K1.create(3, 3, CV_64F); + if(K2.empty()) + K2.create(3, 3, CV_64F); + if(om.empty()) + om.create(3, 1, CV_64F); + if(T.empty()) + T.create(3, 1, CV_64F); + + int n = ((int)parameters.total() - 20) / 6 - 1; + + if(omL.empty()) + omL.create(1, n, CV_64FC3); + if(tL.empty()) + tL.create(1, n, CV_64FC3); + if(D1.empty()) + D1.create(1, 4, CV_64F); + if(D2.empty()) + D2.create(1, 4, CV_64F); + + Mat param = parameters.getMat().reshape(1, 1); + param.colRange(0, 3).reshape(1, 3).copyTo(om.getMat()); + param.colRange(3, 6).reshape(1, 3).copyTo(T.getMat()); + std::vector _omL, _tL; + + for(int i = 0; i < n; i++) + { + _omL.push_back(Vec3d(param.colRange(6 + i*6, 6 + i*6 + 3))); + _tL.push_back(Vec3d(param.colRange(6 + i*6 + 3, 6 + i*6 + 6))); + } + + double* para = param.ptr(); + int offset1 = (n + 1)*6; + Matx33d _K1(para[offset1], para[offset1+2], para[offset1+3], + 0, para[offset1+1], para[offset1+4], + 0, 0, 1); + xi1 = para[offset1+5]; + Matx14d _D1(para[offset1+6], para[offset1+7], para[offset1+8], para[offset1+9]); + + int offset2 = (n + 1)*6 + 10; + Matx33d _K2(para[offset2], para[offset2+2], para[offset2+3], + 0, para[offset2+1], para[offset2+4], + 0, 0, 1); + xi2 = para[offset2+5]; + Matx14d _D2(para[offset2+6], para[offset2+7], para[offset2+8], para[offset2+9]); + + Mat(_K1).convertTo(K1, CV_64F); + Mat(_D1).convertTo(D1, CV_64F); + Mat(_K2).convertTo(K2, CV_64F); + Mat(_D2).convertTo(D2, CV_64F); + if(omL.kind() == _InputArray::STD_VECTOR_MAT) + { + for(int i = 0; i < n; ++i) + { + Mat(_omL[i]).copyTo(omL.getMat(i)); + Mat(_tL[i]).copyTo(tL.getMat(i)); + } + } + else + { + Mat(_omL).convertTo(omL, CV_64FC3); + Mat(_tL).convertTo(tL, CV_64FC3); + } + } + +void cv::omnidir::internal::estimateUncertainties(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, InputArray parameters, + Mat& errors, Vec2d& std_error, double& rms, int flags) +{ + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints.empty() && imagePoints.type() == CV_64FC2); + CV_Assert(!parameters.empty() && parameters.type() == CV_64F); + + int n = (int) objectPoints.total(); + // assume every image has the same number of objectpoints + int nPointsAll = 0; + for (int i = 0; i < n; ++i) + { + nPointsAll += (int)objectPoints.getMat(i).total(); + } + + Mat reprojError = Mat(nPointsAll, 1, CV_64FC2); + + double* para = parameters.getMat().ptr(); + Matx33d K(para[6*n], para[6*n+2], para[6*n+3], + 0, para[6*n+1], para[6*n+4], + 0, 0, 1); + Matx14d D(para[6*n+6], para[6*n+7], para[6*n+8], para[6*n+9]); + double xi = para[6*n+5]; + int nPointsAccu = 0; + + for(int i=0; i < n; ++i) + { + Mat imgPoints, objPoints; + imagePoints.getMat(i).copyTo(imgPoints); + objectPoints.getMat(i).copyTo(objPoints); + imgPoints = imgPoints.reshape(2, imgPoints.rows*imgPoints.cols); + objPoints = objPoints.reshape(3, objPoints.rows*objPoints.cols); + + Mat om = parameters.getMat().colRange(i*6, i*6+3); + Mat T = parameters.getMat().colRange(i*6+3, (i+1)*6); + + Mat x; + omnidir::projectPoints(objPoints, x, om, T, K, xi, D, cv::noArray()); + + Mat errorx = (imgPoints - x); + + //reprojError.rowRange(errorx.rows*i, errorx.rows*(i+1)) = errorx.clone(); + errorx.copyTo(reprojError.rowRange(nPointsAccu, nPointsAccu + (int)errorx.total())); + nPointsAccu += (int)errorx.total(); + } + + meanStdDev(reprojError, noArray(), std_error); + std_error *= sqrt((double)reprojError.total()/((double)reprojError.total() - 1.0)); + + Mat sigma_x; + meanStdDev(reprojError.reshape(1,1), noArray(), sigma_x); + sigma_x *= sqrt(2.0*(double)reprojError.total()/(2.0*(double)reprojError.total() - 1.0)); + double s = sigma_x.at(0); + + Mat _JTJ_inv, _JTE; + computeJacobian(objectPoints, imagePoints, parameters, _JTJ_inv, _JTE, flags, 0.0); + sqrt(_JTJ_inv, _JTJ_inv); + + errors = 3 * s * _JTJ_inv.diag(); + + checkFixed(errors, flags, n); + + rms = 0; + const Vec2d* ptr_ex = reprojError.ptr(); + for (int i = 0; i < (int)reprojError.total(); i++) + { + rms += ptr_ex[i][0] * ptr_ex[i][0] + ptr_ex[i][1] * ptr_ex[i][1]; + } + + rms /= (double)reprojError.total(); + rms = sqrt(rms); +} + +// estimateUncertaintiesStereo +void cv::omnidir::internal::estimateUncertaintiesStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, + InputArray parameters, Mat& errors, Vec2d& std_error, double& rms, int flags) +{ + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints1.empty() && imagePoints1.type() == CV_64FC2 && imagePoints1.total() == objectPoints.total()); + CV_Assert(!imagePoints2.empty() && imagePoints2.type() == CV_64FC2 && imagePoints1.total() == imagePoints2.total()); + int n_img = (int)objectPoints.total(); + CV_Assert((int)parameters.total() == (6*(n_img+1)+20)); + + Mat _K1, _K2, _D1, _D2; + Vec3d _om, _T; + std::vector _omL(n_img), _tL(n_img); + Mat _parameters = parameters.getMat().reshape(1, 1); + double _xi1, _xi2; + internal::decodeParametersStereo(_parameters, _K1, _K2, _om, _T, _omL, _tL, _D1, _D2, _xi1, _xi2); + + int n_points = (int)objectPoints.getMat(0).total(); + Mat reprojErrorAll = Mat::zeros(2*n_points*n_img, 1, CV_64FC2); + + // error for left image + for (int i = 0; i < n_img; ++i) + { + Mat objPointsi, imgPointsi; + objectPoints.getMat(i).copyTo(objPointsi); + imagePoints1.getMat(i).copyTo(imgPointsi); + objPointsi = objPointsi.reshape(3, objPointsi.rows*objPointsi.cols); + imgPointsi = imgPointsi.reshape(2, imgPointsi.rows*imgPointsi.cols); + + Mat x; + omnidir::projectPoints(objPointsi, x, _omL[i], _tL[i], _K1, _xi1, _D1, cv::noArray()); + + Mat errorx = imgPointsi - x; + + errorx.copyTo(reprojErrorAll.rowRange(i*2*n_points, (i*2+1)*n_points)); + } + // error for right image + for (int i = 0; i < n_img; ++i) + { + Mat objPointsi, imgPointsi; + objectPoints.getMat(i).copyTo(objPointsi); + imagePoints2.getMat(i).copyTo(imgPointsi); + objPointsi = objPointsi.reshape(3, objPointsi.rows*objPointsi.cols); + imgPointsi = imgPointsi.reshape(2, imgPointsi.rows*imgPointsi.cols); + + Mat x; + Mat _R, _R2, _R1, _T2, _T1, _om2; + Rodrigues(_om, _R); + Rodrigues(_omL[i], _R1); + _T1 = Mat(_tL[i]); + _R2 = _R * _R1; + _T2 = _R * _T1 + Mat(_T); + Rodrigues(_R2, _om2); + + omnidir::projectPoints(objPointsi, x, _om2, _T2, _K2, _xi2, _D2, cv::noArray()); + + Mat errorx = imgPointsi - x; + + errorx.copyTo(reprojErrorAll.rowRange((i*2+1)*n_points, (i+1)*2*n_points)); + } + + meanStdDev(reprojErrorAll, cv::noArray(), std_error); + std_error *= sqrt((double)reprojErrorAll.total()/((double)reprojErrorAll.total() - 1.0)); + + Mat sigma_x; + meanStdDev(reprojErrorAll.reshape(1,1), noArray(), sigma_x); + sigma_x *= sqrt(2.0*(double)reprojErrorAll.total()/(2.0*(double)reprojErrorAll.total() - 1.0)); + double s = sigma_x.at(0); + + Mat _JTJ_inv, _JTE; + computeJacobianStereo(objectPoints, imagePoints1, imagePoints2, _parameters, _JTJ_inv, _JTE, flags, 0.0); + cv::sqrt(_JTJ_inv, _JTJ_inv); + + errors = 3 * s * _JTJ_inv.diag(); + + rms = 0; + + const Vec2d* ptr_ex = reprojErrorAll.ptr(); + for (int i = 0; i < (int)reprojErrorAll.total(); i++) + { + rms += ptr_ex[i][0] * ptr_ex[i][0] + ptr_ex[i][1] * ptr_ex[i][1]; + } + rms /= (double)reprojErrorAll.total(); + rms = sqrt(rms); +} + +// +double cv::omnidir::internal::computeMeanReproErr(InputArrayOfArrays imagePoints, InputArrayOfArrays proImagePoints) +{ + CV_Assert(!imagePoints.empty() && imagePoints.type()==CV_64FC2); + CV_Assert(!proImagePoints.empty() && proImagePoints.type() == CV_64FC2); + CV_Assert(imagePoints.total() == proImagePoints.total()); + + int n = (int)imagePoints.total(); + double reprojError = 0; + int totalPoints = 0; + if (imagePoints.kind() == _InputArray::STD_VECTOR_MAT) + { + for (int i = 0; i < n; i++) + { + Mat x, proj_x; + imagePoints.getMat(i).copyTo(x); + proImagePoints.getMat(i).copyTo(proj_x); + Mat errorI = x.reshape(2, x.rows*x.cols) - proj_x.reshape(2, proj_x.rows*proj_x.cols); + //Mat errorI = imagePoints.getMat(i) - proImagePoints.getMat(i); + totalPoints += (int)errorI.total(); + Vec2d* ptr_err = errorI.ptr(); + for (int j = 0; j < (int)errorI.total(); j++) + { + reprojError += sqrt(ptr_err[j][0]*ptr_err[j][0] + ptr_err[j][1]*ptr_err[j][1]); + } + } + } + else + { + Mat x, proj_x; + imagePoints.getMat().copyTo(x); + proImagePoints.getMat().copyTo(proj_x); + Mat errorI = x.reshape(2, x.rows*x.cols) - proj_x.reshape(2, proj_x.rows*proj_x.cols); + //Mat errorI = imagePoints.getMat() - proImagePoints.getMat(); + totalPoints += (int)errorI.total(); + Vec2d* ptr_err = errorI.ptr(); + for (int j = 0; j < (int)errorI.total(); j++) + { + reprojError += sqrt(ptr_err[j][0]*ptr_err[j][0] + ptr_err[j][1]*ptr_err[j][1]); + } + } + double meanReprojError = reprojError / totalPoints; + return meanReprojError; +} + +double cv::omnidir::internal::computeMeanReproErr(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, InputArray K, InputArray D, double xi, InputArrayOfArrays omAll, + InputArrayOfArrays tAll) +{ + CV_Assert(objectPoints.total() == imagePoints.total()); + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints.empty() && imagePoints.type() == CV_64FC2); + std::vector proImagePoints; + int n = (int)objectPoints.total(); + Mat _omAll = omAll.getMat(); + Mat _tAll = tAll.getMat(); + for(int i = 0; i < n; ++i) + { + Mat imgPoint; + //cv::omnidir::projectPoints(objetPoints.getMat(i), imgPoint, omAll.getMat(i), tAll.getMat(i), K.getMat(), xi, D.getMat(), noArray()); + cv::omnidir::projectPoints(objectPoints.getMat(i), imgPoint, _omAll.at(i), _tAll.at(i), K.getMat(), xi, D.getMat(), noArray()); + proImagePoints.push_back(imgPoint); + } + + return internal::computeMeanReproErr(imagePoints, proImagePoints); +} + +double cv::omnidir::internal::computeMeanReproErrStereo(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputArray K1, InputArray K2, + InputArray D1, InputArray D2, double xi1, double xi2, InputArray om, InputArray T, InputArrayOfArrays omL, InputArrayOfArrays TL) +{ + CV_Assert(objectPoints.total() == imagePoints1.total() && imagePoints1.total() == imagePoints2.total()); + CV_Assert(!objectPoints.empty() && objectPoints.type() == CV_64FC3); + CV_Assert(!imagePoints1.empty() && imagePoints1.type() == CV_64FC2); + CV_Assert(!imagePoints2.empty() && imagePoints2.type() == CV_64FC2); + + std::vector proImagePoints1, proImagePoints2; + int n = (int)objectPoints.total(); + Mat _omL = omL.getMat(), _TL = TL.getMat(); + Mat _om = om.getMat(), _R, _T = T.getMat(); + Rodrigues(_om, _R); + Mat _K1 = K1.getMat(), _K2 = K2.getMat(); + Mat _D1 = D1.getMat(), _D2 = D2.getMat(); + + // reprojection error for left image + for (int i = 0; i < n; ++i) + { + Mat imgPoints; + cv::omnidir::projectPoints(objectPoints.getMat(i), imgPoints, _omL.at(i), _TL.at(i), _K1, xi1, _D1, cv::noArray()); + proImagePoints1.push_back(imgPoints); + } + + // reprojection error for right image + for (int i = 0; i < n; ++i) + { + Mat imgPoints; + Mat _omRi,_RRi,_TRi,_RLi, _TLi; + Rodrigues(_omL.at(i), _RLi); + _TLi = Mat(_TL.at(i)).reshape(1, 3); + _RRi = _R * _RLi; + _TRi = _R * _TLi + _T; + Rodrigues(_RRi, _omRi); + cv::omnidir::projectPoints(objectPoints.getMat(i), imgPoints, _omRi, _TRi, _K2, xi2, _D2, cv::noArray()); + proImagePoints2.push_back(imgPoints); + } + double reProErr1 = internal::computeMeanReproErr(imagePoints1, proImagePoints1); + double reProErr2 = internal::computeMeanReproErr(imagePoints2, proImagePoints2); + + double reProErr = (reProErr1 + reProErr2) / 2.0; + //double reProErr = reProErr1*reProErr1 + reProErr2* reProErr2; + return reProErr; +} + +void cv::omnidir::internal::checkFixed(Mat& G, int flags, int n) +{ + int _flags = flags; + if(_flags >= omnidir::CALIB_FIX_CENTER) + { + G.at(6*n+3) = 0; + G.at(6*n+4) = 0; + _flags -= omnidir::CALIB_FIX_CENTER; + } + if(_flags >= omnidir::CALIB_FIX_GAMMA) + { + G.at(6*n) = 0; + G.at(6*n+1) = 0; + _flags -= omnidir::CALIB_FIX_GAMMA; + } + if(_flags >= omnidir::CALIB_FIX_XI) + { + G.at(6*n + 5) = 0; + _flags -= omnidir::CALIB_FIX_XI; + } + if(_flags >= omnidir::CALIB_FIX_P2) + { + G.at(6*n + 9) = 0; + _flags -= omnidir::CALIB_FIX_P2; + } + if(_flags >= omnidir::CALIB_FIX_P1) + { + G.at(6*n + 8) = 0; + _flags -= omnidir::CALIB_FIX_P1; + } + if(_flags >= omnidir::CALIB_FIX_K2) + { + G.at(6*n + 7) = 0; + _flags -= omnidir::CALIB_FIX_K2; + } + if(_flags >= omnidir::CALIB_FIX_K1) + { + G.at(6*n + 6) = 0; + _flags -= omnidir::CALIB_FIX_K1; + } + if(_flags >= omnidir::CALIB_FIX_SKEW) + { + G.at(6*n + 2) = 0; + } +} + +// This function is from fisheye.cpp +void cv::omnidir::internal::subMatrix(const Mat& src, Mat& dst, const std::vector& cols, const std::vector& rows) +{ + CV_Assert(src.type() == CV_64FC1); + + int nonzeros_cols = cv::countNonZero(cols); + Mat tmp(src.rows, nonzeros_cols, CV_64FC1); + + for (int i = 0, j = 0; i < (int)cols.size(); i++) + { + if (cols[i]) + { + src.col(i).copyTo(tmp.col(j++)); + } + } + + int nonzeros_rows = cv::countNonZero(rows); + Mat tmp1(nonzeros_rows, nonzeros_cols, CV_64FC1); + for (int i = 0, j = 0; i < (int)rows.size(); i++) + { + if (rows[i]) + { + tmp.row(i).copyTo(tmp1.row(j++)); + } + } + + dst = tmp1.clone(); +} + +void cv::omnidir::internal::flags2idx(int flags, std::vector& idx, int n) +{ + idx = std::vector(6*n+10,1); + int _flags = flags; + if(_flags >= omnidir::CALIB_FIX_CENTER) + { + idx[6*n+3] = 0; + idx[6*n+4] = 0; + _flags -= omnidir::CALIB_FIX_CENTER; + } + if(_flags >= omnidir::CALIB_FIX_GAMMA) + { + idx[6*n] = 0; + idx[6*n+1] = 0; + _flags -= omnidir::CALIB_FIX_GAMMA; + } + if(_flags >= omnidir::CALIB_FIX_XI) + { + idx[6*n + 5] = 0; + _flags -= omnidir::CALIB_FIX_XI; + } + if(_flags >= omnidir::CALIB_FIX_P2) + { + idx[6*n + 9] = 0; + _flags -= omnidir::CALIB_FIX_P2; + } + if(_flags >= omnidir::CALIB_FIX_P1) + { + idx[6*n + 8] = 0; + _flags -= omnidir::CALIB_FIX_P1; + } + if(_flags >= omnidir::CALIB_FIX_K2) + { + idx[6*n + 7] = 0; + _flags -= omnidir::CALIB_FIX_K2; + } + if(_flags >= omnidir::CALIB_FIX_K1) + { + idx[6*n + 6] = 0; + _flags -= omnidir::CALIB_FIX_K1; + } + if(_flags >= omnidir::CALIB_FIX_SKEW) + { + idx[6*n + 2] = 0; + } +} + +void cv::omnidir::internal::flags2idxStereo(int flags, std::vector& idx, int n) +{ + idx = std::vector(6*(n+1)+20, 1); + int _flags = flags; + int offset1 = 6*(n+1); + int offset2 = offset1 + 10; + if(_flags >= omnidir::CALIB_FIX_CENTER) + { + idx[offset1+3] = 0; + idx[offset1+4] = 0; + idx[offset2+3] = 0; + idx[offset2+4] = 0; + _flags -= omnidir::CALIB_FIX_CENTER; + } + if(_flags >= omnidir::CALIB_FIX_GAMMA) + { + idx[offset1] = 0; + idx[offset1+1] = 0; + idx[offset2] = 0; + idx[offset2+1] = 0; + _flags -= omnidir::CALIB_FIX_GAMMA; + } + if(_flags >= omnidir::CALIB_FIX_XI) + { + idx[offset1 + 5] = 0; + idx[offset2 + 5] = 0; + _flags -= omnidir::CALIB_FIX_XI; + } + if(_flags >= omnidir::CALIB_FIX_P2) + { + idx[offset1 + 9] = 0; + idx[offset2 + 9] = 0; + _flags -= omnidir::CALIB_FIX_P2; + } + if(_flags >= omnidir::CALIB_FIX_P1) + { + idx[offset1 + 8] = 0; + idx[offset2 + 8] = 0; + _flags -= omnidir::CALIB_FIX_P1; + } + if(_flags >= omnidir::CALIB_FIX_K2) + { + idx[offset1 + 7] = 0; + idx[offset2 + 7] = 0; + _flags -= omnidir::CALIB_FIX_K2; + } + if(_flags >= omnidir::CALIB_FIX_K1) + { + idx[offset1 + 6] = 0; + idx[offset2 + 6] = 0; + _flags -= omnidir::CALIB_FIX_K1; + } + if(_flags >= omnidir::CALIB_FIX_SKEW) + { + idx[offset1 + 2] = 0; + idx[offset2 + 2] = 0; + } +} + +// fill in zerso for fixed parameters +void cv::omnidir::internal::fillFixed(Mat&G, int flags, int n) +{ + Mat tmp = G.clone(); + std::vector idx(6*n + 10, 1); + flags2idx(flags, idx, n); + G.release(); + G.create(6*n +10, 1, CV_64F); + G = cv::Mat::zeros(6*n +10, 1, CV_64F); + for (int i = 0,j=0; i < (int)idx.size(); i++) + { + if (idx[i]) + { + G.at(i) = tmp.at(j++); + } + } +} + +void cv::omnidir::internal::fillFixedStereo(Mat& G, int flags, int n) +{ + Mat tmp = G.clone(); + std::vector idx(6*(n+1)+20, 1); + flags2idxStereo(flags, idx, n); + G.release(); + G.create(6 * (n+1) + 20, 1, CV_64F); + G = cv::Mat::zeros(6* (n + 1) + 20, 1, CV_64F); + for (int i = 0,j=0; i < (int)idx.size(); i++) + { + if (idx[i]) + { + G.at(i) = tmp.at(j++); + } + } +} + +double cv::omnidir::internal::findMedian(const Mat& row) +{ + CV_Assert(!row.empty() && row.rows == 1 && row.type() == CV_64F); + Mat tmp = row.clone(); + cv::sort(tmp, tmp, 0); + if((int)tmp.total()%2 == 0) + return tmp.at((int)tmp.total() / 2); + else + return 0.5 * (tmp.at((int)tmp.total() / 2) + tmp.at((int)tmp.total()/2 - 1)); +} + +cv::Vec3d cv::omnidir::internal::findMedian3(InputArray mat) +{ + CV_Assert(mat.depth() == CV_64F && mat.getMat().rows == 1); + Mat M = Mat(mat.getMat().t()).reshape(1).t(); + return Vec3d(findMedian(M.row(0)), findMedian(M.row(1)), findMedian(M.row(2))); +} + +void cv::omnidir::stereoRectify(InputArray R, InputArray T, OutputArray R1, OutputArray R2) +{ + CV_Assert((R.size() == Size(3,3) || R.total() == 3) && (R.depth() == CV_32F || R.depth() == CV_64F)); + CV_Assert(T.total() == 3 && (T.depth() == CV_32F || T.depth() == CV_64F)); + + Mat _R, _T; + if (R.size() == Size(3, 3)) + { + R.getMat().convertTo(_R, CV_64F); + } + else if (R.total() == 3) + { + Rodrigues(R.getMat(), _R); + _R.convertTo(_R, CV_64F); + } + + T.getMat().reshape(1, 3).convertTo(_T, CV_64F); + + R1.create(3, 3, CV_64F); + Mat _R1 = R1.getMat(); + R2.create(3, 3, CV_64F); + Mat _R2 = R2.getMat(); + + Mat R21 = _R.t(); + Mat T21 = -_R.t() * _T; + + Mat e1, e2, e3; + e1 = T21.t() / norm(T21); + e2 = Mat(Matx13d(T21.at(1)*-1, T21.at(0), 0.0)); + e2 = e2 / norm(e2); + e3 = e1.cross(e2); + e3 = e3 / norm(e3); + e1.copyTo(_R1.row(0)); + e2.copyTo(_R1.row(1)); + e3.copyTo(_R1.row(2)); + _R2 = R21 * _R1; + +} + +void cv::omnidir::internal::getInterset(InputArray idx1, InputArray idx2, OutputArray inter1, OutputArray inter2, + OutputArray inter_ori) +{ + Mat _idx1 = idx1.getMat(); + Mat _idx2 = idx2.getMat(); + + int n1 = (int)idx1.total(); + int n2 = (int)idx2.total(); + + std::vector _inter1, _inter2, _inter_ori; + for (int i = 0; i < n1; ++i) + { + for (int j = 0; j < n2; ++j) + { + if(_idx1.at(i) == _idx2.at(j)) + { + _inter1.push_back(i); + _inter2.push_back(j); + _inter_ori.push_back(_idx1.at(i)); + } + } + } + + inter1.create(1, (int)_inter1.size(), CV_32S); + inter2.create(1, (int)_inter2.size(), CV_32S); + inter_ori.create(1, (int)_inter_ori.size(), CV_32S); + + for (int i = 0; i < (int)_inter1.size(); ++i) + { + inter1.getMat().at(i) = _inter1[i]; + } + for (int i = 0; i < (int)_inter2.size(); ++i) + { + inter2.getMat().at(i) = _inter2[i]; + } + for (int i = 0; i < (int)_inter_ori.size(); ++i) + { + inter_ori.getMat().at(i) = _inter_ori[i]; + } +} \ No newline at end of file diff --git a/modules/ccalib/src/precomp.hpp b/modules/ccalib/src/precomp.hpp index f52c72719..b2ced45da 100644 --- a/modules/ccalib/src/precomp.hpp +++ b/modules/ccalib/src/precomp.hpp @@ -1,51 +1,52 @@ /*M/////////////////////////////////////////////////////////////////////////////////////// - // - // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. - // - // By downloading, copying, installing or using the software you agree to this license. - // If you do not agree to this license, do not download, install, - // copy or use the software. - // - // - // License Agreement - // For Open Source Computer Vision Library - // - // Copyright (C) 2014, OpenCV Foundation, all rights reserved. - // Third party copyrights are property of their respective owners. - // - // Redistribution and use in source and binary forms, with or without modification, - // are permitted provided that the following conditions are met: - // - // * Redistribution's of source code must retain the above copyright notice, - // this list of conditions and the following disclaimer. - // - // * Redistribution's 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. - // - // * The name of the copyright holders may not 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 Intel Corporation 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. - // - //M*/ +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ -#ifndef __OPENCV_CCALIB_PRECOMP__ -#define __OPENCV_CCALIB_PRECOMP__ +#ifndef __OPENCV_PRECOMP_H__ +#define __OPENCV_PRECOMP_H__ #include #include #include - +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" #include - #endif diff --git a/modules/ccalib/src/randpattern.cpp b/modules/ccalib/src/randpattern.cpp new file mode 100644 index 000000000..bde3978fb --- /dev/null +++ b/modules/ccalib/src/randpattern.cpp @@ -0,0 +1,395 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2015, Baisheng Lai (laibaisheng@gmail.com), Zhejiang University, +// all rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +/** + * This module was accepted as a GSoC 2015 project for OpenCV, authored by + * Baisheng Lai, mentored by Bo Li. + + * This module implements points extraction from a "random" pattern image. + * It returns 3D object points and 2D image pixels that can be used for calibration. + * Compared with traditional calibration object like chessboard, it is useful when pattern is + * partly occluded or only a part of pattern can be observed in multiple cameras calibration. + * For detail, refer to this paper + * B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System + * Calibration Toolbox Using A Feature Descriptor-Based Calibration + * Pattern", in IROS 2013. + */ +#include "precomp.hpp" +#include "opencv2/ccalib/randpattern.hpp" +#include +using namespace std; + +namespace cv { namespace randpattern { +RandomPatternCornerFinder::RandomPatternCornerFinder(float patternWidth, float patternHeight, + int nminiMatch, int depth, int verbose, int showExtraction, Ptr detector, Ptr descriptor, + Ptr matcher) +{ + _patternHeight = patternHeight; + _patternWidth = patternWidth; + _nminiMatch = nminiMatch; + _objectPonits.resize(0); + _imagePoints.resize(0); + _depth = depth; + _detector = detector; + _descriptor = descriptor; + _matcher = matcher; + _showExtraction = showExtraction; + _verbose = verbose; +} + +void RandomPatternCornerFinder::computeObjectImagePoints(std::vector inputImages) +{ + CV_Assert(!_patternImage.empty()); + CV_Assert(inputImages.size() > 0); + + int nImages = (int)inputImages.size(); + std::vector imageObjectPoints; + for (int i = 0; i < nImages; ++i) + { + imageObjectPoints = computeObjectImagePointsForSingle(inputImages[i]); + if ((int)imageObjectPoints[0].total() > _nminiMatch) + { + _imagePoints.push_back(imageObjectPoints[0]); + _objectPonits.push_back(imageObjectPoints[1]); + } + } +} + +void RandomPatternCornerFinder::keyPoints2MatchedLocation(const std::vector& imageKeypoints, + const std::vector& patternKeypoints, const std::vector matchces, + cv::Mat& matchedImagelocation, cv::Mat& matchedPatternLocation) +{ + matchedImagelocation.release(); + matchedPatternLocation.release(); + std::vector image, pattern; + for (int i = 0; i < (int)matchces.size(); ++i) + { + Point2f imgPt = imageKeypoints[matchces[i].queryIdx].pt; + Point2f patPt = patternKeypoints[matchces[i].trainIdx].pt; + image.push_back(Vec2d(imgPt.x, imgPt.y)); + pattern.push_back(Vec2d(patPt.x, patPt.y)); + } + Mat(image).convertTo(matchedImagelocation, CV_64FC2); + Mat(pattern).convertTo(matchedPatternLocation, CV_64FC2); +} + +void RandomPatternCornerFinder::getFilteredLocation(cv::Mat& imageKeypoints, cv::Mat& patternKeypoints, const cv::Mat mask) +{ + Mat tmpKeypoint, tmpPattern; + imageKeypoints.copyTo(tmpKeypoint); + patternKeypoints.copyTo(tmpPattern); + imageKeypoints.release(); + patternKeypoints.release(); + std::vector vecKeypoint, vecPattern; + for(int i = 0; i < (int)mask.total(); ++i) + { + if (mask.at(i) == 1) + { + vecKeypoint.push_back(tmpKeypoint.at(i)); + vecPattern.push_back(tmpPattern.at(i)); + } + } + Mat(vecKeypoint).convertTo(imageKeypoints, CV_64FC2); + Mat(vecPattern).convertTo(patternKeypoints, CV_64FC2); +} + +void RandomPatternCornerFinder::getObjectImagePoints(const cv::Mat& imageKeypoints, const cv::Mat& patternKeypoints) +{ + Mat imagePoints_i, objectPoints_i; + int imagePointsType = CV_MAKETYPE(_depth, 2); + int objectPointsType = CV_MAKETYPE(_depth, 3); + imageKeypoints.convertTo(imagePoints_i, imagePointsType); + _imagePoints.push_back(imagePoints_i); + if (patternKeypoints.total()!=CV_64FC2) + patternKeypoints.convertTo(patternKeypoints, CV_64FC2); + + std::vector objectPoints; + + for (int i = 0; i < (int)patternKeypoints.total(); ++i) + { + double x = patternKeypoints.at(i)[0]; + double y = patternKeypoints.at(i)[1]; + x = x / _patternImageSize.width * _patternWidth; + y = y / _patternImageSize.height * _patternHeight; + objectPoints.push_back(Vec3d(x, y, 0)); + } + + Mat(objectPoints).convertTo(objectPoints_i, objectPointsType); + _objectPonits.push_back(objectPoints_i); +} + +void RandomPatternCornerFinder::crossCheckMatching( Ptr& descriptorMatcher, + const Mat& descriptors1, const Mat& descriptors2, + std::vector& filteredMatches12, int knn ) +{ + filteredMatches12.clear(); + std::vector > matches12, matches21; + descriptorMatcher->knnMatch( descriptors1, descriptors2, matches12, knn ); + descriptorMatcher->knnMatch( descriptors2, descriptors1, matches21, knn ); + for( size_t m = 0; m < matches12.size(); m++ ) + { + bool findCrossCheck = false; + for( size_t fk = 0; fk < matches12[m].size(); fk++ ) + { + DMatch forward = matches12[m][fk]; + + for( size_t bk = 0; bk < matches21[forward.trainIdx].size(); bk++ ) + { + DMatch backward = matches21[forward.trainIdx][bk]; + if( backward.trainIdx == forward.queryIdx ) + { + filteredMatches12.push_back(forward); + findCrossCheck = true; + break; + } + } + if( findCrossCheck ) break; + } + } +} + +void RandomPatternCornerFinder::drawCorrespondence(const Mat& image1, const std::vector keypoint1, + const Mat& image2, const std::vector keypoint2, const std::vector matchces, + const Mat& mask1, const Mat& mask2, const int step) +{ + Mat img_corr; + if(step == 1) + { + drawMatches(image1, keypoint1, image2, keypoint2, matchces, img_corr); + } + else if(step == 2) + { + std::vector matchesFilter; + for (int i = 0; i < (int)mask1.total(); ++i) + { + if (!mask1.empty() && mask1.at(i) == 1) + { + matchesFilter.push_back(matchces[i]); + } + } + drawMatches(image1, keypoint1, image2, keypoint2, matchesFilter, img_corr); + } + else if(step == 3) + { + std::vector matchesFilter; + int j = 0; + for (int i = 0; i < (int)mask1.total(); ++i) + { + if (mask1.at(i) == 1) + { + if (!mask2.empty() && mask2.at(j) == 1) + { + matchesFilter.push_back(matchces[i]); + } + j++; + } + } + drawMatches(image1, keypoint1, image2, keypoint2, matchesFilter, img_corr); + } + imshow("correspondence", img_corr); + waitKey(0); +} + +std::vector RandomPatternCornerFinder::getObjectPoints() +{ + return _objectPonits; +} + +std::vector RandomPatternCornerFinder::getImagePoints() +{ + return _imagePoints; +} + +void RandomPatternCornerFinder::loadPattern(cv::Mat patternImage) +{ + _patternImage = patternImage.clone(); + if (_patternImage.type()!= CV_8U) + _patternImage.convertTo(_patternImage, CV_8U); + _patternImageSize = _patternImage.size(); + _detector->detect(patternImage, _keypointsPattern); + _descriptor->compute(patternImage, _keypointsPattern, _descriptorPattern); + _descriptorPattern.convertTo(_descriptorPattern, CV_32F); +} + +std::vector RandomPatternCornerFinder::computeObjectImagePointsForSingle(cv::Mat inputImage) +{ + CV_Assert(!_patternImage.empty()); + std::vector r(2); + Mat descriptorImage1, descriptorImage2,descriptorImage; + std::vector keypointsImage1, keypointsImage2, keypointsImage; + if (inputImage.type()!=CV_8U) + { + inputImage.convertTo(inputImage, CV_8U); + } + + Mat imageEquHist; + equalizeHist(inputImage, imageEquHist); + + _detector->detect(inputImage, keypointsImage1); + _descriptor->compute(inputImage, keypointsImage1, descriptorImage1); + _detector->detect(imageEquHist, keypointsImage2); + _descriptor->compute(imageEquHist, keypointsImage2, descriptorImage2); + descriptorImage1.convertTo(descriptorImage1, CV_32F); + descriptorImage2.convertTo(descriptorImage2, CV_32F); + + // match with pattern + std::vector matchesImgtoPat, matchesImgtoPat1, matchesImgtoPat2; + + cv::Mat keypointsImageLocation, keypointsPatternLocation; + + crossCheckMatching(this->_matcher, descriptorImage1, this->_descriptorPattern, matchesImgtoPat1, 1); + crossCheckMatching(this->_matcher, descriptorImage2, this->_descriptorPattern, matchesImgtoPat2, 1); + if ((int)matchesImgtoPat1.size() > (int)matchesImgtoPat2.size()) + { + matchesImgtoPat = matchesImgtoPat1; + keypointsImage = keypointsImage1; + } + else + { + matchesImgtoPat = matchesImgtoPat2; + keypointsImage = keypointsImage2; + } + + keyPoints2MatchedLocation(keypointsImage, this->_keypointsPattern, matchesImgtoPat, + keypointsImageLocation, keypointsPatternLocation); + + Mat img_corr; + + // innerMask is CV_8U type + Mat innerMask1, innerMask2; + + // draw raw correspondence + if(this->_showExtraction) + { + drawCorrespondence(inputImage, keypointsImage, _patternImage, _keypointsPattern, matchesImgtoPat, + innerMask1, innerMask2, 1); + } + + if (_verbose) + { + std::cout << "number of matched points " << (int)keypointsImageLocation.total() << std::endl; + } + // outlier remove + findFundamentalMat(keypointsImageLocation, keypointsPatternLocation, + FM_RANSAC, 1, 0.995, innerMask1); + getFilteredLocation(keypointsImageLocation, keypointsPatternLocation, innerMask1); + + if (this->_showExtraction) + { + drawCorrespondence(inputImage, keypointsImage, _patternImage, _keypointsPattern, matchesImgtoPat, + innerMask1, innerMask2, 2); + } + + findHomography(keypointsImageLocation, keypointsPatternLocation, RANSAC, 30*inputImage.cols/1000, innerMask2); + getFilteredLocation(keypointsImageLocation, keypointsPatternLocation, innerMask2); + + if (_verbose) + { + std::cout << "number of filtered points " << (int)keypointsImageLocation.total() << std::endl; + } + + // draw filtered correspondence + if (this->_showExtraction) + { + drawCorrespondence(inputImage, keypointsImage, _patternImage, _keypointsPattern, matchesImgtoPat, + innerMask1, innerMask2, 3); + } + + std::vector objectPoints; + + int imagePointsType = CV_MAKETYPE(_depth, 2); + int objectPointsType = CV_MAKETYPE(_depth, 3); + + keypointsImageLocation.convertTo(r[0], imagePointsType); + + for (int i = 0; i < (int)keypointsPatternLocation.total(); ++i) + { + double x = keypointsPatternLocation.at(i)[0]; + double y = keypointsPatternLocation.at(i)[1]; + x = x / _patternImageSize.width * _patternWidth; + y = y / _patternImageSize.height * _patternHeight; + objectPoints.push_back(Vec3d(x, y, 0)); + } + Mat(objectPoints).convertTo(r[1], objectPointsType); + return r; +} + +RandomPatternGenerator::RandomPatternGenerator(int imageWidth, int imageHeight) +{ + _imageWidth = imageWidth; + _imageHeight = imageHeight; +} + +void RandomPatternGenerator::generatePattern() +{ + Mat pattern = Mat(_imageHeight, _imageWidth, CV_32F, Scalar(0.)); + + int m = 5; + int count = 0; + + while(m < _imageWidth) + { + int n = (int)std::floor(double(_imageHeight) / double(_imageWidth) * double(m)) + 1; + + Mat r = Mat(n, m, CV_32F); + cv::randn(r, Scalar::all(0), Scalar::all(1)); + cv::resize(r, r, Size(_imageWidth ,_imageHeight)); + double min_r, max_r; + minMaxLoc(r, &min_r, &max_r); + + r = (r - (float)min_r) / float(max_r - min_r); + + pattern += r; + count += 1; + m *= 2; + } + pattern = pattern / count * 255; + pattern.convertTo(pattern, CV_8U); + equalizeHist(pattern, pattern); + pattern.copyTo(_pattern); +} + +cv::Mat RandomPatternGenerator::getPattern() +{ + return _pattern; +} + +}} //namespace randpattern, cv \ No newline at end of file diff --git a/modules/ccalib/tutorial/data/omni_calib_data.xml b/modules/ccalib/tutorial/data/omni_calib_data.xml new file mode 100644 index 000000000..883eee51d --- /dev/null +++ b/modules/ccalib/tutorial/data/omni_calib_data.xml @@ -0,0 +1,1146 @@ + + + + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0. + <_ type_id="opencv-matrix"> + 54 + 1 +
"3d"
+ + 0. 0. 0. 2.0000000000000001e-001 0. 0. 4.0000000000000002e-001 0. + 0. 6.0000000000000009e-001 0. 0. 8.0000000000000004e-001 0. 0. 1. + 0. 0. 0. 2.0000000000000001e-001 0. 2.0000000000000001e-001 + 2.0000000000000001e-001 0. 4.0000000000000002e-001 + 2.0000000000000001e-001 0. 6.0000000000000009e-001 + 2.0000000000000001e-001 0. 8.0000000000000004e-001 + 2.0000000000000001e-001 0. 1. 2.0000000000000001e-001 0. 0. + 4.0000000000000002e-001 0. 2.0000000000000001e-001 + 4.0000000000000002e-001 0. 4.0000000000000002e-001 + 4.0000000000000002e-001 0. 6.0000000000000009e-001 + 4.0000000000000002e-001 0. 8.0000000000000004e-001 + 4.0000000000000002e-001 0. 1. 4.0000000000000002e-001 0. 0. + 6.0000000000000009e-001 0. 2.0000000000000001e-001 + 6.0000000000000009e-001 0. 4.0000000000000002e-001 + 6.0000000000000009e-001 0. 6.0000000000000009e-001 + 6.0000000000000009e-001 0. 8.0000000000000004e-001 + 6.0000000000000009e-001 0. 1. 6.0000000000000009e-001 0. 0. + 8.0000000000000004e-001 0. 2.0000000000000001e-001 + 8.0000000000000004e-001 0. 4.0000000000000002e-001 + 8.0000000000000004e-001 0. 6.0000000000000009e-001 + 8.0000000000000004e-001 0. 8.0000000000000004e-001 + 8.0000000000000004e-001 0. 1. 8.0000000000000004e-001 0. 0. 1. 0. + 2.0000000000000001e-001 1. 0. 4.0000000000000002e-001 1. 0. + 6.0000000000000009e-001 1. 0. 8.0000000000000004e-001 1. 0. 1. 1. + 0. 0. 1.2000000000000002e+000 0. 2.0000000000000001e-001 + 1.2000000000000002e+000 0. 4.0000000000000002e-001 + 1.2000000000000002e+000 0. 6.0000000000000009e-001 + 1.2000000000000002e+000 0. 8.0000000000000004e-001 + 1.2000000000000002e+000 0. 1. 1.2000000000000002e+000 0. 0. + 1.4000000000000001e+000 0. 2.0000000000000001e-001 + 1.4000000000000001e+000 0. 4.0000000000000002e-001 + 1.4000000000000001e+000 0. 6.0000000000000009e-001 + 1.4000000000000001e+000 0. 8.0000000000000004e-001 + 1.4000000000000001e+000 0. 1. 1.4000000000000001e+000 0. 0. + 1.6000000000000001e+000 0. 2.0000000000000001e-001 + 1.6000000000000001e+000 0. 4.0000000000000002e-001 + 1.6000000000000001e+000 0. 6.0000000000000009e-001 + 1.6000000000000001e+000 0. 8.0000000000000004e-001 + 1.6000000000000001e+000 0. 1. 1.6000000000000001e+000 0.
+ + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 6.75490112e+002 2.58054169e+002 6.56950867e+002 2.73248138e+002 + 6.36838318e+002 2.90432434e+002 6.16385193e+002 3.13483246e+002 + 5.91500000e+002 337. 569. 359. 6.61358582e+002 2.31272415e+002 + 6.40136780e+002 2.45905136e+002 6.18555176e+002 2.64595276e+002 + 5.92727356e+002 2.85703613e+002 5.65221863e+002 3.12442780e+002 + 5.42423889e+002 3.41452393e+002 6.43457520e+002 2.03086868e+002 + 6.21402466e+002 2.17740417e+002 5.93600830e+002 2.37447601e+002 + 5.65232788e+002 2.59174164e+002 5.37838196e+002 2.84915863e+002 + 5.12503052e+002 3.16757507e+002 6.24005432e+002 1.74736618e+002 + 5.97496338e+002 1.88732834e+002 5.67288635e+002 2.07220291e+002 + 5.38015198e+002 2.30461014e+002 5.07095947e+002 2.58994263e+002 + 4.77491852e+002 2.92051727e+002 6.01037720e+002 1.46273209e+002 + 5.73469177e+002 1.59748337e+002 5.40935669e+002 1.77509201e+002 + 5.06503784e+002 2.02032761e+002 4.74068848e+002 2.32182053e+002 + 4.42500122e+002 2.66570831e+002 5.77138550e+002 1.19448029e+002 + 5.45628052e+002 1.32241302e+002 5.11336334e+002 1.50559265e+002 + 4.76117249e+002 1.75316269e+002 4.40502075e+002 2.05725952e+002 + 4.07965607e+002 2.41970963e+002 5.51863831e+002 9.43849182e+001 + 5.18395569e+002 1.07406387e+002 4.82542755e+002 1.26161377e+002 + 4.44942627e+002 1.51338882e+002 4.08494537e+002 1.82473099e+002 + 3.74957062e+002 2.19434235e+002 5.26199463e+002 7.13332672e+001 + 4.90725861e+002 8.47979507e+001 4.54244202e+002 1.03585014e+002 + 4.15386475e+002 1.29469131e+002 3.77955872e+002 1.61422897e+002 + 3.44593353e+002 1.99354340e+002 5.00305573e+002 4.98030853e+001 + 4.63683289e+002 6.37438354e+001 4.25043182e+002 8.33283768e+001 + 3.87471771e+002 1.09548264e+002 3.49389191e+002 1.41874283e+002 + 3.16625092e+002 1.79468613e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 7.84090210e+002 3.88017731e+002 7.58447571e+002 3.71531097e+002 + 7.31788330e+002 3.55191376e+002 7.01500000e+002 341. 674. 329. + 6.47506470e+002 3.17759216e+002 8.03502258e+002 3.63574219e+002 + 7.75521851e+002 3.44961121e+002 746. 328. 715. 3.12500000e+002 + 6.84290955e+002 3.00195953e+002 655. 289. 8.23624084e+002 + 3.35837616e+002 7.93792664e+002 3.16025818e+002 7.60739319e+002 + 2.97872772e+002 7.29195923e+002 2.81551361e+002 6.95991028e+002 + 2.68595581e+002 6.64197266e+002 2.57892395e+002 8.43718933e+002 + 3.07062378e+002 8.12469604e+002 2.84912384e+002 7.79037659e+002 + 2.66707306e+002 7.41777527e+002 2.49394852e+002 7.07556702e+002 + 2.34234406e+002 6.72774292e+002 2.27675980e+002 8.61286499e+002 + 2.75579224e+002 8.30026917e+002 2.53900146e+002 7.93825806e+002 + 2.32928696e+002 7.57441345e+002 2.16481247e+002 7.20349548e+002 + 2.02759094e+002 6.83531921e+002 1.94480438e+002 8.79620789e+002 + 2.44113449e+002 8.46151184e+002 2.20349777e+002 8.09496887e+002 + 2.00622604e+002 7.70929443e+002 1.82847610e+002 7.30988708e+002 + 1.70821991e+002 6.93835693e+002 1.63439514e+002 8.94767029e+002 + 2.13258896e+002 8.60505676e+002 1.89982834e+002 8.22427734e+002 + 1.68008087e+002 7.82129700e+002 1.51629501e+002 7.41957092e+002 + 1.40314484e+002 7.03475403e+002 1.33016800e+002 9.08190430e+002 + 1.83071915e+002 8.72554749e+002 1.58984772e+002 8.33662354e+002 + 1.38905655e+002 7.93456970e+002 1.22534683e+002 7.52483276e+002 + 1.12002495e+002 7.12622009e+002 1.05611115e+002 9.20126831e+002 + 1.53868591e+002 8.83432190e+002 1.30497757e+002 8.43475952e+002 + 1.10962593e+002 8.02609802e+002 9.46659164e+001 7.62433105e+002 + 8.44985809e+001 7.22421509e+002 7.95673294e+001 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 7.92344788e+002 1.23433441e+002 7.83113831e+002 1.56123978e+002 + 7.73464417e+002 1.87453384e+002 7.63411438e+002 2.17998337e+002 + 7.53567810e+002 2.45984650e+002 7.44753601e+002 2.71632080e+002 + 7.60217590e+002 1.08415695e+002 7.52620911e+002 1.42628448e+002 + 7.44526428e+002 1.76912338e+002 7.35988892e+002 2.09661407e+002 + 7.28117737e+002 2.39632019e+002 7.19922302e+002 2.67545227e+002 + 7.22557617e+002 9.39710464e+001 7.16941467e+002 1.30629669e+002 + 7.10926208e+002 1.67611130e+002 7.04934631e+002 2.02370895e+002 + 6.98490540e+002 2.34473831e+002 6.93224060e+002 2.63872314e+002 + 6.80145203e+002 8.36722336e+001 6.76818970e+002 1.22316780e+002 + 6.73215637e+002 1.60653091e+002 6.70026489e+002 1.97099380e+002 + 6.66568665e+002 2.31376785e+002 6.62879944e+002 2.62516785e+002 + 6.32677307e+002 7.81240692e+001 6.32470459e+002 1.17437523e+002 + 6.32117493e+002 1.57589417e+002 6.32748596e+002 1.95813293e+002 + 6.30779907e+002 2.31080444e+002 6.31525696e+002 2.61573303e+002 + 5.83167114e+002 7.81999664e+001 5.86345337e+002 1.18803757e+002 + 5.89284363e+002 1.58127457e+002 5.92464355e+002 1.96512299e+002 + 5.95569031e+002 2.31983124e+002 599. 2.63500000e+002 + 5.34004700e+002 8.45869598e+001 5.39235229e+002 1.25196678e+002 + 5.46483337e+002 1.64360748e+002 5.52699951e+002 2.01743942e+002 + 5.59695923e+002 2.36428940e+002 5.66886475e+002 2.66694885e+002 + 4.87107574e+002 9.68924789e+001 4.96528351e+002 1.36307755e+002 + 5.05490631e+002 1.73577209e+002 5.15388550e+002 2.10275955e+002 + 5.25177612e+002 2.43547882e+002 5.34730652e+002 2.73751343e+002 + 4.44378540e+002 1.13022438e+002 4.55947266e+002 1.51598907e+002 + 4.68412659e+002 1.86861725e+002 4.80615326e+002 2.21379471e+002 + 4.92385834e+002 2.51911041e+002 5.05001953e+002 2.81006958e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 4.81378052e+002 3.22624115e+002 4.80406860e+002 3.48465851e+002 + 4.79837738e+002 3.75912994e+002 4.81462616e+002 4.04819092e+002 + 4.83980530e+002 4.33634308e+002 4.87793243e+002 4.60171875e+002 + 4.54013733e+002 3.18167145e+002 4.51625885e+002 3.45765320e+002 + 4.50526794e+002 3.75426971e+002 4.51838287e+002 4.06206909e+002 + 4.53470581e+002 4.38935760e+002 4.58468933e+002 4.69474152e+002 + 4.23284729e+002 3.13804901e+002 4.19377289e+002 3.43510986e+002 + 4.17511902e+002 3.76080963e+002 4.18134125e+002 4.09680328e+002 + 4.21365753e+002 4.44091339e+002 4.26660858e+002 4.77992554e+002 + 3.89624908e+002 3.10471985e+002 3.84562958e+002 3.42330597e+002 + 3.81837799e+002 3.76874817e+002 3.82294586e+002 4.13676239e+002 + 3.85513824e+002 4.50580383e+002 3.92000275e+002 4.87093964e+002 + 3.53710693e+002 3.08246033e+002 3.47404022e+002 3.42408508e+002 + 3.44254639e+002 3.79191742e+002 3.43830841e+002 4.18523499e+002 + 3.48014771e+002 4.58329376e+002 3.55914246e+002 4.96030151e+002 + 3.17335358e+002 3.06980377e+002 3.09772308e+002 3.42725769e+002 + 3.05612762e+002 3.82554993e+002 3.05464905e+002 4.24428253e+002 + 3.09292694e+002 4.66695251e+002 3.18388306e+002 5.07142700e+002 + 2.80019928e+002 3.07089233e+002 2.71911407e+002 3.44642975e+002 + 2.66643463e+002 3.86568085e+002 2.65566803e+002 4.30820862e+002 + 2.70939453e+002 4.74563324e+002 2.81078247e+002 5.16716125e+002 + 2.40957367e+002 3.08758362e+002 2.31442734e+002 3.48210541e+002 + 2.27068802e+002 3.91975769e+002 2.25384995e+002 4.37844238e+002 + 2.31651993e+002 4.83715027e+002 2.42571533e+002 5.28483398e+002 + 2.02110733e+002 3.09812042e+002 1.94327621e+002 3.51957764e+002 + 1.87146088e+002 3.98251556e+002 1.87980118e+002 4.44944000e+002 + 1.91585983e+002 4.91924042e+002 2.04436539e+002 5.38972961e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 2.98078094e+002 2.37883362e+002 3.35515320e+002 2.48331757e+002 + 3.71690491e+002 2.59992523e+002 4.05996399e+002 2.71813202e+002 + 4.38327240e+002 2.84377747e+002 4.67610535e+002 2.96125549e+002 + 2.76246307e+002 2.72641418e+002 3.17697021e+002 2.81506042e+002 + 3.55573639e+002 2.91446899e+002 3.93156860e+002 3.01325012e+002 + 4.27950684e+002 3.12004181e+002 4.59678680e+002 3.22413574e+002 + 2.56363251e+002 3.13856415e+002 2.99295868e+002 3.21094360e+002 + 3.40440948e+002 3.28280487e+002 3.80945679e+002 3.35933075e+002 + 4.18308960e+002 3.43917114e+002 4.52452362e+002 3.51947723e+002 + 2.39919037e+002 3.61791626e+002 2.85563354e+002 3.65437958e+002 + 3.28859955e+002 3.69890686e+002 3.70934082e+002 3.74754761e+002 + 4.11297394e+002 3.79269104e+002 4.46561798e+002 3.84470093e+002 + 2.29331482e+002 4.13949615e+002 2.76502441e+002 4.14469330e+002 + 3.21892761e+002 4.15404633e+002 3.65014740e+002 4.16746887e+002 + 4.05875916e+002 4.18226929e+002 4.42373169e+002 4.19298706e+002 + 2.25439499e+002 4.66823242e+002 2.73527618e+002 4.65384979e+002 + 3.19782501e+002 4.63428619e+002 3.62731781e+002 4.60680084e+002 + 4.04263794e+002 4.57940735e+002 4.40636688e+002 4.55776001e+002 + 2.30218567e+002 5.20786621e+002 2.77071594e+002 5.14983215e+002 + 3.23104034e+002 5.08725159e+002 3.65094299e+002 5.03015442e+002 + 4.05360077e+002 4.97127014e+002 4.41966370e+002 4.91036346e+002 + 2.40612778e+002 5.70426086e+002 2.85953003e+002 5.62237854e+002 + 3.30600311e+002 5.52684509e+002 3.71975464e+002 5.42622925e+002 + 4.09923431e+002 5.33989502e+002 4.44944977e+002 5.25030884e+002 + 2.55944458e+002 6.14003845e+002 2.99916656e+002 6.03268311e+002 + 3.41513885e+002 5.91473389e+002 3.80401947e+002 5.79480225e+002 + 4.16935638e+002 5.67436584e+002 4.50069733e+002 5.56018372e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 3.50848297e+002 7.14228760e+002 3.39568451e+002 6.80527710e+002 + 3.31520844e+002 6.47583862e+002 3.25584290e+002 6.16500488e+002 + 3.22707947e+002 5.87258911e+002 3.21184540e+002 5.60773315e+002 + 3.77261963e+002 7.01518982e+002 3.65311646e+002 6.68576538e+002 + 3.55806183e+002 6.36336304e+002 3.49578125e+002 6.06026062e+002 + 3.45301941e+002 5.77650146e+002 3.42621765e+002 5.51476318e+002 + 4.04504059e+002 6.87412781e+002 3.91320770e+002 6.55220886e+002 + 3.80983765e+002 6.24722473e+002 3.73301453e+002 5.95179749e+002 + 3.68130768e+002 5.67810120e+002 3.65298218e+002 5.42442078e+002 + 4.31546967e+002 6.72458313e+002 4.17646942e+002 6.42048096e+002 + 4.06438263e+002 6.12466675e+002 3.98071136e+002 5.83806885e+002 + 3.92286835e+002 5.57391174e+002 3.88171814e+002 5.32996887e+002 + 4.58466370e+002 6.56727600e+002 4.44212433e+002 6.27420959e+002 + 4.32595306e+002 5.99160889e+002 4.23473755e+002 5.71937195e+002 + 4.16379791e+002 5.47057983e+002 4.11460785e+002 5.23456848e+002 + 4.85465790e+002 6.40406189e+002 4.70502625e+002 6.12528503e+002 + 4.58568359e+002 5.85643738e+002 4.48552917e+002 5.59496521e+002 + 4.39335297e+002 5.35315491e+002 4.35449188e+002 5.11826019e+002 + 5.11575684e+002 6.23271973e+002 4.96589050e+002 5.97307983e+002 + 4.83748962e+002 5.71929810e+002 4.74580475e+002 5.48551331e+002 + 4.64500000e+002 5.25500000e+002 4.57500000e+002 504. + 5.36280518e+002 6.06423767e+002 5.21435181e+002 5.81569031e+002 + 5.08335693e+002 5.58358887e+002 4.96972076e+002 5.35987671e+002 + 4.87500000e+002 515. 480. 4.95500000e+002 5.58491699e+002 + 5.88809082e+002 5.44518311e+002 5.66903748e+002 5.31299805e+002 + 5.45354065e+002 5.19564819e+002 5.24556335e+002 5.09763062e+002 + 5.04446228e+002 4.99442291e+002 4.86084625e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 8.81713440e+002 3.86197113e+002 9.17583252e+002 4.03987152e+002 + 9.53123840e+002 4.25079559e+002 9.87299316e+002 4.48395782e+002 + 1.01957056e+003 4.71871674e+002 1.05150195e+003 4.96505127e+002 + 8.70195496e+002 4.18432007e+002 9.06274963e+002 4.37890503e+002 + 9.40723938e+002 4.60578949e+002 9.75081177e+002 4.86557098e+002 + 1.00749420e+003 5.12476074e+002 1.03804028e+003 5.39053772e+002 + 8.52960571e+002 4.51070099e+002 8.88932251e+002 4.74545105e+002 + 9.23249329e+002 5.00817688e+002 9.57479492e+002 5.26468933e+002 + 9.88569580e+002 5.54295715e+002 1.01776630e+003 5.80369690e+002 + 833. 4.85500000e+002 8.68537170e+002 5.11270020e+002 + 9.01563538e+002 5.37908203e+002 9.33960876e+002 5.67073425e+002 + 9.63848145e+002 5.94500244e+002 9.92547302e+002 6.23060425e+002 + 8.09514282e+002 5.19066772e+002 8.41934021e+002 5.47015015e+002 + 8.74326538e+002 5.76352844e+002 9.05180908e+002 6.05454163e+002 + 9.33955200e+002 6.33015564e+002 9.61550537e+002 6.60031067e+002 + 7.83425110e+002 5.48695862e+002 8.13460266e+002 5.79241699e+002 + 8.43861572e+002 6.08925354e+002 8.73789917e+002 6.38604370e+002 + 9.00273804e+002 6.66994873e+002 926. 691. 7.55429077e+002 + 5.78604431e+002 7.84420837e+002 6.06109802e+002 8.11835876e+002 + 6.36899536e+002 8.39316772e+002 6.66466309e+002 8.65523132e+002 + 6.94579712e+002 887. 721. 7.31811340e+002 6.02392456e+002 + 7.56072571e+002 6.29946777e+002 7.80895203e+002 6.59628906e+002 + 8.05592163e+002 6.88606934e+002 8.30125122e+002 7.16589966e+002 + 8.53550293e+002 7.42749756e+002 7.06514648e+002 6.19389526e+002 + 7.29003296e+002 6.47576904e+002 7.52428772e+002 6.77560120e+002 + 7.73979187e+002 7.05406006e+002 7.96596558e+002 7.32817749e+002 + 8.19155334e+002 7.58741821e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 9.62623657e+002 1.43474075e+002 9.87476990e+002 1.86780289e+002 + 1.00622748e+003 2.27544540e+002 1.01850989e+003 2.68001343e+002 + 1.02580457e+003 3.05497681e+002 1.02905554e+003 3.40061096e+002 + 9.39946655e+002 1.60036179e+002 9.65124207e+002 2.02795746e+002 + 9.82815247e+002 2.44572601e+002 9.95420349e+002 2.84801941e+002 + 1.00243457e+003 3.22694733e+002 1.00672827e+003 3.55448639e+002 + 9.13736206e+002 1.78822800e+002 9.39209473e+002 2.21480820e+002 + 9.58125244e+002 2.62399445e+002 9.70636292e+002 3.02435455e+002 + 9.78465759e+002 3.38327209e+002 9.82429932e+002 3.70877167e+002 + 8.85564148e+002 1.99267883e+002 9.12097656e+002 2.40570816e+002 + 9.31139771e+002 2.81464874e+002 9.44167786e+002 3.20086060e+002 + 9.52656250e+002 3.55026093e+002 9.57049866e+002 3.86803772e+002 + 8.54976013e+002 2.21390503e+002 8.81532410e+002 2.62056274e+002 + 9.01685364e+002 3.01690674e+002 9.15212036e+002 3.39471344e+002 + 9.24049683e+002 3.71807831e+002 9.30585632e+002 4.01065582e+002 + 8.22988953e+002 2.45276154e+002 8.49244141e+002 2.84704559e+002 + 8.69523010e+002 3.22591766e+002 8.84555115e+002 3.57831940e+002 + 8.93988586e+002 3.89629944e+002 9.01408630e+002 4.16973846e+002 + 7.90107666e+002 2.72643127e+002 8.14884399e+002 3.09990326e+002 + 8.36442383e+002 3.43821808e+002 8.52355164e+002 3.76016418e+002 + 8.63413513e+002 4.05272797e+002 8.71420044e+002 4.30495575e+002 + 7.55500000e+002 2.99500000e+002 7.83207214e+002 3.32013153e+002 + 8.02516418e+002 3.64541840e+002 8.20689148e+002 3.95600006e+002 + 8.30940125e+002 4.21514069e+002 8.41085144e+002 4.42547974e+002 + 7.23500000e+002 3.25500000e+002 7.49073181e+002 3.55019714e+002 + 7.68561096e+002 3.82762939e+002 7.88711731e+002 4.10029236e+002 + 8.00077393e+002 4.34538788e+002 8.13500000e+002 455. + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 1.02610925e+003 5.69419373e+002 1018. 6.08500000e+002 + 1.00757269e+003 6.50474792e+002 9.90500000e+002 690. + 9.69713196e+002 7.28559875e+002 945. 760. 9.96910217e+002 + 5.55883240e+002 9.88487000e+002 5.95331909e+002 9.74262878e+002 + 6.34519043e+002 9.59772949e+002 6.74763550e+002 9.40404785e+002 + 7.11471130e+002 9.15623962e+002 7.47316528e+002 9.66300659e+002 + 5.43581970e+002 9.58032898e+002 5.81726501e+002 9.45526917e+002 + 6.19927490e+002 9.29846252e+002 6.57364746e+002 9.07986694e+002 + 6.93463928e+002 8.85528625e+002 7.26559448e+002 9.36298889e+002 + 5.31255432e+002 9.27100647e+002 5.67005432e+002 9.14340454e+002 + 6.04617249e+002 8.97536072e+002 6.41583191e+002 8.77466370e+002 + 6.75493286e+002 8.55136047e+002 7.06785339e+002 9.05193909e+002 + 5.19209595e+002 8.96645874e+002 5.53356995e+002 8.81072083e+002 + 5.87715820e+002 8.66478516e+002 6.23560242e+002 8.47192688e+002 + 6.56474304e+002 8.25451843e+002 6.86781494e+002 8.74048035e+002 + 5.06574799e+002 8.63423889e+002 5.38618835e+002 8.52353210e+002 + 5.72285339e+002 8.35347961e+002 6.05874939e+002 8.17006592e+002 + 6.37074524e+002 7.96157104e+002 6.66649353e+002 8.43320862e+002 + 4.94560669e+002 8.31992737e+002 5.26001587e+002 8.20451355e+002 + 5.58649658e+002 8.04538635e+002 5.88254333e+002 7.86978882e+002 + 6.16805054e+002 7.68332642e+002 6.44677917e+002 8.13489441e+002 + 4.84499451e+002 8.03744141e+002 5.13451721e+002 7.89310547e+002 + 5.41404175e+002 7.76207275e+002 5.71436951e+002 7.59780945e+002 + 5.98410828e+002 7.42307495e+002 6.24391235e+002 7.86433960e+002 + 4.74941956e+002 776. 5.00500000e+002 7.62905396e+002 + 5.25627258e+002 7.48652344e+002 5.54555420e+002 7.34200806e+002 + 5.79552063e+002 7.18498901e+002 6.04499268e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 9.81431458e+002 1.50723282e+002 1.01354156e+003 1.89045822e+002 + 1.03995068e+003 2.30531693e+002 1057. 272. 1073. 322. + 1.08372375e+003 3.59986786e+002 9.53933044e+002 1.70431076e+002 + 9.85864075e+002 2.09328415e+002 1.01058606e+003 2.48266327e+002 + 1.03053076e+003 2.91816650e+002 1.04453125e+003 3.33481750e+002 + 1.05310962e+003 3.73423157e+002 9.26057983e+002 1.91534622e+002 + 9.55485291e+002 2.28094772e+002 9.79567627e+002 2.67866821e+002 + 9.99413330e+002 3.09235443e+002 1.01355310e+003 3.50008392e+002 + 1.02151367e+003 3.88853394e+002 8.96944275e+002 2.13524841e+002 + 9.25470215e+002 2.48956131e+002 9.49139709e+002 2.87351990e+002 + 9.67360901e+002 3.26701294e+002 9.81027039e+002 3.65454712e+002 + 9.89696350e+002 4.02052551e+002 8.67878784e+002 2.35145157e+002 + 8.93921936e+002 2.69948578e+002 9.17444458e+002 3.06666321e+002 + 9.35262207e+002 3.44310059e+002 9.49273499e+002 3.80840088e+002 + 9.57196228e+002 4.15376526e+002 8.37211060e+002 2.57732269e+002 + 8.63078918e+002 2.90968628e+002 8.84456726e+002 3.25454163e+002 + 9.02282166e+002 3.60872833e+002 9.15394653e+002 3.95404449e+002 + 9.25000916e+002 4.27231750e+002 8.07257935e+002 2.80493073e+002 + 8.31424500e+002 3.11445557e+002 8.52416260e+002 3.43626923e+002 + 8.69502930e+002 3.76587524e+002 8.83034119e+002 4.08043854e+002 + 8.92384033e+002 4.37808990e+002 7.79647278e+002 3.02607025e+002 + 8.01500000e+002 331. 8.21078003e+002 3.61130402e+002 + 8.36605713e+002 3.90487549e+002 8.50583069e+002 4.20562988e+002 + 8.61375000e+002 4.47132935e+002 7.53991333e+002 3.22964294e+002 + 7.74386963e+002 3.48028870e+002 7.92334412e+002 3.76588531e+002 + 8.08500000e+002 4.03500000e+002 8.21683960e+002 4.30331360e+002 + 8.32711182e+002 4.55293457e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 943. 665. 9.16278015e+002 6.53599182e+002 8.89926086e+002 + 6.39973694e+002 8.63574951e+002 6.26499451e+002 8.37769043e+002 + 6.12583801e+002 8.12686646e+002 5.98407715e+002 9.62436462e+002 + 6.41479614e+002 9.34012207e+002 6.28588379e+002 9.06015320e+002 + 6.16000183e+002 8.78138000e+002 6.02532837e+002 8.50593689e+002 + 5.89413879e+002 8.23956055e+002 5.75843201e+002 9.79901611e+002 + 6.12453613e+002 9.50447876e+002 5.99915649e+002 9.21525208e+002 + 5.87731018e+002 892. 5.75562622e+002 8.62920715e+002 + 5.62961060e+002 8.34826538e+002 5.50825378e+002 9.96176331e+002 + 5.78932007e+002 9.65559021e+002 5.67786194e+002 9.34909790e+002 + 5.56707581e+002 9.04852844e+002 5.45350830e+002 8.74290710e+002 + 5.34053772e+002 8.44917908e+002 5.23278564e+002 1.00932385e+003 + 5.42889587e+002 9.77957153e+002 5.32451477e+002 9.46471741e+002 + 5.22616333e+002 9.15226868e+002 5.12911560e+002 8.83610840e+002 + 5.02954590e+002 8.53250366e+002 4.93492188e+002 1.01908594e+003 + 5.04993866e+002 9.87409180e+002 4.95473785e+002 9.55026733e+002 + 4.86801392e+002 9.22781494e+002 4.78766449e+002 8.91075867e+002 + 4.70492035e+002 8.59416992e+002 4.62671021e+002 1.02507336e+003 + 4.65049469e+002 9.92578613e+002 4.57474152e+002 9.60626831e+002 + 4.50082123e+002 9.28285034e+002 4.43053711e+002 8.95946228e+002 + 4.36700684e+002 8.64128967e+002 4.31439453e+002 1.02649512e+003 + 4.25967773e+002 9.94566406e+002 4.19460480e+002 9.62663879e+002 + 4.14105835e+002 9.30171631e+002 4.08365509e+002 8.97982483e+002 + 4.04065765e+002 8.66648926e+002 4.00205078e+002 1.02453589e+003 + 3.87660034e+002 9.92254456e+002 3.82540924e+002 9.61000061e+002 + 3.78366821e+002 9.29085388e+002 3.74990723e+002 8.96591003e+002 + 3.72973572e+002 8.67031006e+002 3.71491272e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 9.92850464e+002 4.18888062e+002 9.59441101e+002 4.31965637e+002 + 9.27529907e+002 4.42658875e+002 8.95500000e+002 4.54500000e+002 + 8.64757568e+002 4.62105591e+002 8.36500000e+002 470. + 9.92081848e+002 3.90383728e+002 9.56924988e+002 4.05250916e+002 + 9.22091003e+002 4.20337341e+002 8.87402649e+002 4.33017029e+002 + 8.56380310e+002 4.44641022e+002 829. 455. 9.86754822e+002 + 3.57046844e+002 9.51323853e+002 3.75313019e+002 9.13420715e+002 + 3.93538635e+002 8.77389587e+002 4.08586243e+002 8.42382935e+002 + 4.23987030e+002 8.14038635e+002 4.34158386e+002 9.78456604e+002 + 3.15776184e+002 9.40002991e+002 3.39462708e+002 9.02653076e+002 + 3.60630981e+002 8.62497986e+002 3.81124268e+002 8.26435364e+002 + 3.97412628e+002 7.95500000e+002 413. 9.62976929e+002 + 2.68506958e+002 9.23128662e+002 2.96603394e+002 8.83157654e+002 + 3.23671356e+002 8.46422974e+002 3.46435120e+002 8.07500000e+002 + 3.69500000e+002 7.75500000e+002 3.87500000e+002 9.37054321e+002 + 2.19495621e+002 8.98032654e+002 2.50468826e+002 8.59119385e+002 + 2.81512115e+002 8.18123779e+002 3.12852264e+002 7.82500000e+002 + 3.38500000e+002 7.49654114e+002 3.60178528e+002 8.99865540e+002 + 1.68641479e+002 8.62528259e+002 2.03040527e+002 8.23181213e+002 + 2.38275269e+002 7.83826294e+002 2.74359985e+002 7.51240540e+002 + 3.08780212e+002 721. 335. 8.50886414e+002 1.21732185e+002 + 8.15732605e+002 1.59313904e+002 7.80988892e+002 1.99837677e+002 + 7.45621826e+002 2.38860184e+002 7.17436951e+002 2.75985657e+002 + 690. 309. 7.96992249e+002 8.39213028e+001 7.64863586e+002 + 1.24419228e+002 7.32131287e+002 1.67438324e+002 7.03050720e+002 + 2.09443497e+002 6.77796021e+002 2.50547577e+002 6.56559998e+002 + 2.84677460e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 6.21648621e+002 2.64615540e+002 6.24922363e+002 2.37001770e+002 + 6.27736938e+002 2.07531189e+002 6.31982788e+002 1.76568405e+002 + 6.36301697e+002 1.45738327e+002 6.41479370e+002 1.12997490e+002 + 6.49474060e+002 2.68830536e+002 6.54831299e+002 2.42088898e+002 + 6.59611450e+002 2.12451355e+002 6.66164429e+002 1.82008011e+002 + 6.72218506e+002 1.50188156e+002 6.78809082e+002 1.18253792e+002 + 6.76446716e+002 2.75682434e+002 6.84066223e+002 2.48810486e+002 + 6.91582581e+002 2.19964661e+002 6.99929382e+002 1.89697372e+002 + 7.08432861e+002 1.58282516e+002 7.16680298e+002 1.26765770e+002 + 7.02703430e+002 2.81968536e+002 7.13080933e+002 2.57524872e+002 + 7.22746216e+002 2.29195480e+002 7.33006653e+002 2.00202789e+002 + 7.43558472e+002 1.69573883e+002 7.53214417e+002 1.38527176e+002 + 7.29548523e+002 2.92423767e+002 7.39874817e+002 2.66248413e+002 + 7.51979431e+002 2.41330765e+002 7.64206543e+002 2.12827515e+002 + 7.76047668e+002 1.83567627e+002 7.87649597e+002 1.54007019e+002 + 7.53089783e+002 3.01017059e+002 7.67395508e+002 2.78472321e+002 + 7.79268372e+002 2.53931122e+002 7.92513916e+002 2.27305573e+002 + 8.05449707e+002 1.99512634e+002 8.18565918e+002 1.71618118e+002 + 7.76721497e+002 3.11713715e+002 7.89275085e+002 2.91075226e+002 + 8.03490906e+002 2.67230316e+002 8.17492493e+002 2.42576752e+002 + 8.31731934e+002 2.16472717e+002 8.45407410e+002 1.89744308e+002 + 7.95295349e+002 3.22685059e+002 8.09476746e+002 3.02655273e+002 + 8.24271973e+002 2.81040771e+002 8.39294617e+002 2.57719421e+002 + 8.54225525e+002 2.33317703e+002 8.68694580e+002 2.09246872e+002 + 8.12529663e+002 3.32871613e+002 8.27758423e+002 3.14300171e+002 + 8.42943970e+002 2.94153076e+002 8.57932678e+002 2.72886414e+002 + 8.73576050e+002 2.50439499e+002 8.88212158e+002 2.27181015e+002 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 4.87553070e+002 3.33081940e+002 4.62614197e+002 3.02489258e+002 + 4.37576416e+002 2.69530884e+002 4.12060089e+002 2.35439728e+002 + 3.88464539e+002 2.01847916e+002 3.67124573e+002 1.69329208e+002 + 5.19967590e+002 3.11576843e+002 4.97410217e+002 2.78322418e+002 + 4.73922424e+002 2.43532043e+002 4.50377716e+002 2.06583496e+002 + 4.28351135e+002 1.72629303e+002 4.08012329e+002 1.37952560e+002 + 5.54011902e+002 2.91292267e+002 5.34618408e+002 2.56294556e+002 + 5.14143921e+002 2.19427399e+002 4.93516510e+002 1.81965973e+002 + 4.74155090e+002 1.46653778e+002 4.54185089e+002 1.11583130e+002 + 5.90221252e+002 2.72753845e+002 5.74075134e+002 2.38453003e+002 + 5.56422119e+002 2.00955048e+002 5.38824219e+002 1.63484421e+002 + 5.19426758e+002 1.27573326e+002 5.01227142e+002 9.22989960e+001 + 6.25049805e+002 2.60661194e+002 6.10513733e+002 2.25872940e+002 + 5.96240234e+002 1.87419449e+002 5.81616028e+002 1.50480957e+002 + 5.65533997e+002 1.14384705e+002 5.49490784e+002 8.06278229e+001 + 6.54708191e+002 2.51049423e+002 6.46017090e+002 2.16017548e+002 + 6.34464661e+002 1.80174149e+002 6.21993286e+002 1.43330460e+002 + 6.08453613e+002 1.07988892e+002 5.94316040e+002 7.44691238e+001 + 6.83734497e+002 2.42870544e+002 6.76964294e+002 2.10122986e+002 + 6.68720886e+002 1.76243042e+002 6.58802124e+002 1.40617599e+002 + 6.47013855e+002 1.06712463e+002 6.34501831e+002 7.43235016e+001 + 7.08225525e+002 2.38328049e+002 7.03408813e+002 2.06709641e+002 + 6.98146729e+002 1.74235916e+002 6.89880737e+002 1.41212967e+002 + 6.80672668e+002 1.08417931e+002 6.70395264e+002 7.71330414e+001 + 7.29351624e+002 2.34441971e+002 7.26809326e+002 2.05535583e+002 + 7.22509155e+002 1.75092453e+002 7.16651672e+002 1.43296677e+002 + 7.09192444e+002 1.12335365e+002 7.01085388e+002 8.23730545e+001 + <_ type_id="opencv-matrix"> + 54 + 1 +
"2f"
+ + 7.44175171e+002 3.41905121e+002 7.81475098e+002 3.30542725e+002 + 8.21084900e+002 3.18639160e+002 8.59480896e+002 3.07950623e+002 + 8.97504517e+002 2.99007721e+002 9.32098755e+002 2.91761475e+002 + 7.56500000e+002 379. 7.94500000e+002 370. 8.33592896e+002 + 3.60368561e+002 8.72396912e+002 3.52087860e+002 9.09731689e+002 + 3.43209076e+002 9.44365051e+002 3.36201935e+002 7.66500000e+002 + 416. 8.02858948e+002 4.08045868e+002 8.43303467e+002 + 4.00438141e+002 8.80331055e+002 3.93918793e+002 9.17367004e+002 + 3.86928528e+002 9.51384460e+002 3.80909027e+002 7.73453308e+002 + 4.50313354e+002 8.09500000e+002 445. 8.47631348e+002 + 4.40441315e+002 8.84517883e+002 4.33624207e+002 9.19723938e+002 + 4.28626343e+002 9.52826843e+002 4.22249237e+002 779. + 4.80500000e+002 8.13571777e+002 4.78707336e+002 8.48882446e+002 + 4.74345764e+002 8.84045044e+002 4.70790955e+002 9.18399536e+002 + 4.65920532e+002 9.50262146e+002 4.60167633e+002 7.81162781e+002 + 5.08493103e+002 8.14266479e+002 5.06445465e+002 8.47477173e+002 + 5.05494507e+002 8.81002136e+002 5.02996338e+002 9.14179688e+002 + 4.99080872e+002 9.45393311e+002 4.93634796e+002 7.82686035e+002 + 5.32574951e+002 8.13157410e+002 5.31836975e+002 8.44857605e+002 + 5.31897461e+002 8.76928589e+002 5.30486755e+002 9.08286499e+002 + 5.27373474e+002 935. 527. 7.84048706e+002 5.52915894e+002 + 8.12160828e+002 5.54131714e+002 8.41816040e+002 5.54021057e+002 + 8.71936523e+002 5.53551270e+002 9.01274780e+002 5.51488403e+002 + 9.28989075e+002 5.49090820e+002 7.83927795e+002 5.70247925e+002 + 8.10133240e+002 5.71974304e+002 8.37997986e+002 5.73809448e+002 + 8.66329834e+002 5.73433228e+002 8.93925415e+002 5.72344299e+002 + 9.20939758e+002 5.70050781e+002
+ + 1280 960 +
diff --git a/modules/ccalib/tutorial/data/omni_stereocalib_data.xml b/modules/ccalib/tutorial/data/omni_stereocalib_data.xml new file mode 100644 index 000000000..9c930a5c1 --- /dev/null +++ b/modules/ccalib/tutorial/data/omni_stereocalib_data.xml @@ -0,0 +1,4683 @@ + + + + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8372964477539062e+002 9.5561058044433594e+001 + 3.2737704467773437e+002 8.5958030700683594e+001 + 3.7614691162109375e+002 8.1356063842773437e+001 + 4.2667660522460937e+002 8.2957870483398438e+001 + 4.7586901855468750e+002 9.0650436401367188e+001 + 5.1889154052734375e+002 1.0257332611083984e+002 + 2.7589376831054688e+002 1.3348562622070313e+002 + 3.2220028686523437e+002 1.2469248962402344e+002 + 3.7515521240234375e+002 1.2068460083007812e+002 + 4.3063479614257812e+002 1.2217810058593750e+002 + 4.8304895019531250e+002 1.2999008178710937e+002 + 5.2819451904296875e+002 1.4264265441894531e+002 + 2.6957742309570312e+002 1.7941644287109375e+002 + 3.1759783935546875e+002 1.7251370239257812e+002 + 3.7383721923828125e+002 1.7030606079101562e+002 + 4.3316339111328125e+002 1.7262052917480469e+002 + 4.8745919799804687e+002 1.8084310913085937e+002 + 5.3410156250000000e+002 1.9139678955078125e+002 + 2.6475704956054687e+002 2.3203541564941406e+002 + 3.1371121215820313e+002 2.3012153625488281e+002 + 3.7182269287109375e+002 2.2983522033691406e+002 + 4.3263006591796875e+002 2.3363407897949219e+002 + 4.8906002807617187e+002 2.3921520996093750e+002 + 5.3587371826171875e+002 2.4765344238281250e+002 + 2.6444668579101562e+002 2.8854470825195312e+002 + 3.1170355224609375e+002 2.9044030761718750e+002 + 3.6950030517578125e+002 2.9504077148437500e+002 + 4.2916156005859375e+002 2.9810916137695312e+002 + 4.8520843505859375e+002 3.0200314331054687e+002 + 5.3163653564453125e+002 3.0524874877929687e+002 + 2.6568649291992187e+002 3.4162182617187500e+002 + 3.1193719482421875e+002 3.4893988037109375e+002 + 3.6612875366210937e+002 3.5462539672851562e+002 + 4.2342568969726562e+002 3.5943923950195312e+002 + 4.7707861328125000e+002 3.6077139282226562e+002 + 5.2249621582031250e+002 3.6098483276367187e+002 + 2.7035534667968750e+002 3.8944848632812500e+002 + 3.1378387451171875e+002 3.9813876342773437e+002 + 3.6383157348632812e+002 4.0647674560546875e+002 + 4.1642355346679687e+002 4.0967071533203125e+002 + 4.6615270996093750e+002 4.1115847778320312e+002 + 5.0924420166015625e+002 4.0832958984375000e+002 + 2.7593667602539062e+002 4.2773791503906250e+002 + 3.1596481323242187e+002 4.3790869140625000e+002 + 3.6158819580078125e+002 4.4565832519531250e+002 + 4.0908660888671875e+002 4.4982739257812500e+002 + 4.5438973999023437e+002 4.5003683471679687e+002 + 4.9557653808593750e+002 4.4724533081054687e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8301220703125000e+002 1.4953561401367187e+002 + 3.2634170532226562e+002 1.4191067504882812e+002 + 3.7618606567382812e+002 1.3747778320312500e+002 + 4.2794119262695312e+002 1.3731047058105469e+002 + 4.7597232055664062e+002 1.4256622314453125e+002 + 5.1906439208984375e+002 1.5160913085937500e+002 + 2.7406817626953125e+002 1.9068444824218750e+002 + 3.2088058471679687e+002 1.8445558166503906e+002 + 3.7555667114257812e+002 1.8055242919921875e+002 + 4.3236447143554687e+002 1.8158517456054687e+002 + 4.8504074096679687e+002 1.8642294311523437e+002 + 5.2990130615234375e+002 1.9520460510253906e+002 + 2.6630325317382812e+002 2.4103329467773437e+002 + 3.1558071899414062e+002 2.3682830810546875e+002 + 3.7388552856445312e+002 2.3602952575683594e+002 + 4.3521713256835937e+002 2.3682037353515625e+002 + 4.9232870483398438e+002 2.4193106079101562e+002 + 5.3794775390625000e+002 2.4728352355957031e+002 + 2.6053500366210937e+002 2.9740414428710937e+002 + 3.1107315063476562e+002 2.9962710571289063e+002 + 3.7172994995117187e+002 3.0058920288085937e+002 + 4.3563766479492187e+002 3.0335678100585937e+002 + 4.9416680908203125e+002 3.0471807861328125e+002 + 5.4137713623046875e+002 3.0702691650390625e+002 + 2.5820285034179687e+002 3.5638311767578125e+002 + 3.0877969360351562e+002 3.6281381225585938e+002 + 3.6876062011718750e+002 3.6924920654296875e+002 + 4.3253970336914063e+002 3.7109744262695312e+002 + 4.9089947509765625e+002 3.7074588012695312e+002 + 5.3786511230468750e+002 3.6677078247070312e+002 + 2.5981451416015625e+002 4.1040179443359375e+002 + 3.0875860595703125e+002 4.2209646606445312e+002 + 3.6624984741210937e+002 4.2933074951171875e+002 + 4.2662008666992187e+002 4.3284213256835937e+002 + 4.8274697875976562e+002 4.2894851684570312e+002 + 5.2928961181640625e+002 4.2332293701171875e+002 + 2.6409884643554687e+002 4.5715597534179687e+002 + 3.1036535644531250e+002 4.6916186523437500e+002 + 3.6331997680664062e+002 4.7867327880859375e+002 + 4.1846417236328125e+002 4.8092126464843750e+002 + 4.7122723388671875e+002 4.7858874511718750e+002 + 5.1568011474609375e+002 4.6968734741210937e+002 + 2.7033508300781250e+002 4.9319616699218750e+002 + 3.1294180297851562e+002 5.0650231933593750e+002 + 3.6128292846679687e+002 5.1528741455078125e+002 + 4.1162194824218750e+002 5.1803582763671875e+002 + 4.5960928344726562e+002 5.1474414062500000e+002 + 5.0247039794921875e+002 5.0716500854492187e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.9717584228515625e+002 1.7861032104492187e+002 + 3.3747390747070312e+002 1.6849749755859375e+002 + 3.8372674560546875e+002 1.6041639709472656e+002 + 4.3244320678710937e+002 1.5527453613281250e+002 + 4.7941613769531250e+002 1.5543157958984375e+002 + 5.2234960937500000e+002 1.5788516235351562e+002 + 2.9359216308593750e+002 2.1869264221191406e+002 + 3.3597268676757812e+002 2.1178640747070312e+002 + 3.8551873779296875e+002 2.0445591735839844e+002 + 4.3847805786132812e+002 2.0069824218750000e+002 + 4.9001522827148437e+002 1.9965130615234375e+002 + 5.3454565429687500e+002 2.0264639282226562e+002 + 2.9023593139648437e+002 2.6739810180664062e+002 + 3.3509490966796875e+002 2.6212985229492187e+002 + 3.8748114013671875e+002 2.5890353393554687e+002 + 4.4371136474609375e+002 2.5526596069335937e+002 + 4.9783364868164062e+002 2.5474980163574219e+002 + 5.4473431396484375e+002 2.5492581176757813e+002 + 2.8835418701171875e+002 3.1892489624023437e+002 + 3.3375103759765625e+002 3.1968679809570312e+002 + 3.8827682495117187e+002 3.1846051025390625e+002 + 4.4582955932617187e+002 3.1773880004882812e+002 + 5.0201666259765625e+002 3.1556369018554687e+002 + 5.4901300048828125e+002 3.1397653198242187e+002 + 2.8852612304687500e+002 3.7168740844726562e+002 + 3.3421923828125000e+002 3.7601303100585937e+002 + 3.8752932739257812e+002 3.7996569824218750e+002 + 4.4528460693359375e+002 3.7970941162109375e+002 + 5.0029809570312500e+002 3.7767730712890625e+002 + 5.4728851318359375e+002 3.7200885009765625e+002 + 2.9144708251953125e+002 4.1937905883789062e+002 + 3.3465249633789062e+002 4.2868450927734375e+002 + 3.8602340698242187e+002 4.3376339721679687e+002 + 4.4146514892578125e+002 4.3647796630859375e+002 + 4.9409786987304687e+002 4.3282611083984375e+002 + 5.3994458007812500e+002 4.2578472900390625e+002 + 2.9526666259765625e+002 4.6151824951171875e+002 + 3.3667541503906250e+002 4.7127285766601562e+002 + 3.8498782348632812e+002 4.7922607421875000e+002 + 4.3581082153320312e+002 4.8134530639648437e+002 + 4.8495385742187500e+002 4.7885968017578125e+002 + 5.2831579589843750e+002 4.7078369140625000e+002 + 3.0003930664062500e+002 4.9447601318359375e+002 + 3.3855792236328125e+002 5.0545602416992187e+002 + 3.8331948852539062e+002 5.1428942871093750e+002 + 4.2904669189453125e+002 5.1640356445312500e+002 + 4.7454711914062500e+002 5.1401281738281250e+002 + 5.1612878417968750e+002 5.0725332641601562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.0604019165039063e+002 2.0360488891601562e+002 + 3.4524194335937500e+002 1.9178704833984375e+002 + 3.8955807495117187e+002 1.8202023315429687e+002 + 4.3632998657226562e+002 1.7383488464355469e+002 + 4.8139953613281250e+002 1.6985281372070313e+002 + 5.2156506347656250e+002 1.6848626708984375e+002 + 3.0398114013671875e+002 2.4420385742187500e+002 + 3.4682135009765625e+002 2.3470249938964844e+002 + 3.9512393188476562e+002 2.2484962463378906e+002 + 4.4619918823242187e+002 2.1772659301757812e+002 + 4.9443316650390625e+002 2.1220130920410156e+002 + 5.3729840087890625e+002 2.1081100463867187e+002 + 3.0342480468750000e+002 2.9210446166992187e+002 + 3.4829174804687500e+002 2.8462805175781250e+002 + 4.0107275390625000e+002 2.7805142211914062e+002 + 4.5477621459960937e+002 2.7059469604492187e+002 + 5.0676583862304687e+002 2.6504287719726562e+002 + 5.5038214111328125e+002 2.6051013183593750e+002 + 3.0401339721679687e+002 3.4319189453125000e+002 + 3.5018103027343750e+002 3.4148004150390625e+002 + 4.0496496582031250e+002 3.3638043212890625e+002 + 4.6160513305664062e+002 3.3125857543945313e+002 + 5.1462365722656250e+002 3.2339904785156250e+002 + 5.5922308349609375e+002 3.1694747924804687e+002 + 3.0635440063476562e+002 3.9568524169921875e+002 + 3.5329449462890625e+002 3.9710693359375000e+002 + 4.0774246215820313e+002 3.9717562866210937e+002 + 4.6515515136718750e+002 3.9196417236328125e+002 + 5.1797778320312500e+002 3.8440719604492187e+002 + 5.6211425781250000e+002 3.7358038330078125e+002 + 3.1058676147460937e+002 4.4317864990234375e+002 + 3.5609545898437500e+002 4.4974703979492187e+002 + 4.0872811889648437e+002 4.5125183105468750e+002 + 4.6414251708984375e+002 4.4853265380859375e+002 + 5.1543890380859375e+002 4.3903140258789063e+002 + 5.5910919189453125e+002 4.2744815063476562e+002 + 3.1512982177734375e+002 4.8525009155273437e+002 + 3.5894299316406250e+002 4.9233584594726562e+002 + 4.0866119384765625e+002 4.9639428710937500e+002 + 4.5979641723632812e+002 4.9374447631835937e+002 + 5.0883563232421875e+002 4.8567245483398438e+002 + 5.5050946044921875e+002 4.7279635620117187e+002 + 3.2097836303710937e+002 5.1743835449218750e+002 + 3.6142727661132812e+002 5.2685498046875000e+002 + 4.0772946166992187e+002 5.3073443603515625e+002 + 4.5518270874023437e+002 5.2929040527343750e+002 + 5.0040176391601562e+002 5.2168139648437500e+002 + 5.4069238281250000e+002 5.1002548217773437e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.9007351684570312e+002 1.8941987609863281e+002 + 3.2384490966796875e+002 1.7316506958007812e+002 + 3.6437524414062500e+002 1.5762481689453125e+002 + 4.0778070068359375e+002 1.4397169494628906e+002 + 4.5229437255859375e+002 1.3410583496093750e+002 + 4.9504473876953125e+002 1.2774736022949219e+002 + 2.9331185913085937e+002 2.2756140136718750e+002 + 3.3014627075195312e+002 2.1388137817382812e+002 + 3.7229177856445312e+002 1.9941319274902344e+002 + 4.1980209350585937e+002 1.8668957519531250e+002 + 4.6761822509765625e+002 1.7605772399902344e+002 + 5.1292352294921875e+002 1.7001210021972656e+002 + 2.9839404296875000e+002 2.7161819458007812e+002 + 3.3602975463867187e+002 2.5952752685546875e+002 + 3.8161151123046875e+002 2.4855639648437500e+002 + 4.3109152221679687e+002 2.3666415405273437e+002 + 4.8203848266601562e+002 2.2751838684082031e+002 + 5.2776947021484375e+002 2.2009782409667969e+002 + 3.0441241455078125e+002 3.1665124511718750e+002 + 3.4336260986328125e+002 3.1062628173828125e+002 + 3.8989721679687500e+002 3.0157388305664062e+002 + 4.4130871582031250e+002 2.9325039672851562e+002 + 4.9224514770507812e+002 2.8366867065429687e+002 + 5.3903210449218750e+002 2.7560006713867187e+002 + 3.1223944091796875e+002 3.6272149658203125e+002 + 3.5173605346679687e+002 3.5905941772460937e+002 + 3.9769012451171875e+002 3.5594744873046875e+002 + 4.4809686279296875e+002 3.4877285766601562e+002 + 4.9858514404296875e+002 3.4079446411132812e+002 + 5.4450408935546875e+002 3.3052453613281250e+002 + 3.2101550292968750e+002 4.0365017700195312e+002 + 3.5911141967773437e+002 4.0558032226562500e+002 + 4.0430371093750000e+002 4.0371765136718750e+002 + 4.5277032470703125e+002 4.0053115844726562e+002 + 5.0103100585937500e+002 3.9197293090820312e+002 + 5.4469958496093750e+002 3.8268960571289062e+002 + 3.2970086669921875e+002 4.4129382324218750e+002 + 3.6659701538085937e+002 4.4430120849609375e+002 + 4.0886059570312500e+002 4.4552117919921875e+002 + 4.5375125122070312e+002 4.4244094848632812e+002 + 4.9872616577148437e+002 4.3648745727539062e+002 + 5.4036322021484375e+002 4.2615307617187500e+002 + 3.3796130371093750e+002 4.7130331420898437e+002 + 3.7258398437500000e+002 4.7603097534179687e+002 + 4.1191571044921875e+002 4.7827169799804687e+002 + 4.5383468627929687e+002 4.7695999145507812e+002 + 4.9538504028320312e+002 4.7134512329101562e+002 + 5.3366424560546875e+002 4.6240124511718750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8434768676757812e+002 1.2303335571289063e+002 + 3.1662249755859375e+002 1.0342134857177734e+002 + 3.5659823608398437e+002 8.4158523559570312e+001 + 3.9895385742187500e+002 6.8574371337890625e+001 + 4.4522540283203125e+002 5.7517734527587891e+001 + 4.8946301269531250e+002 5.2629867553710937e+001 + 2.9249401855468750e+002 1.5863824462890625e+002 + 3.2812994384765625e+002 1.4037687683105469e+002 + 3.6884320068359375e+002 1.2247984313964844e+002 + 4.1556713867187500e+002 1.0722921752929687e+002 + 4.6324636840820312e+002 9.6374557495117188e+001 + 5.0955987548828125e+002 9.2659568786621094e+001 + 3.0367782592773437e+002 1.9769567871093750e+002 + 3.3910021972656250e+002 1.8239944458007812e+002 + 3.8310717773437500e+002 1.6716752624511719e+002 + 4.3022604370117187e+002 1.5370687866210937e+002 + 4.8047033691406250e+002 1.4464262390136719e+002 + 5.2648492431640625e+002 1.3962290954589844e+002 + 3.1511511230468750e+002 2.3938931274414062e+002 + 3.5243008422851562e+002 2.2817460632324219e+002 + 3.9546838378906250e+002 2.1642533874511719e+002 + 4.4453390502929688e+002 2.0556266784667969e+002 + 4.9352230834960937e+002 1.9714553833007812e+002 + 5.3913592529296875e+002 1.9287149047851562e+002 + 3.2749450683593750e+002 2.8107159423828125e+002 + 3.6440478515625000e+002 2.7399325561523438e+002 + 4.0755764770507812e+002 2.6646630859375000e+002 + 4.5485528564453125e+002 2.5793582153320312e+002 + 5.0213461303710938e+002 2.5161466979980469e+002 + 5.4637591552734375e+002 2.4515382385253906e+002 + 3.3981677246093750e+002 3.1970544433593750e+002 + 3.7505072021484375e+002 3.1743527221679687e+002 + 4.1669857788085937e+002 3.1221682739257812e+002 + 4.6182342529296875e+002 3.0709118652343750e+002 + 5.0643734741210937e+002 3.0080752563476562e+002 + 5.4763464355468750e+002 2.9575173950195312e+002 + 3.5044381713867187e+002 3.5516113281250000e+002 + 3.8472573852539062e+002 3.5384561157226562e+002 + 4.2330883789062500e+002 3.5242117309570312e+002 + 4.6489526367187500e+002 3.4873236083984375e+002 + 5.0673098754882812e+002 3.4410250854492187e+002 + 5.4490582275390625e+002 3.3850811767578125e+002 + 3.6071301269531250e+002 3.8452185058593750e+002 + 3.9315652465820312e+002 3.8577017211914062e+002 + 4.2895315551757813e+002 3.8545428466796875e+002 + 4.6672634887695312e+002 3.8356103515625000e+002 + 5.0442239379882813e+002 3.7984454345703125e+002 + 5.4038122558593750e+002 3.7412985229492187e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8123336791992187e+002 9.1161796569824219e+001 + 3.1811398315429687e+002 7.6087387084960937e+001 + 3.6151351928710937e+002 6.2678798675537109e+001 + 4.0854217529296875e+002 5.5296775817871094e+001 + 4.5652835083007812e+002 5.3603191375732422e+001 + 5.0106317138671875e+002 5.7147899627685547e+001 + 2.8739776611328125e+002 1.2752811431884766e+002 + 3.2621948242187500e+002 1.1437207794189453e+002 + 3.6974853515625000e+002 1.0253434753417969e+002 + 4.1784426879882812e+002 9.5525367736816406e+001 + 4.6663226318359375e+002 9.4073280334472656e+001 + 5.1134069824218750e+002 9.8127998352050781e+001 + 2.9568951416015625e+002 1.6715272521972656e+002 + 3.3347775268554687e+002 1.5635136413574219e+002 + 3.7807711791992187e+002 1.4767802429199219e+002 + 4.2665646362304687e+002 1.4210830688476562e+002 + 4.7387780761718750e+002 1.4114262390136719e+002 + 5.1888189697265625e+002 1.4437393188476562e+002 + 3.0434521484375000e+002 2.0814476013183594e+002 + 3.4296105957031250e+002 2.0085865783691406e+002 + 3.8525390625000000e+002 1.9471476745605469e+002 + 4.3226675415039063e+002 1.9143350219726562e+002 + 4.7857788085937500e+002 1.9013798522949219e+002 + 5.2092401123046875e+002 1.9229869079589844e+002 + 3.1223336791992187e+002 2.4867016601562500e+002 + 3.4995574951171875e+002 2.4418174743652344e+002 + 3.9202264404296875e+002 2.4084870910644531e+002 + 4.3585031127929687e+002 2.3819079589843750e+002 + 4.7946615600585937e+002 2.3772045898437500e+002 + 5.2015338134765625e+002 2.3824938964843750e+002 + 3.2259582519531250e+002 2.8470458984375000e+002 + 3.5812524414062500e+002 2.8405880737304687e+002 + 3.9608676147460937e+002 2.8249215698242187e+002 + 4.3794973754882812e+002 2.8168246459960937e+002 + 4.7861907958984375e+002 2.8016821289062500e+002 + 5.1663562011718750e+002 2.8055044555664062e+002 + 3.3101022338867188e+002 3.1759429931640625e+002 + 3.6401330566406250e+002 3.1729211425781250e+002 + 3.9959030151367187e+002 3.1792153930664062e+002 + 4.3758016967773438e+002 3.1754193115234375e+002 + 4.7495996093750000e+002 3.1765093994140625e+002 + 5.1080413818359375e+002 3.1620315551757812e+002 + 3.3943051147460938e+002 3.4425555419921875e+002 + 3.6868124389648437e+002 3.4649453735351563e+002 + 4.0265283203125000e+002 3.4808343505859375e+002 + 4.3790298461914062e+002 3.4881405639648437e+002 + 4.7150561523437500e+002 3.4808517456054687e+002 + 5.0434603881835937e+002 3.4725601196289062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.0751010131835937e+002 1.0752435302734375e+002 + 3.5240597534179687e+002 9.7742485046386719e+001 + 4.0583990478515625e+002 9.2015861511230469e+001 + 4.6280133056640625e+002 9.3956665039062500e+001 520. 104. + 5.6517364501953125e+002 1.1850695037841797e+002 + 2.9812988281250000e+002 1.5040753173828125e+002 + 3.4683172607421875e+002 1.4242005920410156e+002 + 4.0435980224609375e+002 1.3853329467773437e+002 + 4.6709805297851562e+002 1.4146031188964844e+002 + 5.2715246582031250e+002 1.5206431579589844e+002 + 5.7590270996093750e+002 1.6853477478027344e+002 + 2.9139517211914062e+002 2.0162207031250000e+002 + 3.4074526977539062e+002 1.9732475280761719e+002 + 4.0179022216796875e+002 1.9830276489257812e+002 + 4.6856796264648437e+002 2.0320223999023437e+002 + 5.3082794189453125e+002 2.1508175659179687e+002 + 5.8102124023437500e+002 2.2870903015136719e+002 + 2.8555538940429687e+002 2.5840307617187500e+002 + 3.3487863159179687e+002 2.6268218994140625e+002 + 3.9646679687500000e+002 2.6758251953125000e+002 + 4.6350628662109375e+002 2.7621252441406250e+002 + 5.2709423828125000e+002 2.8597540283203125e+002 + 5.7742559814453125e+002 2.9620703125000000e+002 + 2.8223199462890625e+002 3.1682839965820312e+002 + 3.2988327026367187e+002 3.2612210083007812e+002 + 3.8886743164062500e+002 3.3829061889648437e+002 + 4.5352981567382812e+002 3.4798406982421875e+002 + 5.1496075439453125e+002 3.5689138793945312e+002 + 5.6508184814453125e+002 3.6166882324218750e+002 + 2.8256811523437500e+002 3.6934872436523437e+002 + 3.2699810791015625e+002 3.8422253417968750e+002 + 3.8178308105468750e+002 3.9823361206054687e+002 + 4.4072280883789062e+002 4.1006704711914062e+002 + 4.9786410522460937e+002 4.1644604492187500e+002 + 5.4626251220703125e+002 4.1937918090820312e+002 + 2.8458102416992187e+002 4.1356881713867187e+002 + 3.2650482177734375e+002 4.2995336914062500e+002 + 3.7499066162109375e+002 4.4546578979492187e+002 + 4.2793023681640625e+002 4.5670498657226562e+002 + 4.7911956787109375e+002 4.6322763061523438e+002 + 5.2509942626953125e+002 4.6384655761718750e+002 + 2.8845324707031250e+002 4.4825488281250000e+002 + 3.2564746093750000e+002 4.6546377563476562e+002 + 3.6939620971679687e+002 4.7994384765625000e+002 + 4.1621752929687500e+002 4.9122064208984375e+002 + 4.6224896240234375e+002 4.9700231933593750e+002 + 5.0452246093750000e+002 4.9807501220703125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.6826388549804687e+002 6.6524917602539062e+001 + 4.0898483276367187e+002 6.4260246276855469e+001 + 4.5364962768554687e+002 6.6773757934570313e+001 + 4.9955825805664062e+002 7.5094177246093750e+001 + 5.4227984619140625e+002 8.8508911132812500e+001 + 5.8195544433593750e+002 1.0726401519775391e+002 + 3.6148947143554687e+002 9.8589035034179688e+001 + 4.0426956176757812e+002 9.7818428039550781e+001 + 4.5225485229492187e+002 1.0132901000976562e+002 + 5.0058142089843750e+002 1.1071529388427734e+002 + 5.4704406738281250e+002 1.2625783538818359e+002 + 5.8698962402343750e+002 1.4588272094726562e+002 + 3.5360787963867187e+002 1.3749485778808594e+002 + 3.9763742065429687e+002 1.3826618957519531e+002 + 4.4801174926757812e+002 1.4449224853515625e+002 + 4.9946237182617187e+002 1.5533372497558594e+002 + 5.4658386230468750e+002 1.7171720886230469e+002 + 5.8852032470703125e+002 1.9173417663574219e+002 + 3.4451101684570312e+002 1.8142341613769531e+002 + 3.8985748291015625e+002 1.8658702087402344e+002 + 4.4086697387695312e+002 1.9444906616210937e+002 + 4.9310934448242187e+002 2.0785887145996094e+002 + 5.4265277099609375e+002 2.2427809143066406e+002 + 5.8375939941406250e+002 2.4359892272949219e+002 + 3.3694326782226562e+002 2.3017442321777344e+002 + 3.8042651367187500e+002 2.3778784179687500e+002 + 4.3062503051757812e+002 2.5052124023437500e+002 + 4.8284155273437500e+002 2.6439395141601562e+002 + 5.3166735839843750e+002 2.8093704223632812e+002 + 5.7322631835937500e+002 2.9732586669921875e+002 + 3.2959518432617187e+002 2.7755609130859375e+002 + 3.7173065185546875e+002 2.9047125244140625e+002 + 4.1938046264648437e+002 3.0455578613281250e+002 + 4.6865295410156250e+002 3.1999368286132812e+002 + 5.1616351318359375e+002 3.3483590698242187e+002 + 5.5586547851562500e+002 3.4843478393554687e+002 + 3.2445166015625000e+002 3.2253198242187500e+002 + 3.6354602050781250e+002 3.3733819580078125e+002 + 4.0673483276367187e+002 3.5311553955078125e+002 + 4.5317147827148437e+002 3.6832086181640625e+002 + 4.9674237060546875e+002 3.8268078613281250e+002 + 5.3650158691406250e+002 3.9351080322265625e+002 + 3.2082318115234375e+002 3.6060034179687500e+002 + 3.5630297851562500e+002 3.7705316162109375e+002 + 3.9590164184570312e+002 3.9358666992187500e+002 + 4.3702627563476562e+002 4.0800842285156250e+002 + 4.7766717529296875e+002 4.2096871948242187e+002 + 5.1501800537109375e+002 4.3088241577148437e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.6864505004882812e+002 4.2273624420166016e+001 + 4.1436123657226562e+002 4.6229995727539063e+001 + 4.6167251586914062e+002 5.6532867431640625e+001 + 5.0712066650390625e+002 7.2805015563964844e+001 + 5.4791528320312500e+002 9.4326820373535156e+001 + 5.8245825195312500e+002 1.1828499603271484e+002 + 3.5859753417968750e+002 7.3989479064941406e+001 + 4.0560440063476562e+002 7.9029174804687500e+001 + 4.5612664794921875e+002 9.0357849121093750e+001 + 5.0417346191406250e+002 1.0780155944824219e+002 + 5.4742462158203125e+002 1.3038235473632812e+002 + 5.8238220214843750e+002 1.5479074096679687e+002 + 3.4677056884765625e+002 1.1371973419189453e+002 + 3.9644573974609375e+002 1.1993966674804687e+002 + 4.4803710937500000e+002 1.3291360473632812e+002 + 4.9845782470703125e+002 1.5133375549316406e+002 + 5.4244482421875000e+002 1.7420320129394531e+002 + 5.7810308837890625e+002 1.9716284179687500e+002 + 3.3520614624023437e+002 1.5948439025878906e+002 + 3.8468231201171875e+002 1.6879327392578125e+002 + 4.3721270751953125e+002 1.8244552612304688e+002 + 4.8783279418945312e+002 2.0167613220214844e+002 + 5.3266796875000000e+002 2.2218791198730469e+002 + 5.6827349853515625e+002 2.4342463684082031e+002 + 3.2349468994140625e+002 2.1026803588867187e+002 + 3.7175799560546875e+002 2.2164161682128906e+002 + 4.2362347412109375e+002 2.3743052673339844e+002 + 4.7350140380859375e+002 2.5453637695312500e+002 + 5.1833026123046875e+002 2.7369631958007812e+002 + 5.5411578369140625e+002 2.9048577880859375e+002 + 3.1510852050781250e+002 2.6031561279296875e+002 + 3.5960113525390625e+002 2.7447680664062500e+002 + 4.0883685302734375e+002 2.9010229492187500e+002 + 4.5630233764648437e+002 3.0627752685546875e+002 + 4.9980416870117187e+002 3.2158044433593750e+002 + 5.3538751220703125e+002 3.3552908325195312e+002 + 3.0777737426757812e+002 3.0589257812500000e+002 + 3.4945153808593750e+002 3.2048233032226562e+002 + 3.9431051635742187e+002 3.3667587280273437e+002 + 4.3929870605468750e+002 3.5148553466796875e+002 + 4.8052670288085937e+002 3.6505520629882813e+002 + 5.1516577148437500e+002 3.7480239868164062e+002 + 3.0329739379882812e+002 3.4430935668945312e+002 + 3.4107012939453125e+002 3.6013180541992187e+002 + 3.8165756225585938e+002 3.7524053955078125e+002 + 4.2298751831054687e+002 3.8899798583984375e+002 + 4.6125073242187500e+002 3.9958422851562500e+002 + 4.9473147583007812e+002 4.0816287231445312e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.6376812744140625e+002 6.4454391479492187e+001 + 3.2082876586914062e+002 5.8305099487304688e+001 + 3.7839767456054687e+002 5.9948497772216797e+001 + 4.3097689819335937e+002 6.9419555664062500e+001 + 4.7405178833007812e+002 8.3741943359375000e+001 + 5.0929238891601562e+002 9.9462081909179688e+001 + 2.6274050903320312e+002 1.1427367401123047e+002 + 3.1853695678710937e+002 1.0822448730468750e+002 + 3.7537545776367187e+002 1.0865793609619141e+002 + 4.2652145385742187e+002 1.1589603424072266e+002 + 4.6936816406250000e+002 1.2666150665283203e+002 + 5.0371078491210937e+002 1.3909298706054687e+002 + 2.6474234008789063e+002 1.6758224487304688e+002 + 3.1872915649414062e+002 1.6110575866699219e+002 + 3.7219372558593750e+002 1.6160676574707031e+002 + 4.2120126342773437e+002 1.6492257690429688e+002 + 4.6256204223632812e+002 1.7142141723632812e+002 + 4.9601647949218750e+002 1.7895837402343750e+002 + 2.6948959350585937e+002 2.1869247436523437e+002 + 3.1932202148437500e+002 2.1438296508789062e+002 + 3.6921960449218750e+002 2.1150205993652344e+002 + 4.1443594360351562e+002 2.1197000122070312e+002 + 4.5425277709960937e+002 2.1432395935058594e+002 + 4.8637280273437500e+002 2.1782254028320312e+002 + 2.7580392456054687e+002 2.6370626831054687e+002 + 3.2109063720703125e+002 2.5952145385742187e+002 + 3.6615502929687500e+002 2.5647274780273437e+002 + 4.0894021606445313e+002 2.5358518981933594e+002 + 4.4522283935546875e+002 2.5398330688476562e+002 + 4.7621075439453125e+002 2.5349589538574219e+002 + 2.8312384033203125e+002 3.0051187133789062e+002 + 3.2333889770507812e+002 2.9715112304687500e+002 + 3.6399020385742187e+002 2.9329815673828125e+002 + 4.0191787719726562e+002 2.9007546997070312e+002 + 4.3691531372070312e+002 2.8726034545898437e+002 + 4.6625524902343750e+002 2.8506954956054687e+002 + 2.8953594970703125e+002 3.3079794311523437e+002 + 3.2562179565429687e+002 3.2732061767578125e+002 + 3.6252697753906250e+002 3.2336660766601562e+002 + 3.9667834472656250e+002 3.1958380126953125e+002 + 4.2848828125000000e+002 3.1612539672851563e+002 + 4.5671179199218750e+002 3.1123971557617187e+002 + 2.9528421020507812e+002 3.5378836059570312e+002 + 3.2753256225585937e+002 3.5155917358398437e+002 + 3.6074206542968750e+002 3.4798767089843750e+002 + 3.9231970214843750e+002 3.4390063476562500e+002 + 4.2116744995117187e+002 3.3921984863281250e+002 + 4.4754953002929687e+002 3.3480633544921875e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.2956921386718750e+002 1.0955868530273437e+002 + 2.9155068969726562e+002 8.8882469177246094e+001 + 3.5777804565429687e+002 7.9634452819824219e+001 + 4.1904254150390625e+002 7.9747627258300781e+001 + 4.6927508544921875e+002 8.8402618408203125e+001 + 5.0898071289062500e+002 9.9052917480468750e+001 + 2.3872412109375000e+002 1.6821302795410156e+002 + 2.9985015869140625e+002 1.5050971984863281e+002 + 3.6483071899414062e+002 1.3938653564453125e+002 + 4.2426388549804687e+002 1.3680789184570312e+002 + 4.7366436767578125e+002 1.3950173950195312e+002 + 5.1097680664062500e+002 1.4591123962402344e+002 + 2.5267990112304687e+002 2.2863549804687500e+002 + 3.1084585571289062e+002 2.1263505554199219e+002 + 3.7173272705078125e+002 2.0232487487792969e+002 + 4.2766159057617187e+002 1.9502630615234375e+002 + 4.7403890991210937e+002 1.9366470336914062e+002 + 5.1016818237304687e+002 1.9355819702148437e+002 + 2.6838751220703125e+002 2.8316534423828125e+002 + 3.2240023803710937e+002 2.7064544677734375e+002 + 3.7729751586914062e+002 2.5870391845703125e+002 + 4.2781243896484375e+002 2.5046952819824219e+002 + 4.7059432983398438e+002 2.4318389892578125e+002 + 5.0540182495117187e+002 2.3946252441406250e+002 + 2.8432348632812500e+002 3.2850631713867187e+002 + 3.3225033569335937e+002 3.1733880615234375e+002 + 3.8098922729492187e+002 3.0744821166992187e+002 + 4.2648522949218750e+002 2.9647256469726562e+002 + 4.6640353393554687e+002 2.8742056274414062e+002 + 4.9875442504882812e+002 2.7891928100585937e+002 + 2.9841674804687500e+002 3.6297183227539062e+002 + 3.4102880859375000e+002 3.5490716552734375e+002 + 3.8396194458007812e+002 3.4429034423828125e+002 + 4.2458761596679687e+002 3.3395877075195312e+002 + 4.6030209350585937e+002 3.2328338623046875e+002 + 4.9091357421875000e+002 3.1402462768554688e+002 + 3.0985601806640625e+002 3.9038555908203125e+002 + 3.4737155151367187e+002 3.8227862548828125e+002 + 3.8601422119140625e+002 3.7368563842773437e+002 + 4.2174008178710937e+002 3.6355242919921875e+002 + 4.5506192016601562e+002 3.5267135620117187e+002 + 4.8386376953125000e+002 3.4217745971679687e+002 + 3.1904476928710937e+002 4.0993099975585937e+002 + 3.5318154907226562e+002 4.0386706542968750e+002 + 3.8667062377929687e+002 3.9622073364257812e+002 + 4.1919042968750000e+002 3.8606817626953125e+002 451. 377. + 4.7642126464843750e+002 3.6565765380859375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.5992156982421875e+002 8.4034469604492187e+001 + 3.1661877441406250e+002 7.9255165100097656e+001 + 3.7368261718750000e+002 8.3392021179199219e+001 + 4.2307562255859375e+002 9.2457183837890625e+001 + 4.6475579833984375e+002 1.0576576995849609e+002 + 4.9766937255859375e+002 1.1933972930908203e+002 + 2.5451263427734375e+002 1.3500866699218750e+002 + 3.1548562622070312e+002 1.2985444641113281e+002 + 3.7514801025390625e+002 1.3129550170898437e+002 + 4.2644796752929687e+002 1.3879409790039062e+002 + 4.6852169799804687e+002 1.4876821899414062e+002 + 5.0060873413085937e+002 1.5954505920410156e+002 + 2.5389120483398437e+002 1.9661962890625000e+002 + 3.1556582641601562e+002 1.8933270263671875e+002 + 3.7593389892578125e+002 1.8921580505371094e+002 + 4.2788284301757812e+002 1.9165496826171875e+002 + 4.6933447265625000e+002 1.9766748046875000e+002 + 5.0121408081054687e+002 2.0325163269042969e+002 + 2.5786416625976562e+002 2.6074517822265625e+002 + 3.1808316040039062e+002 2.5483590698242187e+002 + 3.7697106933593750e+002 2.4999771118164062e+002 + 4.2740420532226562e+002 2.4831455993652344e+002 + 4.6770965576171875e+002 2.4758265686035156e+002 + 4.9879895019531250e+002 2.4907456970214844e+002 + 2.6624050903320312e+002 3.2185546875000000e+002 + 3.2237554931640625e+002 3.1481100463867187e+002 + 3.7698440551757812e+002 3.0862088012695312e+002 + 4.2442169189453125e+002 3.0162078857421875e+002 + 4.6406063842773437e+002 2.9729956054687500e+002 + 4.9423248291015625e+002 2.9212420654296875e+002 + 2.7627938842773437e+002 3.7238201904296875e+002 + 3.2720233154296875e+002 3.6624160766601562e+002 + 3.7677749633789062e+002 3.5792965698242187e+002 + 4.2109518432617187e+002 3.4900268554687500e+002 + 4.5764605712890625e+002 3.4031942749023437e+002 + 4.8773428344726562e+002 3.3254205322265625e+002 + 2.8600796508789063e+002 4.1232794189453125e+002 + 3.3155007934570312e+002 4.0616217041015625e+002 + 3.7641983032226562e+002 3.9784933471679687e+002 + 4.1643521118164062e+002 3.8746511840820312e+002 + 4.5147787475585937e+002 3.7747247314453125e+002 + 4.7928924560546875e+002 3.6743136596679687e+002 + 2.9485168457031250e+002 4.4159213256835937e+002 + 3.3554595947265625e+002 4.3656787109375000e+002 + 3.7543572998046875e+002 4.2836538696289062e+002 + 4.1224502563476562e+002 4.1833090209960937e+002 + 4.4420956420898437e+002 4.0731658935546875e+002 + 4.7182162475585937e+002 3.9667959594726562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8133163452148437e+002 7.0724617004394531e+001 + 3.3550000000000000e+002 65. 3.8476589965820312e+002 + 6.5476562500000000e+001 4.3175323486328125e+002 + 7.3109687805175781e+001 4.7037512207031250e+002 + 8.3528549194335937e+001 5.0254589843750000e+002 + 9.5421920776367188e+001 2.7929382324218750e+002 + 1.1064707183837891e+002 3.3639620971679687e+002 + 1.0534089660644531e+002 3.9175714111328125e+002 + 1.0479587554931641e+002 4.3878262329101562e+002 + 1.1152985382080078e+002 4.7968301391601562e+002 + 1.2127812194824219e+002 5.1086880493164062e+002 + 1.3155047607421875e+002 2.8008267211914062e+002 + 1.6293646240234375e+002 3.3991806030273437e+002 + 1.5508302307128906e+002 3.9730871582031250e+002 + 1.5524684143066406e+002 4.4748098754882812e+002 + 1.5843019104003906e+002 4.8611953735351562e+002 + 1.6528135681152344e+002 5.1825909423828125e+002 + 1.7241458129882813e+002 2.8347860717773437e+002 + 2.2315634155273437e+002 3.4442926025390625e+002 + 2.1573231506347656e+002 4.0228991699218750e+002 + 2.1158541870117187e+002 4.5159262084960937e+002 + 2.1196307373046875e+002 4.9125576782226562e+002 + 2.1342114257812500e+002 5.2125976562500000e+002 + 2.1698353576660156e+002 2.9074020385742187e+002 + 2.8750653076171875e+002 3.4942846679687500e+002 + 2.7870791625976562e+002 4.0630911254882812e+002 + 2.7278424072265625e+002 4.5370541381835937e+002 + 2.6717672729492187e+002 4.9195535278320312e+002 + 2.6453646850585937e+002 5.2124609375000000e+002 + 2.6205313110351562e+002 3.0005197143554687e+002 + 3.4492221069335938e+002 3.5495547485351563e+002 + 3.3770541381835938e+002 4.0754037475585937e+002 + 3.2904504394531250e+002 4.5247509765625000e+002 + 3.2039956665039063e+002 4.8952670288085937e+002 + 3.1243203735351562e+002 5.1901141357421875e+002 + 3.0557556152343750e+002 3.0972796630859375e+002 + 3.9377804565429687e+002 3.5956301879882812e+002 + 3.8559826660156250e+002 4.0782366943359375e+002 + 3.7733645629882812e+002 4.5033395385742187e+002 + 3.6539648437500000e+002 4.8552441406250000e+002 + 3.5563174438476562e+002 5.1359356689453125e+002 + 3.4535787963867187e+002 3.1848861694335937e+002 + 4.3094973754882812e+002 3.6358969116210937e+002 + 4.2450231933593750e+002 4.0685952758789062e+002 + 4.1496722412109375e+002 4.4616607666015625e+002 + 4.0364883422851563e+002 4.7954010009765625e+002 + 3.9155923461914062e+002 5.0678024291992187e+002 + 3.7988076782226562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7735568237304687e+002 2.0544271850585937e+002 + 3.1661022949218750e+002 1.8951077270507812e+002 + 3.5967932128906250e+002 1.7546173095703125e+002 + 4.0088034057617187e+002 1.6489724731445312e+002 + 4.3957324218750000e+002 1.5770280456542969e+002 + 4.7345117187500000e+002 1.5257627868652344e+002 + 2.9124212646484375e+002 2.4580213928222656e+002 + 3.3040423583984375e+002 2.3143048095703125e+002 + 3.7074142456054687e+002 2.1842495727539062e+002 + 4.1122702026367187e+002 2.0791152954101562e+002 + 4.4848785400390625e+002 1.9839381408691406e+002 + 4.8192376708984375e+002 1.9197427368164062e+002 + 3.0464236450195312e+002 2.8575561523437500e+002 + 3.4277716064453125e+002 2.7234249877929687e+002 + 3.8234292602539062e+002 2.6063525390625000e+002 + 4.2030221557617187e+002 2.4845361328125000e+002 + 4.5622042846679688e+002 2.3867881774902344e+002 + 4.8714242553710938e+002 2.3032679748535156e+002 + 3.1850912475585938e+002 3.2155151367187500e+002 + 3.5441217041015625e+002 3.1068569946289062e+002 + 3.9127032470703125e+002 2.9845861816406250e+002 + 4.2802554321289062e+002 2.8700564575195312e+002 + 4.6072317504882812e+002 2.7629061889648438e+002 + 4.9051809692382812e+002 2.6649645996093750e+002 + 3.3170526123046875e+002 3.5314505004882812e+002 + 3.6549316406250000e+002 3.4305880737304687e+002 + 3.9952120971679687e+002 3.3245599365234375e+002 + 4.3276626586914062e+002 3.2056552124023437e+002 + 4.6448611450195312e+002 3.0967263793945313e+002 + 4.9212506103515625e+002 2.9897662353515625e+002 + 3.4259921264648437e+002 3.7950997924804687e+002 + 3.7442803955078125e+002 3.7106518554687500e+002 + 4.0574392700195312e+002 3.6106765747070312e+002 + 4.3717706298828125e+002 3.5043554687500000e+002 + 4.6575375366210937e+002 3.3921206665039062e+002 + 4.9254733276367187e+002 3.2803866577148437e+002 + 3.5284207153320312e+002 4.0182241821289062e+002 + 3.8190411376953125e+002 3.9395767211914062e+002 + 4.1136508178710937e+002 3.8526190185546875e+002 + 4.3994403076171875e+002 3.7450775146484375e+002 + 4.6726074218750000e+002 3.6408331298828125e+002 + 4.9160079956054687e+002 3.5323724365234375e+002 + 3.6106451416015625e+002 4.1976953125000000e+002 + 3.8814099121093750e+002 4.1338156127929687e+002 + 4.1544287109375000e+002 4.0452062988281250e+002 + 4.4178903198242187e+002 3.9528353881835937e+002 + 4.6714056396484375e+002 3.8533383178710937e+002 + 4.9047497558593750e+002 3.7455599975585937e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.1394265747070313e+002 1.9036227416992187e+002 + 2.4830751037597656e+002 1.6179914855957031e+002 + 2.8669216918945312e+002 1.3583525085449219e+002 + 3.2595892333984375e+002 1.1394491577148437e+002 + 3.6358233642578125e+002 9.7501800537109375e+001 + 3.9775195312500000e+002 8.6284049987792969e+001 + 2.3618351745605469e+002 2.2450579833984375e+002 + 2.7054238891601562e+002 1.9794694519042969e+002 + 3.0733969116210937e+002 1.7303138732910156e+002 + 3.4507476806640625e+002 1.5135556030273437e+002 + 3.8113253784179687e+002 1.3323794555664062e+002 + 4.1374758911132812e+002 1.2040964508056641e+002 + 2.5940194702148437e+002 2.5829367065429687e+002 + 2.9194439697265625e+002 2.3382568359375000e+002 + 3.2800228881835937e+002 2.1000796508789062e+002 + 3.6305502319335937e+002 1.8853381347656250e+002 + 3.9683441162109375e+002 1.7040824890136719e+002 + 4.2723934936523437e+002 1.5561431884765625e+002 + 2.8172222900390625e+002 2.8947961425781250e+002 + 3.1376831054687500e+002 2.6656127929687500e+002 + 3.4653408813476562e+002 2.4468052673339844e+002 + 3.8041577148437500e+002 2.2324069213867187e+002 + 4.1141278076171875e+002 2.0526057434082031e+002 + 4.3957711791992187e+002 1.8948631286621094e+002 + 3.0305215454101562e+002 3.1707360839843750e+002 + 3.3255786132812500e+002 2.9646713256835937e+002 + 3.6382131958007812e+002 2.7600668334960937e+002 + 3.9430316162109375e+002 2.5569479370117187e+002 + 4.2250015258789062e+002 2.3781764221191406e+002 + 4.4859918212890625e+002 2.2091714477539062e+002 + 3.2159997558593750e+002 3.4036782836914062e+002 + 3.4977557373046875e+002 3.2158306884765625e+002 + 3.7801022338867187e+002 3.0287359619140625e+002 + 4.0567587280273437e+002 2.8416702270507812e+002 + 4.3262103271484375e+002 2.6600195312500000e+002 + 4.5644488525390625e+002 2.4972491455078125e+002 + 3.3774520874023437e+002 3.5988824462890625e+002 + 3.6393133544921875e+002 3.4317544555664062e+002 + 3.9042962646484375e+002 3.2544955444335937e+002 + 4.1590350341796875e+002 3.0752456665039063e+002 + 4.3966198730468750e+002 2.9094427490234375e+002 + 4.6163351440429687e+002 2.7505346679687500e+002 + 3.5150735473632812e+002 3.7587066650390625e+002 + 3.7597509765625000e+002 3.6036599731445312e+002 + 3.9974224853515625e+002 3.4523553466796875e+002 + 4.2363879394531250e+002 3.2841275024414062e+002 + 4.4609640502929687e+002 3.1252398681640625e+002 + 4.6646606445312500e+002 2.9650073242187500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.5849591064453125e+002 7.1482650756835938e+001 + 3.9522583007812500e+002 6.3804718017578125e+001 + 4.3535198974609375e+002 5.9466972351074219e+001 + 4.7509594726562500e+002 5.9032913208007813e+001 + 5.1396020507812500e+002 6.2968990325927734e+001 + 5.4949243164062500e+002 7.1404731750488281e+001 + 3.6549951171875000e+002 1.0454283142089844e+002 + 4.0334652709960937e+002 9.8132804870605469e+001 + 4.4294720458984375e+002 9.4356704711914063e+001 + 4.8326638793945312e+002 9.5521080017089844e+001 + 5.2168041992187500e+002 9.8877609252929688e+001 + 5.5648681640625000e+002 1.0740502166748047e+002 + 3.7238220214843750e+002 1.4057960510253906e+002 + 4.0936190795898437e+002 1.3528369140625000e+002 + 4.4933911132812500e+002 1.3364297485351562e+002 + 4.8866473388671875e+002 1.3439404296875000e+002 + 5.2670965576171875e+002 1.3863502502441406e+002 + 5.6073797607421875e+002 1.4567308044433594e+002 + 3.7848101806640625e+002 1.7696812438964844e+002 + 4.1502258300781250e+002 1.7473857116699219e+002 + 4.5370187377929687e+002 1.7324299621582031e+002 + 4.9218640136718750e+002 1.7540077209472656e+002 + 5.2819018554687500e+002 1.7914427185058594e+002 + 5.6091235351562500e+002 1.8500497436523437e+002 + 3.8417926025390625e+002 2.1357081604003906e+002 + 4.1941516113281250e+002 2.1200053405761719e+002 + 4.5609005737304687e+002 2.1315237426757812e+002 + 4.9248031616210937e+002 2.1446307373046875e+002 + 5.2726715087890625e+002 2.1799794006347656e+002 + 5.5832366943359375e+002 2.2266377258300781e+002 + 3.8849267578125000e+002 2.4754765319824219e+002 + 4.2133398437500000e+002 2.4778009033203125e+002 + 4.5630429077148437e+002 2.4892213439941406e+002 + 4.9120745849609375e+002 2.5153500366210937e+002 + 5.2351989746093750e+002 2.5427593994140625e+002 + 5.5364080810546875e+002 2.5796875000000000e+002 + 3.9218893432617187e+002 2.7783190917968750e+002 + 4.2336636352539062e+002 2.7963528442382812e+002 + 4.5556152343750000e+002 2.8166116333007812e+002 + 4.8752175903320312e+002 2.8373483276367187e+002 + 5.1871453857421875e+002 2.8701583862304688e+002 + 5.4673370361328125e+002 2.8948989868164062e+002 + 3.9535162353515625e+002 3.0420913696289062e+002 + 4.2444070434570312e+002 3.0763003540039062e+002 + 4.5402972412109375e+002 3.1035400390625000e+002 + 4.8432394409179687e+002 3.1277542114257812e+002 + 5.1264617919921875e+002 3.1502627563476562e+002 + 5.3930804443359375e+002 3.1677124023437500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7430868530273437e+002 1.9303665161132812e+002 + 3.1873098754882812e+002 1.9363691711425781e+002 + 3.6585012817382812e+002 1.9754597473144531e+002 + 4.1304376220703125e+002 2.0459211730957031e+002 + 4.5585070800781250e+002 2.1335931396484375e+002 + 4.9441076660156250e+002 2.2329444885253906e+002 + 2.6581207275390625e+002 2.3810662841796875e+002 + 3.1090884399414062e+002 2.4185630798339844e+002 + 3.6020602416992187e+002 2.4544036865234375e+002 + 4.1008285522460937e+002 2.5291795349121094e+002 + 4.5573120117187500e+002 2.5946371459960937e+002 + 4.9427563476562500e+002 2.6733581542968750e+002 + 2.5771896362304688e+002 2.8908624267578125e+002 + 3.0382452392578125e+002 2.9356387329101562e+002 + 3.5455615234375000e+002 2.9966275024414062e+002 + 4.0649661254882812e+002 3.0519540405273437e+002 + 4.5247155761718750e+002 3.1057669067382812e+002 + 4.9180294799804687e+002 3.1478228759765625e+002 + 2.5346829223632812e+002 3.4052575683593750e+002 + 2.9938684082031250e+002 3.4879354858398437e+002 + 3.5010470581054687e+002 3.5435662841796875e+002 + 4.0082931518554688e+002 3.5944918823242187e+002 + 4.4662640380859375e+002 3.6153753662109375e+002 + 4.8646786499023437e+002 3.6323370361328125e+002 + 2.5137239074707031e+002 3.8987030029296875e+002 + 2.9610098266601562e+002 3.9831134033203125e+002 + 3.4463751220703125e+002 4.0586755371093750e+002 + 3.9377896118164062e+002 4.0855932617187500e+002 + 4.3935476684570312e+002 4.1002777099609375e+002 + 4.7868737792968750e+002 4.0717282104492188e+002 + 2.5309197998046875e+002 4.3231500244140625e+002 + 2.9492459106445312e+002 4.4255981445312500e+002 + 3.4107806396484375e+002 4.4911370849609375e+002 + 3.8754977416992187e+002 4.5228002929687500e+002 + 4.3102304077148437e+002 4.5059695434570312e+002 + 4.6929010009765625e+002 4.4758370971679687e+002 + 2.5546176147460937e+002 4.6866394042968750e+002 + 2.9591619873046875e+002 4.7804891967773437e+002 + 3.3855233764648437e+002 4.8464385986328125e+002 + 3.8156396484375000e+002 4.8643032836914063e+002 + 4.2207882690429687e+002 4.8555249023437500e+002 + 4.5909521484375000e+002 4.8076647949218750e+002 + 2.6023559570312500e+002 4.9705322265625000e+002 + 2.9713632202148437e+002 5.0653530883789062e+002 + 3.3646890258789062e+002 5.1241210937500000e+002 + 3.7655841064453125e+002 5.1477642822265625e+002 + 4.1421426391601562e+002 5.1264080810546875e+002 + 4.4874459838867187e+002 5.0825427246093750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.2018417358398437e+002 2.2167564392089844e+002 + 3.6499896240234375e+002 2.2720426940917969e+002 + 4.1086868286132812e+002 2.3572267150878906e+002 + 4.5467254638671875e+002 2.4461122131347656e+002 + 4.9294149780273437e+002 2.5512211608886719e+002 + 5.2693951416015625e+002 2.6542166137695312e+002 + 3.0954129028320312e+002 2.6537310791015625e+002 + 3.5610519409179687e+002 2.7310134887695312e+002 + 4.0471136474609375e+002 2.8195315551757812e+002 + 4.5142312622070312e+002 2.9142901611328125e+002 + 4.9256256103515625e+002 2.9973141479492187e+002 + 5.2682843017578125e+002 3.0830984497070312e+002 + 2.9775521850585937e+002 3.1554669189453125e+002 + 3.4597363281250000e+002 3.2437722778320312e+002 + 3.9655441284179687e+002 3.3454852294921875e+002 + 4.4548748779296875e+002 3.4241812133789062e+002 + 4.8820440673828125e+002 3.4959237670898437e+002 + 5.2338873291015625e+002 3.5374670410156250e+002 + 2.8785870361328125e+002 3.6561248779296875e+002 + 3.3618502807617187e+002 3.7787249755859375e+002 + 3.8776870727539062e+002 3.8813885498046875e+002 + 4.3712649536132812e+002 3.9549218750000000e+002 + 4.8038098144531250e+002 3.9878781127929687e+002 + 5.1634936523437500e+002 4.0125497436523437e+002 + 2.8079055786132812e+002 4.1578399658203125e+002 + 3.2750598144531250e+002 4.2802819824218750e+002 + 3.7762823486328125e+002 4.3902816772460937e+002 + 4.2626541137695312e+002 4.4401214599609375e+002 + 4.7009457397460937e+002 4.4594799804687500e+002 + 5.0617880249023437e+002 4.4460089111328125e+002 + 2.7562527465820313e+002 4.5800567626953125e+002 + 3.2049914550781250e+002 4.7271908569335937e+002 + 3.6785250854492187e+002 4.8160394287109375e+002 + 4.1536605834960937e+002 4.8717416381835937e+002 + 4.5772311401367187e+002 4.8676275634765625e+002 + 4.9374938964843750e+002 4.8405627441406250e+002 + 2.7276110839843750e+002 4.9461334228515625e+002 + 3.1509899902343750e+002 5.0760488891601562e+002 + 3.5953396606445313e+002 5.1742126464843750e+002 + 4.0366873168945312e+002 5.2148156738281250e+002 + 4.4425161743164063e+002 5.2146453857421875e+002 + 4.8020660400390625e+002 5.1676660156250000e+002 + 2.7173980712890625e+002 5.2247351074218750e+002 + 3.1087738037109375e+002 5.3623065185546875e+002 + 3.5190686035156250e+002 5.4486053466796875e+002 + 3.9348452758789062e+002 5.4870263671875000e+002 + 4.3179321289062500e+002 5.4788873291015625e+002 + 4.6649813842773437e+002 5.4408209228515625e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7652783203125000e+002 1.3335128784179687e+002 + 3.0941848754882812e+002 1.1611652374267578e+002 + 3.4732580566406250e+002 1.0007693481445312e+002 + 3.8538259887695312e+002 8.8223358154296875e+001 + 4.2398165893554687e+002 7.9608779907226563e+001 + 4.5958303833007812e+002 7.5229339599609375e+001 + 2.8420352172851562e+002 1.6441006469726562e+002 + 3.1935113525390625e+002 1.4763522338867187e+002 + 3.5846151733398437e+002 1.3209355163574219e+002 + 3.9958288574218750e+002 1.1925965881347656e+002 + 4.3950982666015625e+002 1.1026898956298828e+002 + 4.7577926635742187e+002 1.0593013000488281e+002 + 2.9263586425781250e+002 2.0164411926269531e+002 + 3.3032949829101563e+002 1.8459416198730469e+002 + 3.7185034179687500e+002 1.6957357788085937e+002 + 4.1367138671875000e+002 1.5664907836914062e+002 + 4.5540551757812500e+002 1.4763919067382812e+002 + 4.9244338989257812e+002 1.4193916320800781e+002 + 3.0356994628906250e+002 2.4122088623046875e+002 + 3.4226010131835937e+002 2.2708261108398438e+002 + 3.8451904296875000e+002 2.1235334777832031e+002 + 4.2863623046875000e+002 1.9952400207519531e+002 + 4.7008090209960937e+002 1.8967131042480469e+002 + 5.0720434570312500e+002 1.8293460083007812e+002 + 3.1493444824218750e+002 2.8471166992187500e+002 + 3.5501315307617187e+002 2.7150476074218750e+002 + 3.9786590576171875e+002 2.5869058227539062e+002 + 4.4163436889648437e+002 2.4609999084472656e+002 + 4.8282611083984375e+002 2.3542185974121094e+002 + 5.1868933105468750e+002 2.2660388183593750e+002 + 3.2830087280273437e+002 3.2556478881835937e+002 + 3.6741854858398437e+002 3.1600045776367187e+002 + 4.0918975830078125e+002 3.0459277343750000e+002 + 4.5222976684570312e+002 2.9316018676757812e+002 + 4.9184674072265625e+002 2.8134667968750000e+002 + 5.2718255615234375e+002 2.7146438598632812e+002 + 3.4068054199218750e+002 3.6508050537109375e+002 + 3.7876873779296875e+002 3.5651132202148437e+002 + 4.1930651855468750e+002 3.4745678710937500e+002 + 4.5997463989257812e+002 3.3615667724609375e+002 + 4.9836437988281250e+002 3.2449850463867187e+002 + 5.3138555908203125e+002 3.1333480834960937e+002 + 3.5259252929687500e+002 3.9821435546875000e+002 + 3.8861999511718750e+002 3.9256524658203125e+002 + 4.2724633789062500e+002 3.8440829467773437e+002 + 4.6465533447265625e+002 3.7459085083007812e+002 + 5.0130084228515625e+002 3.6259017944335937e+002 + 5.3329180908203125e+002 3.5067034912109375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7736267089843750e+002 1.2636489868164062e+002 + 3.1180181884765625e+002 1.0938557434082031e+002 + 3.4961184692382812e+002 9.5163925170898437e+001 + 3.8884634399414062e+002 8.3948745727539063e+001 + 4.2745657348632812e+002 7.7038391113281250e+001 + 4.6309567260742187e+002 7.3601318359375000e+001 + 2.8321908569335938e+002 1.5834719848632812e+002 + 3.2033200073242187e+002 1.4131167602539062e+002 + 3.6098925781250000e+002 1.2578517913818359e+002 + 4.0227133178710937e+002 1.1523874664306641e+002 + 4.4192984008789063e+002 1.0715541076660156e+002 + 4.7905130004882812e+002 1.0416494750976562e+002 + 2.9188824462890625e+002 1.9477992248535156e+002 + 3.3041125488281250e+002 1.7862051391601562e+002 + 3.7301107788085937e+002 1.6462495422363281e+002 + 4.1628494262695312e+002 1.5229153442382812e+002 + 4.5738464355468750e+002 1.4492526245117187e+002 + 4.9469308471679687e+002 1.4015267944335937e+002 + 3.0082525634765625e+002 2.3629028320312500e+002 + 3.4155734252929687e+002 2.2181031799316406e+002 + 3.8561398315429687e+002 2.0745188903808594e+002 + 4.2996737670898437e+002 1.9600314331054687e+002 + 4.7176071166992187e+002 1.8707469177246094e+002 + 5.0857153320312500e+002 1.8158938598632812e+002 + 3.1324066162109375e+002 2.7982437133789062e+002 + 3.5374511718750000e+002 2.6687265014648437e+002 + 3.9806597900390625e+002 2.5471101379394531e+002 + 4.4194531250000000e+002 2.4294200134277344e+002 + 4.8377032470703125e+002 2.3352819824218750e+002 + 5.1965032958984375e+002 2.2529512023925781e+002 + 3.2543246459960937e+002 3.2265603637695312e+002 + 3.6615927124023437e+002 3.1280972290039062e+002 + 4.0898483276367187e+002 3.0162222290039062e+002 + 4.5254510498046875e+002 2.9053546142578125e+002 + 4.9249041748046875e+002 2.7949719238281250e+002 + 5.2777551269531250e+002 2.7023208618164062e+002 + 3.3795779418945312e+002 3.6253259277343750e+002 + 3.7639062500000000e+002 3.5462670898437500e+002 + 4.1821685791015625e+002 3.4569750976562500e+002 + 4.5902166748046875e+002 3.3502557373046875e+002 + 4.9771994018554687e+002 3.2354220581054687e+002 + 5.3152600097656250e+002 3.1252880859375000e+002 + 3.4963421630859375e+002 3.9690325927734375e+002 + 3.8645135498046875e+002 3.9166198730468750e+002 + 4.2541979980468750e+002 3.8327624511718750e+002 + 4.6422973632812500e+002 3.7354116821289062e+002 + 5.0031460571289062e+002 3.6263153076171875e+002 + 5.3276818847656250e+002 3.5073379516601562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.7436315917968750e+002 2.6418655395507812e+002 + 4.0039984130859375e+002 2.4244653320312500e+002 + 4.3018338012695312e+002 2.1849136352539062e+002 + 4.6110815429687500e+002 1.9421333312988281e+002 + 4.9216586303710937e+002 1.7026977539062500e+002 + 5.2132080078125000e+002 1.4797016906738281e+002 + 3.9056484985351562e+002 2.9746142578125000e+002 + 4.1949258422851563e+002 2.7744503784179687e+002 + 4.5166931152343750e+002 2.5424920654296875e+002 + 4.8513287353515625e+002 2.3015818786621094e+002 + 5.1818206787109375e+002 2.0549975585937500e+002 + 5.4837939453125000e+002 1.8309831237792969e+002 + 4.0739569091796875e+002 3.3266317749023437e+002 + 4.3849557495117187e+002 3.1436322021484375e+002 + 4.7258819580078125e+002 2.9367529296875000e+002 + 5.0828237915039062e+002 2.7009915161132812e+002 + 5.4251000976562500e+002 2.4662811279296875e+002 + 5.7345184326171875e+002 2.2304864501953125e+002 + 4.2362573242187500e+002 3.6796066284179687e+002 + 4.5644006347656250e+002 3.5272576904296875e+002 + 4.9169525146484375e+002 3.3399389648437500e+002 + 5.2859259033203125e+002 3.1247497558593750e+002 + 5.6332617187500000e+002 2.8936685180664062e+002 + 5.9405859375000000e+002 2.6613613891601562e+002 + 4.3900747680664062e+002 4.0234884643554687e+002 + 4.7210507202148437e+002 3.8951464843750000e+002 + 5.0787554931640625e+002 3.7366796875000000e+002 + 5.4425451660156250e+002 3.5405502319335937e+002 + 5.7900952148437500e+002 3.3260604858398437e+002 + 6.0941729736328125e+002 3.0915643310546875e+002 + 4.5228692626953125e+002 4.3317910766601562e+002 + 4.8503134155273437e+002 4.2371286010742187e+002 + 5.2047631835937500e+002 4.0941778564453125e+002 + 5.5585620117187500e+002 3.9258593750000000e+002 + 5.8965411376953125e+002 3.7191125488281250e+002 + 6.1959423828125000e+002 3.5035418701171875e+002 + 4.6415686035156250e+002 4.6136328125000000e+002 + 4.9571078491210937e+002 4.5251416015625000e+002 + 5.2948199462890625e+002 4.4174264526367187e+002 + 5.6333306884765625e+002 4.2608843994140625e+002 + 5.9576269531250000e+002 4.0772195434570312e+002 + 6.2465435791015625e+002 3.8658514404296875e+002 + 4.7364971923828125e+002 4.8450234985351562e+002 + 5.0400115966796875e+002 4.7784448242187500e+002 + 5.3593176269531250e+002 4.6801916503906250e+002 + 5.6780096435546875e+002 4.5448348999023437e+002 + 5.9859936523437500e+002 4.3824911499023437e+002 + 6.2647686767578125e+002 4.1821252441406250e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.1009748840332031e+002 2.4443733215332031e+002 + 2.3570234680175781e+002 2.1447442626953125e+002 + 2.6863629150390625e+002 1.8230126953125000e+002 + 3.0537890625000000e+002 1.5071452331542969e+002 + 3.4534829711914062e+002 1.2245578002929687e+002 + 3.8466314697265625e+002 9.8860282897949219e+001 + 2.3564408874511719e+002 2.7622009277343750e+002 + 2.6334652709960937e+002 2.4844660949707031e+002 + 2.9604269409179687e+002 2.1857478332519531e+002 + 3.3342324829101562e+002 1.8862068176269531e+002 + 3.7219769287109375e+002 1.6049482727050781e+002 + 4.1069601440429688e+002 1.3696289062500000e+002 + 2.6268121337890625e+002 3.0630444335937500e+002 + 2.8989410400390625e+002 2.8256341552734375e+002 + 3.2365658569335937e+002 2.5453007507324219e+002 + 3.6022067260742188e+002 2.2661802673339844e+002 + 3.9792462158203125e+002 2.0050393676757813e+002 + 4.3332049560546875e+002 1.7652470397949219e+002 + 2.8858596801757813e+002 3.3437222290039062e+002 + 3.1735235595703125e+002 3.1235321044921875e+002 + 3.4945553588867188e+002 2.8854788208007812e+002 + 3.8449288940429687e+002 2.6282336425781250e+002 + 4.1932586669921875e+002 2.3853909301757812e+002 + 4.5274630737304687e+002 2.1477763366699219e+002 + 3.1323522949218750e+002 3.5860800170898437e+002 + 3.4081283569335937e+002 3.4024816894531250e+002 + 3.7235531616210937e+002 3.1859317016601562e+002 + 4.0450070190429687e+002 2.9551229858398437e+002 + 4.3737442016601562e+002 2.7239331054687500e+002 + 4.6725082397460938e+002 2.5039245605468750e+002 + 3.3498397827148437e+002 3.7900720214843750e+002 + 3.6239990234375000e+002 3.6249365234375000e+002 + 3.9112094116210937e+002 3.4420059204101562e+002 + 4.2151074218750000e+002 3.2334701538085937e+002 + 4.5146215820312500e+002 3.0140341186523437e+002 + 4.8010440063476562e+002 2.8077691650390625e+002 + 3.5463659667968750e+002 3.9650671386718750e+002 + 3.8012548828125000e+002 3.8156973266601562e+002 + 4.0752035522460937e+002 3.6474468994140625e+002 + 4.3552902221679687e+002 3.4648913574218750e+002 + 4.6308877563476562e+002 3.2658969116210937e+002 + 4.8876071166992187e+002 3.0650180053710937e+002 + 3.7060375976562500e+002 4.1060482788085937e+002 + 3.9527972412109375e+002 3.9706018066406250e+002 + 4.2044830322265625e+002 3.8252545166015625e+002 + 4.4651202392578125e+002 3.6474179077148437e+002 + 4.7132431030273437e+002 3.4743432617187500e+002 + 4.9542980957031250e+002 3.2864117431640625e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0709756469726562e+002 3.0965753173828125e+002 + 2.4183863830566406e+002 2.9717437744140625e+002 + 2.8193728637695312e+002 2.8456869506835937e+002 + 3.2362149047851562e+002 2.7145623779296875e+002 + 3.6525765991210937e+002 2.6050451660156250e+002 + 4.0327322387695312e+002 2.5078736877441406e+002 + 2.1484167480468750e+002 3.5329516601562500e+002 + 2.5175173950195312e+002 3.4230596923828125e+002 + 2.9285339355468750e+002 3.2938021850585937e+002 + 3.3589212036132812e+002 3.1666174316406250e+002 + 3.7832296752929687e+002 3.0305282592773437e+002 + 4.1772619628906250e+002 2.9044281005859375e+002 + 2.2616299438476562e+002 3.9836734008789062e+002 + 2.6411621093750000e+002 3.8806500244140625e+002 + 3.0582656860351562e+002 3.7689151000976562e+002 + 3.4980050659179687e+002 3.6241369628906250e+002 + 3.9169226074218750e+002 3.4806533813476562e+002 + 4.2957034301757813e+002 3.3302224731445312e+002 + 2.4043191528320312e+002 4.4018423461914062e+002 + 2.7902380371093750e+002 4.3236373901367187e+002 + 3.2046249389648437e+002 4.2122604370117187e+002 + 3.6354171752929687e+002 4.0697204589843750e+002 + 4.0447589111328125e+002 3.9114196777343750e+002 + 4.4155834960937500e+002 3.7445608520507812e+002 + 2.5718334960937500e+002 4.7899169921875000e+002 + 2.9444030761718750e+002 4.7157882690429687e+002 + 3.3503781127929687e+002 4.6166268920898437e+002 + 3.7645187377929687e+002 4.4714770507812500e+002 + 4.1597955322265625e+002 4.3077090454101562e+002 + 4.5077206420898437e+002 4.1285253906250000e+002 + 2.7388284301757812e+002 5.1068182373046875e+002 + 3.1034515380859375e+002 5.0555154418945312e+002 + 3.4913006591796875e+002 4.9522879028320312e+002 + 3.8817813110351562e+002 4.8157928466796875e+002 + 4.2514419555664062e+002 4.6466650390625000e+002 + 4.5900500488281250e+002 4.4639065551757812e+002 + 2.9044958496093750e+002 5.3773828125000000e+002 + 3.2469036865234375e+002 5.3225109863281250e+002 + 3.6197085571289062e+002 5.2309063720703125e+002 + 3.9840051269531250e+002 5.1020233154296875e+002 + 4.3297988891601562e+002 4.9357302856445312e+002 + 4.6435983276367187e+002 4.7538415527343750e+002 + 3.0530343627929687e+002 5.5845788574218750e+002 + 3.3861846923828125e+002 5.5384759521484375e+002 + 3.7334664916992187e+002 5.4475305175781250e+002 + 4.0681497192382812e+002 5.3254943847656250e+002 + 4.3972396850585937e+002 5.1663751220703125e+002 + 4.6893658447265625e+002 4.9951690673828125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0647404479980469e+002 1.8367417907714844e+002 + 2.3695410156250000e+002 1.9436628723144531e+002 + 2.6793206787109375e+002 2.0669296264648437e+002 + 3.0172225952148437e+002 2.2110440063476562e+002 + 3.3200698852539062e+002 2.3366516113281250e+002 + 3.6120681762695312e+002 2.4782788085937500e+002 + 1.9059092712402344e+002 2.1606526184082031e+002 + 2.2136923217773437e+002 2.2772795104980469e+002 + 2.5480912780761719e+002 2.3968527221679687e+002 + 2.8986776733398437e+002 2.5422082519531250e+002 + 3.2363012695312500e+002 2.6726434326171875e+002 + 3.5444845581054687e+002 2.7968612670898437e+002 + 1.7445605468750000e+002 2.5322109985351562e+002 + 2.0675985717773437e+002 2.6519705200195312e+002 + 2.4260551452636719e+002 2.7860748291015625e+002 + 2.7889782714843750e+002 2.9163229370117187e+002 + 3.1412854003906250e+002 3.0362145996093750e+002 + 3.4716995239257812e+002 3.1494815063476562e+002 + 1.6107046508789062e+002 2.9385198974609375e+002 + 1.9434632873535156e+002 3.0752636718750000e+002 + 2.3130186462402344e+002 3.2046154785156250e+002 + 2.6855929565429687e+002 3.3262301635742187e+002 + 3.0586560058593750e+002 3.4321939086914062e+002 + 3.3966177368164062e+002 3.5275845336914062e+002 + 1.5018629455566406e+002 3.3659701538085937e+002 + 1.8407218933105469e+002 3.5019668579101562e+002 + 2.2125819396972656e+002 3.6358441162109375e+002 + 2.6024954223632812e+002 3.7423364257812500e+002 + 2.9769525146484375e+002 3.8365295410156250e+002 + 3.3253027343750000e+002 3.8961819458007812e+002 + 1.4410398864746094e+002 3.7861288452148437e+002 + 1.7720327758789062e+002 3.9300424194335937e+002 + 2.1514828491210937e+002 4.0552288818359375e+002 + 2.5338554382324219e+002 4.1550753784179687e+002 + 2.9161102294921875e+002 4.2195281982421875e+002 + 3.2616735839843750e+002 4.2685925292968750e+002 + 1.4249555969238281e+002 4.1871948242187500e+002 + 1.7508612060546875e+002 4.3168066406250000e+002 + 2.1140155029296875e+002 4.4429144287109375e+002 + 2.4892036437988281e+002 4.5235516357421875e+002 + 2.8613394165039062e+002 4.5807467651367187e+002 + 3.2029598999023437e+002 4.6010644531250000e+002 + 1.4364460754394531e+002 4.5310314941406250e+002 + 1.7516079711914063e+002 4.6721136474609375e+002 + 2.1038066101074219e+002 4.7765533447265625e+002 + 2.4655024719238281e+002 4.8546823120117187e+002 + 2.8208221435546875e+002 4.8884823608398437e+002 + 3.1538830566406250e+002 4.9014779663085937e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.9256420898437500e+002 1.3316365051269531e+002 + 3.2985421752929687e+002 1.2514764404296875e+002 + 3.7051663208007812e+002 1.2061127471923828e+002 + 4.1158502197265625e+002 1.1814923858642578e+002 + 4.5088571166992187e+002 1.2064416503906250e+002 + 4.8663995361328125e+002 1.2522171783447266e+002 + 2.9167681884765625e+002 1.6867283630371094e+002 + 3.3120040893554687e+002 1.6154115295410156e+002 + 3.7398532104492187e+002 1.5657025146484375e+002 + 4.1682015991210937e+002 1.5541845703125000e+002 + 4.5708386230468750e+002 1.5650508117675781e+002 + 4.9334188842773437e+002 1.6075065612792969e+002 + 2.9290927124023437e+002 2.0903230285644531e+002 + 3.3306613159179687e+002 2.0265928649902344e+002 + 3.7624078369140625e+002 1.9905741882324219e+002 + 4.2040606689453125e+002 1.9723043823242187e+002 + 4.6185662841796875e+002 1.9864994812011719e+002 + 4.9883728027343750e+002 2.0087243652343750e+002 + 2.9452697753906250e+002 2.5237539672851562e+002 + 3.3551263427734375e+002 2.4860549926757812e+002 + 3.7959399414062500e+002 2.4467161560058594e+002 + 4.2313784790039062e+002 2.4343008422851562e+002 + 4.6513150024414062e+002 2.4272555541992187e+002 + 5.0127813720703125e+002 2.4435061645507812e+002 + 2.9857968139648437e+002 2.9622424316406250e+002 + 3.3821615600585937e+002 2.9340591430664062e+002 + 3.8162554931640625e+002 2.9240029907226562e+002 + 4.2449755859375000e+002 2.8964810180664062e+002 + 4.6536959838867187e+002 2.8872940063476562e+002 + 5.0129171752929688e+002 2.8653085327148437e+002 + 3.0277523803710937e+002 3.3759136962890625e+002 + 3.4128536987304687e+002 3.3761160278320312e+002 + 3.8317431640625000e+002 3.3637048339843750e+002 + 4.2456359863281250e+002 3.3446844482421875e+002 + 4.6395364379882812e+002 3.3118267822265625e+002 + 4.9891732788085937e+002 3.2847106933593750e+002 + 3.0745544433593750e+002 3.7542971801757812e+002 + 3.4488562011718750e+002 3.7615554809570312e+002 + 3.8403948974609375e+002 3.7604144287109375e+002 + 4.2353833007812500e+002 3.7358541870117187e+002 + 4.6060995483398438e+002 3.7053927612304687e+002 + 4.9431283569335937e+002 3.6589926147460937e+002 + 3.1329550170898437e+002 4.0728869628906250e+002 + 3.4783734130859375e+002 4.0947094726562500e+002 + 3.8503701782226562e+002 4.0943371582031250e+002 + 4.2183291625976562e+002 4.0755865478515625e+002 + 4.5739483642578125e+002 4.0402081298828125e+002 + 4.8881237792968750e+002 3.9928466796875000e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.8399234008789062e+002 2.0360317993164062e+002 + 3.2220837402343750e+002 2.0217848205566406e+002 + 3.6278308105468750e+002 2.0352662658691406e+002 + 4.0427188110351562e+002 2.0571232604980469e+002 + 4.4269467163085937e+002 2.1069691467285156e+002 + 4.7859918212890625e+002 2.1662466430664062e+002 + 2.7693652343750000e+002 2.4172126770019531e+002 + 3.1744210815429687e+002 2.4205375671386719e+002 + 3.6052618408203125e+002 2.4346548461914063e+002 + 4.0383959960937500e+002 2.4691825866699219e+002 + 4.4492343139648437e+002 2.5022657775878906e+002 + 4.8164791870117187e+002 2.5575186157226562e+002 + 2.7139379882812500e+002 2.8528475952148437e+002 + 3.1210577392578125e+002 2.8674093627929687e+002 + 3.5812280273437500e+002 2.8999353027343750e+002 + 4.0325595092773437e+002 2.9213989257812500e+002 + 4.4609597778320312e+002 2.9584762573242187e+002 + 4.8358236694335937e+002 2.9828875732421875e+002 + 2.6680346679687500e+002 3.3074816894531250e+002 + 3.0887149047851562e+002 3.3565853881835937e+002 + 3.5472286987304687e+002 3.3838494873046875e+002 + 4.0102722167968750e+002 3.4133505249023437e+002 + 4.4447290039062500e+002 3.4233016967773437e+002 + 4.8247793579101562e+002 3.4302221679687500e+002 + 2.6483590698242187e+002 3.7761544799804687e+002 + 3.0633981323242187e+002 3.8272790527343750e+002 + 3.5152935791015625e+002 3.8747354125976562e+002 + 3.9783862304687500e+002 3.8911462402343750e+002 + 4.4133499145507812e+002 3.8932363891601562e+002 + 4.7961380004882812e+002 3.8680041503906250e+002 + 2.6553393554687500e+002 4.2023867797851562e+002 + 3.0536746215820312e+002 4.2770803833007812e+002 + 3.4969564819335938e+002 4.3184957885742187e+002 + 3.9495086669921875e+002 4.3386608886718750e+002 + 4.3715072631835937e+002 4.3199227905273437e+002 + 4.7460128784179687e+002 4.2824771118164062e+002 + 2.6709646606445312e+002 4.5836306762695312e+002 + 3.0650030517578125e+002 4.6623547363281250e+002 + 3.4771905517578125e+002 4.7122567749023437e+002 + 3.9064450073242187e+002 4.7163967895507812e+002 + 4.3141638183593750e+002 4.6995092773437500e+002 + 4.6777310180664062e+002 4.6438873291015625e+002 + 2.7049191284179687e+002 4.8942114257812500e+002 + 3.0729898071289063e+002 4.9768927001953125e+002 + 3.4673919677734375e+002 5.0233312988281250e+002 + 3.8699362182617187e+002 5.0334411621093750e+002 + 4.2466729736328125e+002 5.0070669555664062e+002 + 4.6003933715820312e+002 4.9575317382812500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.9134738159179687e+002 2.6866732788085937e+002 + 3.2707247924804687e+002 2.5673153686523437e+002 + 3.6527529907226562e+002 2.4593000793457031e+002 + 4.0322152709960937e+002 2.3611790466308594e+002 + 4.4053695678710937e+002 2.2708868408203125e+002 + 4.7445730590820312e+002 2.2011820983886719e+002 + 2.9702160644531250e+002 3.0646740722656250e+002 + 3.3398452758789062e+002 2.9699508666992187e+002 + 3.7366275024414062e+002 2.8626614379882812e+002 + 4.1408877563476562e+002 2.7555621337890625e+002 + 4.5317984008789063e+002 2.6543670654296875e+002 + 4.8794686889648438e+002 2.5705371093750000e+002 + 3.0390435791015625e+002 3.4795898437500000e+002 + 3.4147164916992187e+002 3.3942687988281250e+002 + 3.8285998535156250e+002 3.2992236328125000e+002 + 4.2475726318359375e+002 3.1855984497070312e+002 + 4.6483541870117187e+002 3.0744586181640625e+002 + 4.9922683715820312e+002 2.9722692871093750e+002 + 3.1135736083984375e+002 3.9015615844726562e+002 + 3.5034103393554687e+002 3.8350137329101563e+002 + 3.9235089111328125e+002 3.7423654174804687e+002 + 4.3443392944335937e+002 3.6370471191406250e+002 + 4.7396759033203125e+002 3.5133978271484375e+002 + 5.0925268554687500e+002 3.3935855102539062e+002 + 3.2046093750000000e+002 4.3056716918945312e+002 + 3.5938995361328125e+002 4.2519989013671875e+002 + 4.0057232666015625e+002 4.1775405883789062e+002 + 4.4242852783203125e+002 4.0636810302734375e+002 + 4.8207257080078125e+002 3.9371533203125000e+002 + 5.1625604248046875e+002 3.7958184814453125e+002 + 3.2956222534179687e+002 4.6645001220703125e+002 + 3.6832028198242187e+002 4.6316629028320312e+002 + 4.0843344116210937e+002 4.5613937377929687e+002 + 4.4907104492187500e+002 4.4555001831054687e+002 + 4.8675601196289062e+002 4.3257278442382812e+002 + 5.2075946044921875e+002 4.1777728271484375e+002 + 3.3924038696289062e+002 4.9837838745117187e+002 + 3.7556369018554687e+002 4.9499771118164062e+002 + 4.1461941528320312e+002 4.8963427734375000e+002 + 4.5300082397460938e+002 4.7936700439453125e+002 + 4.8940359497070312e+002 4.6661248779296875e+002 + 5.2210156250000000e+002 4.5150903320312500e+002 + 3.4753713989257812e+002 5.2432666015625000e+002 + 3.8324530029296875e+002 5.2269702148437500e+002 + 4.1981869506835937e+002 5.1683142089843750e+002 + 4.5609329223632812e+002 5.0748669433593750e+002 + 4.9046246337890625e+002 4.9548336791992187e+002 + 5.2164190673828125e+002 4.8068103027343750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.3239877319335937e+002 6.7654724121093750e+001 + 2.7254669189453125e+002 5.4803215026855469e+001 + 3.1627798461914062e+002 4.6094039916992187e+001 + 3.6034518432617187e+002 4.3011390686035156e+001 + 4.0218295288085937e+002 4.5147319793701172e+001 + 4.4049926757812500e+002 5.0752769470214844e+001 + 2.3283779907226562e+002 1.0223851013183594e+002 + 2.7426617431640625e+002 8.8749145507812500e+001 + 3.1880413818359375e+002 8.0109695434570312e+001 + 3.6401751708984375e+002 7.6589065551757813e+001 + 4.0653656005859375e+002 7.7529808044433594e+001 + 4.4472116088867187e+002 8.3450775146484375e+001 + 2.3650086975097656e+002 1.4118685913085937e+002 + 2.7753628540039062e+002 1.2860504150390625e+002 + 3.2211596679687500e+002 1.2038135528564453e+002 + 3.6727880859375000e+002 1.1565257263183594e+002 + 4.1005892944335937e+002 1.1600447845458984e+002 + 4.4764443969726562e+002 1.1923625946044922e+002 + 2.4170362854003906e+002 1.8245191955566406e+002 + 2.8275479125976562e+002 1.7194335937500000e+002 + 3.2655816650390625e+002 1.6355148315429687e+002 + 3.7091314697265625e+002 1.5896463012695312e+002 + 4.1220019531250000e+002 1.5674244689941406e+002 + 4.4928955078125000e+002 1.5851002502441406e+002 + 2.4974761962890625e+002 2.2523602294921875e+002 + 2.8887362670898437e+002 2.1513758850097656e+002 + 3.3137145996093750e+002 2.0821804809570312e+002 + 3.7422320556640625e+002 2.0230607604980469e+002 + 4.1427059936523437e+002 1.9901081848144531e+002 + 4.4965463256835937e+002 1.9734799194335937e+002 + 2.5913851928710937e+002 2.6456976318359375e+002 + 2.9657635498046875e+002 2.5740261840820312e+002 + 3.3643634033203125e+002 2.5032579040527344e+002 + 3.7722161865234375e+002 2.4430278015136719e+002 + 4.1444982910156250e+002 2.3944996643066406e+002 + 4.4825115966796875e+002 2.3592562866210937e+002 + 2.6927416992187500e+002 3.0102938842773437e+002 + 3.0451821899414062e+002 2.9443600463867187e+002 + 3.4148486328125000e+002 2.8828735351562500e+002 + 3.7899093627929687e+002 2.8129028320312500e+002 + 4.1428536987304687e+002 2.7583193969726562e+002 + 4.4612619018554687e+002 2.7075958251953125e+002 + 2.7899240112304688e+002 3.3095944213867187e+002 + 3.1161901855468750e+002 3.2616116333007812e+002 + 3.4580413818359375e+002 3.2049804687500000e+002 + 3.8066806030273437e+002 3.1383099365234375e+002 + 4.1289782714843750e+002 3.0812026977539062e+002 + 4.4305032348632812e+002 3.0172882080078125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.2315011596679687e+002 1.9762280273437500e+002 + 2.5141058349609375e+002 1.9500988769531250e+002 + 2.8282119750976562e+002 1.9398619079589844e+002 + 3.1555548095703125e+002 1.9373730468750000e+002 + 3.4782443237304687e+002 1.9505163574218750e+002 + 3.8035693359375000e+002 1.9849224853515625e+002 + 2.1777653503417969e+002 2.2869909667968750e+002 + 2.4744853210449219e+002 2.2766374206542969e+002 + 2.7973507690429687e+002 2.2619180297851562e+002 + 3.1368710327148437e+002 2.2633316040039062e+002 + 3.4793716430664062e+002 2.2734124755859375e+002 + 3.8083584594726562e+002 2.2994961547851563e+002 + 2.1421163940429687e+002 2.6350717163085937e+002 + 2.4474511718750000e+002 2.6217123413085937e+002 + 2.7737985229492187e+002 2.6238601684570312e+002 + 3.1223394775390625e+002 2.6233013916015625e+002 + 3.4711334228515625e+002 2.6346060180664062e+002 + 3.8075625610351562e+002 2.6464254760742187e+002 + 2.1217524719238281e+002 2.9937625122070313e+002 + 2.4258055114746094e+002 2.9965649414062500e+002 + 2.7642926025390625e+002 2.9967813110351562e+002 + 3.1178363037109375e+002 3.0076562500000000e+002 + 3.4680224609375000e+002 3.0054412841796875e+002 + 3.8111755371093750e+002 3.0080877685546875e+002 + 2.1244862365722656e+002 3.3675283813476562e+002 + 2.4281117248535156e+002 3.3754986572265625e+002 + 2.7614202880859375e+002 3.3861691284179687e+002 + 3.1204382324218750e+002 3.3838394165039062e+002 + 3.4721841430664062e+002 3.3790917968750000e+002 + 3.8094525146484375e+002 3.3668289184570312e+002 + 2.1456909179687500e+002 3.7236727905273437e+002 + 2.4468826293945313e+002 3.7496084594726562e+002 + 2.7847088623046875e+002 3.7526092529296875e+002 + 3.1280200195312500e+002 3.7563528442382812e+002 + 3.4764123535156250e+002 3.7423672485351562e+002 + 3.8095953369140625e+002 3.7272988891601562e+002 + 2.1874980163574219e+002 4.0640997314453125e+002 + 2.4827583312988281e+002 4.0837896728515625e+002 + 2.8072943115234375e+002 4.0999151611328125e+002 + 3.1428582763671875e+002 4.0971102905273438e+002 + 3.4801791381835937e+002 4.0862448120117187e+002 + 3.8067495727539062e+002 4.0483074951171875e+002 + 2.2448921203613281e+002 4.3545028686523437e+002 + 2.5279331970214844e+002 4.3888534545898437e+002 + 2.8367517089843750e+002 4.4056774902343750e+002 + 3.1675656127929687e+002 4.4023281860351562e+002 + 3.4900509643554687e+002 4.3826046752929687e+002 + 3.7958532714843750e+002 4.3510290527343750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.5202261352539062e+002 1.5841270446777344e+002 + 2.8272497558593750e+002 1.3750520324707031e+002 + 3.1896166992187500e+002 1.1752564239501953e+002 + 3.5868273925781250e+002 9.9736312866210937e+001 + 4.0171234130859375e+002 8.5327033996582031e+001 + 4.4373138427734375e+002 7.5846504211425781e+001 + 2.6289642333984375e+002 1.9209381103515625e+002 + 2.9446203613281250e+002 1.7435845947265625e+002 + 3.3259149169921875e+002 1.5467070007324219e+002 + 3.7445971679687500e+002 1.3749337768554687e+002 + 4.1792132568359375e+002 1.2347884368896484e+002 + 4.6150765991210937e+002 1.1398068237304687e+002 + 2.7535620117187500e+002 2.3011090087890625e+002 + 3.0774356079101562e+002 2.1368406677246094e+002 + 3.4708532714843750e+002 1.9700260925292969e+002 + 3.9009350585937500e+002 1.8115551757812500e+002 + 4.3493917846679687e+002 1.6762898254394531e+002 + 4.7800009155273437e+002 1.5742147827148437e+002 + 2.8865554809570312e+002 2.6859527587890625e+002 + 3.2262142944335937e+002 2.5573518371582031e+002 + 3.6227453613281250e+002 2.4111032104492187e+002 + 4.0474313354492187e+002 2.2740176391601562e+002 + 4.4902017211914062e+002 2.1448281860351562e+002 + 4.9159429931640625e+002 2.0428511047363281e+002 + 3.0345550537109375e+002 3.0636480712890625e+002 + 3.3728869628906250e+002 2.9601623535156250e+002 + 3.7556234741210937e+002 2.8543270874023437e+002 + 4.1741171264648437e+002 2.7316036987304687e+002 + 4.6048236083984375e+002 2.6186044311523437e+002 + 5.0089562988281250e+002 2.5055921936035156e+002 + 3.1821243286132813e+002 3.4063818359375000e+002 + 3.5101458740234375e+002 3.3381295776367188e+002 + 3.8831875610351562e+002 3.2513784790039062e+002 + 4.2805343627929687e+002 3.1563919067382812e+002 + 4.6839904785156250e+002 3.0469326782226562e+002 + 5.0665658569335937e+002 2.9435540771484375e+002 + 3.3173571777343750e+002 3.7129977416992187e+002 + 3.6342205810546875e+002 3.6628649902343750e+002 + 3.9921981811523437e+002 3.6029620361328125e+002 + 4.3635156250000000e+002 3.5159204101562500e+002 + 4.7422497558593750e+002 3.4262179565429687e+002 + 5.0894808959960938e+002 3.3214703369140625e+002 + 3.4421890258789062e+002 3.9697036743164062e+002 + 3.7470574951171875e+002 3.9424554443359375e+002 + 4.0757733154296875e+002 3.8938739013671875e+002 + 4.4237197875976562e+002 3.8231832885742187e+002 + 4.7685812377929687e+002 3.7380377197265625e+002 + 5.0981469726562500e+002 3.6448071289062500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.7865925598144531e+002 3.0756106567382812e+002 + 2.0467779541015625e+002 2.8785388183593750e+002 + 2.3350169372558594e+002 2.6757385253906250e+002 + 2.6458694458007812e+002 2.4754595947265625e+002 + 2.9490078735351562e+002 2.3001069641113281e+002 + 3.2431430053710937e+002 2.1441699218750000e+002 + 1.8863381958007813e+002 3.4014913940429687e+002 + 2.1660745239257812e+002 3.1932772827148437e+002 + 2.4813206481933594e+002 2.9651702880859375e+002 + 2.8052371215820312e+002 2.7563589477539062e+002 + 3.1255484008789063e+002 2.5571339416503906e+002 + 3.4354309082031250e+002 2.3782160949707031e+002 + 2.0333032226562500e+002 3.7584631347656250e+002 + 2.3275288391113281e+002 3.5423245239257812e+002 + 2.6625234985351562e+002 3.3112347412109375e+002 + 3.0029016113281250e+002 3.0732400512695312e+002 + 3.3376324462890625e+002 2.8554589843750000e+002 + 3.6504058837890625e+002 2.6541937255859375e+002 + 2.2160528564453125e+002 4.1457211303710937e+002 + 2.5305433654785156e+002 3.9265084838867187e+002 + 2.8797232055664062e+002 3.6830453491210937e+002 + 3.2337997436523437e+002 3.4296844482421875e+002 + 3.5748660278320312e+002 3.1819903564453125e+002 + 3.8849182128906250e+002 2.9568215942382812e+002 + 2.4479512023925781e+002 4.5369961547851562e+002 + 2.7747604370117187e+002 4.3208078002929687e+002 + 3.1336276245117187e+002 4.0710617065429687e+002 + 3.4914361572265625e+002 3.7973400878906250e+002 + 3.8308166503906250e+002 3.5308993530273437e+002 + 4.1278494262695312e+002 3.2798852539062500e+002 + 2.7077493286132812e+002 4.9053186035156250e+002 + 3.0505694580078125e+002 4.6963546752929687e+002 + 3.4081625366210937e+002 4.4462951660156250e+002 + 3.7634460449218750e+002 4.1666189575195312e+002 + 4.0869729614257812e+002 3.8782882690429688e+002 + 4.3739407348632812e+002 3.6060003662109375e+002 + 2.9950219726562500e+002 5.2279260253906250e+002 + 3.3264089965820312e+002 5.0331225585937500e+002 + 3.6847088623046875e+002 4.7812741088867187e+002 + 4.0245797729492187e+002 4.4972784423828125e+002 + 4.3364620971679687e+002 4.2004687500000000e+002 + 4.6004971313476562e+002 3.9143750000000000e+002 + 3.2718725585937500e+002 5.4946295166015625e+002 + 3.6035107421875000e+002 5.3046783447265625e+002 + 3.9448815917968750e+002 5.0694458007812500e+002 + 4.2656427001953125e+002 4.7846740722656250e+002 + 4.5544967651367187e+002 4.4926992797851562e+002 + 4.8016619873046875e+002 4.1998165893554687e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.0040686035156250e+002 3.2073614501953125e+002 + 3.1948165893554687e+002 3.0393081665039062e+002 + 3.3954699707031250e+002 2.8651651000976563e+002 + 3.5916162109375000e+002 2.6963174438476562e+002 + 3.7846365356445312e+002 2.5344624328613281e+002 + 3.9711032104492187e+002 2.3780197143554687e+002 + 3.1429376220703125e+002 3.4232406616210937e+002 + 3.3468905639648437e+002 3.2427856445312500e+002 + 3.5506903076171875e+002 3.0653945922851563e+002 + 3.7556469726562500e+002 2.8858636474609375e+002 + 3.9523907470703125e+002 2.7138854980468750e+002 + 4.1374725341796875e+002 2.5531755065917969e+002 + 3.2965649414062500e+002 3.6446893310546875e+002 + 3.5052258300781250e+002 3.4620364379882812e+002 + 3.7185974121093750e+002 3.2778503417968750e+002 + 3.9251843261718750e+002 3.0942916870117187e+002 + 4.1262167358398437e+002 2.9148428344726562e+002 + 4.3140429687500000e+002 2.7413345336914062e+002 + 3.4612115478515625e+002 3.8679284667968750e+002 + 3.6762512207031250e+002 3.6889273071289063e+002 + 3.8923193359375000e+002 3.4990051269531250e+002 + 4.1042001342773437e+002 3.3065811157226562e+002 + 4.3040026855468750e+002 3.1199743652343750e+002 + 4.4900253295898437e+002 2.9391918945312500e+002 + 3.6334326171875000e+002 4.0990539550781250e+002 + 3.8531521606445312e+002 3.9144000244140625e+002 + 4.0722732543945312e+002 3.7216723632812500e+002 + 4.2836248779296875e+002 3.5261526489257812e+002 + 4.4836776733398437e+002 3.3351861572265625e+002 + 4.6647430419921875e+002 3.1445104980468750e+002 + 3.8059667968750000e+002 4.3202371215820312e+002 + 4.0290133666992187e+002 4.1386962890625000e+002 + 4.2478155517578125e+002 3.9442404174804688e+002 + 4.4619384765625000e+002 3.7454949951171875e+002 + 4.6559829711914062e+002 3.5467648315429687e+002 + 4.8363949584960937e+002 3.3580447387695312e+002 + 3.9811520385742187e+002 4.5324191284179687e+002 + 4.2026861572265625e+002 4.3518679809570312e+002 + 4.4227304077148437e+002 4.1580789184570312e+002 + 4.6290213012695312e+002 3.9582965087890625e+002 + 4.8234155273437500e+002 3.7570520019531250e+002 + 4.9946917724609375e+002 3.5537255859375000e+002 + 4.1460549926757812e+002 4.7208721923828125e+002 + 4.3667517089843750e+002 4.5507092285156250e+002 + 4.5821704101562500e+002 4.3586709594726562e+002 + 4.7862161254882812e+002 4.1546368408203125e+002 + 4.9721343994140625e+002 3.9576171875000000e+002 + 5.1420391845703125e+002 3.7546047973632812e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 3.2050097656250000e+002 2.2883522033691406e+002 + 3.3435357666015625e+002 2.1017816162109375e+002 + 3.4864022827148437e+002 1.8980599975585937e+002 + 3.6439633178710937e+002 1.7034527587890625e+002 + 3.8032778930664062e+002 1.5117919921875000e+002 + 3.9622409057617187e+002 1.3227835083007812e+002 + 3.3696444702148437e+002 2.4490312194824219e+002 + 3.5156146240234375e+002 2.2572611999511719e+002 + 3.6698574829101562e+002 2.0654919433593750e+002 + 3.8340969848632812e+002 1.8643966674804687e+002 + 3.9960488891601562e+002 1.6692265319824219e+002 + 4.1633432006835937e+002 1.4817070007324219e+002 + 3.5450616455078125e+002 2.6164855957031250e+002 + 3.6938552856445312e+002 2.4343035888671875e+002 + 3.8556338500976562e+002 2.2366665649414062e+002 + 4.0244302368164062e+002 2.0402769470214844e+002 + 4.1934671020507813e+002 1.8444593811035156e+002 + 4.3626248168945312e+002 1.6554064941406250e+002 + 3.7139697265625000e+002 2.7938195800781250e+002 + 3.8764349365234375e+002 2.6158154296875000e+002 + 4.0429003906250000e+002 2.4226045227050781e+002 + 4.2161871337890625e+002 2.2246328735351562e+002 + 4.3879757690429688e+002 2.0345568847656250e+002 + 4.5579116821289062e+002 1.8440426635742187e+002 + 3.8881698608398437e+002 2.9709609985351562e+002 + 4.0510714721679687e+002 2.7936010742187500e+002 + 4.2260806274414062e+002 2.6126907348632812e+002 + 4.4001162719726562e+002 2.4209210205078125e+002 + 4.5767160034179687e+002 2.2254673767089844e+002 + 4.7473605346679687e+002 2.0405941772460937e+002 + 4.0564413452148437e+002 3.1424929809570312e+002 + 4.2268048095703125e+002 2.9762945556640625e+002 + 4.4011041259765625e+002 2.7977230834960937e+002 + 4.5799972534179687e+002 2.6155706787109375e+002 + 4.7546566772460937e+002 2.4282090759277344e+002 + 4.9234545898437500e+002 2.2449223327636719e+002 + 4.2208834838867187e+002 3.3111758422851562e+002 + 4.3891973876953125e+002 3.1551364135742187e+002 + 4.5677990722656250e+002 2.9827026367187500e+002 + 4.7444012451171875e+002 2.8091998291015625e+002 + 4.9186828613281250e+002 2.6306106567382812e+002 + 5.0850216674804688e+002 2.4459852600097656e+002 + 4.3722528076171875e+002 3.4745227050781250e+002 + 4.5450100708007812e+002 3.3195590209960937e+002 + 4.7199118041992187e+002 3.1632809448242187e+002 + 4.8949755859375000e+002 2.9964196777343750e+002 + 5.0648181152343750e+002 2.8223489379882812e+002 + 5.2281182861328125e+002 2.6415667724609375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.6377696228027344e+002 2.0158671569824219e+002 + 1.7501095581054687e+002 1.7495938110351562e+002 + 1.9040240478515625e+002 1.4785726928710937e+002 + 2.0699365234375000e+002 1.2143093872070312e+002 + 2.2635098266601562e+002 9.5515525817871094e+001 + 2.4728222656250000e+002 7.1824806213378906e+001 + 1.8331561279296875e+002 2.1353720092773437e+002 + 1.9636515808105469e+002 1.8779682922363281e+002 + 2.1114889526367187e+002 1.6144001770019531e+002 + 2.2853144836425781e+002 1.3533802795410156e+002 + 2.4725259399414062e+002 1.0968914794921875e+002 + 2.6798986816406250e+002 8.5467330932617188e+001 + 2.0435374450683594e+002 2.2542170715332031e+002 + 2.1773490905761719e+002 2.0141673278808594e+002 + 2.3316366577148437e+002 1.7552757263183594e+002 + 2.5048370361328125e+002 1.5017395019531250e+002 + 2.6927517700195312e+002 1.2535332489013672e+002 + 2.8923049926757812e+002 1.0190052795410156e+002 + 2.2573472595214844e+002 2.3894653320312500e+002 + 2.3943940734863281e+002 2.1481024169921875e+002 + 2.5486485290527344e+002 1.9015917968750000e+002 + 2.7245837402343750e+002 1.6575233459472656e+002 + 2.9068521118164062e+002 1.4168701171875000e+002 + 3.1059420776367187e+002 1.1960120391845703e+002 + 2.4748832702636719e+002 2.5151004028320312e+002 + 2.6117575073242187e+002 2.2857957458496094e+002 + 2.7686389160156250e+002 2.0542660522460937e+002 + 2.9356619262695312e+002 1.8168370056152344e+002 + 3.1190823364257812e+002 1.5884866333007813e+002 + 3.3052401733398437e+002 1.3749113464355469e+002 + 2.6825299072265625e+002 2.6376251220703125e+002 + 2.8242861938476562e+002 2.4243983459472656e+002 + 2.9771597290039062e+002 2.1998490905761719e+002 + 3.1447726440429687e+002 1.9764816284179687e+002 + 3.3167010498046875e+002 1.7570973205566406e+002 + 3.4957028198242187e+002 1.5493548583984375e+002 + 2.8783929443359375e+002 2.7487081909179687e+002 + 3.0205429077148437e+002 2.5474137878417969e+002 + 3.1751660156250000e+002 2.3434712219238281e+002 + 3.3355059814453125e+002 2.1350343322753906e+002 + 3.5041949462890625e+002 1.9188749694824219e+002 + 3.6712387084960937e+002 1.7292967224121094e+002 + 3.0617047119140625e+002 2.8550985717773437e+002 + 3.2049517822265625e+002 2.6649945068359375e+002 + 3.3529876708984375e+002 2.4754885864257812e+002 + 3.5070306396484375e+002 2.2768142700195312e+002 + 3.6675286865234375e+002 2.0747404479980469e+002 + 3.8264489746093750e+002 1.8948219299316406e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.1662733459472656e+002 2.9195550537109375e+002 + 2.4335379028320312e+002 2.6856875610351562e+002 + 2.7256610107421875e+002 2.4532009887695312e+002 + 3.0320022583007812e+002 2.2288313293457031e+002 + 3.3340536499023437e+002 2.0279925537109375e+002 + 3.6195999145507812e+002 1.8510800170898437e+002 + 2.3350505065917969e+002 3.2425650024414062e+002 + 2.6161770629882813e+002 3.0043490600585937e+002 + 2.9173855590820312e+002 2.7632791137695312e+002 + 3.2340057373046875e+002 2.5253588867187500e+002 + 3.5406518554687500e+002 2.3121519470214844e+002 + 3.8277212524414062e+002 2.1228379821777344e+002 + 2.5367022705078125e+002 3.5780108642578125e+002 + 2.8246585083007812e+002 3.3435760498046875e+002 + 3.1369754028320312e+002 3.1019876098632812e+002 + 3.4550115966796875e+002 2.8540127563476562e+002 + 3.7640252685546875e+002 2.6235842895507812e+002 + 4.0438473510742187e+002 2.4143948364257812e+002 + 2.7593676757812500e+002 3.9122610473632812e+002 + 3.0553738403320312e+002 3.6862506103515625e+002 + 3.3725958251953125e+002 3.4371661376953125e+002 + 3.6877493286132813e+002 3.1874539184570312e+002 + 3.9869757080078125e+002 2.9449731445312500e+002 + 4.2594555664062500e+002 2.7257537841796875e+002 + 2.9982769775390625e+002 4.2244604492187500e+002 + 3.2966110229492187e+002 4.0110833740234375e+002 + 3.6083776855468750e+002 3.7680096435546875e+002 + 3.9148809814453125e+002 3.5221783447265625e+002 + 4.2061856079101562e+002 3.2660342407226562e+002 + 4.4635913085937500e+002 3.0367251586914063e+002 + 3.2368002319335937e+002 4.5152154541015625e+002 + 3.5307052612304687e+002 4.3087475585937500e+002 + 3.8344647216796875e+002 4.0765197753906250e+002 + 4.1293530273437500e+002 3.8299987792968750e+002 + 4.4038778686523437e+002 3.5747131347656250e+002 + 4.6479864501953125e+002 3.3343005371093750e+002 + 3.4641592407226562e+002 4.7600094604492188e+002 + 3.7525839233398437e+002 4.5630297851562500e+002 + 4.0420272827148437e+002 4.3434597778320312e+002 + 4.3193814086914062e+002 4.1025128173828125e+002 + 4.5795846557617187e+002 3.8531039428710937e+002 + 4.8069030761718750e+002 3.6064907836914062e+002 + 3.6710751342773437e+002 4.9635220336914062e+002 + 3.9480609130859375e+002 4.7827105712890625e+002 + 4.2235433959960937e+002 4.5649145507812500e+002 + 4.4859393310546875e+002 4.3360281372070312e+002 + 4.7282925415039062e+002 4.0985794067382812e+002 + 4.9419647216796875e+002 3.8568722534179687e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.4031932067871094e+002 3.0966931152343750e+002 + 1.6560198974609375e+002 2.8725933837890625e+002 + 1.9619644165039062e+002 2.6290176391601563e+002 + 2.2782133483886719e+002 2.4149354553222656e+002 + 2.6073608398437500e+002 2.2089122009277344e+002 + 2.9244897460937500e+002 2.0404563903808594e+002 + 1.5471949768066406e+002 3.4676361083984375e+002 + 1.8193783569335938e+002 3.2317593383789062e+002 + 2.1309101867675781e+002 2.9802178955078125e+002 + 2.4614175415039062e+002 2.7470730590820312e+002 + 2.7943963623046875e+002 2.5237356567382812e+002 + 3.1109341430664062e+002 2.3367652893066406e+002 + 1.7478184509277344e+002 3.8454412841796875e+002 + 2.0245068359375000e+002 3.6066098022460937e+002 + 2.3414508056640625e+002 3.3630789184570312e+002 + 2.6750759887695312e+002 3.1054626464843750e+002 + 3.0093237304687500e+002 2.8673083496093750e+002 + 3.3192941284179687e+002 2.6536035156250000e+002 + 1.9834431457519531e+002 4.2264498901367187e+002 + 2.2691986083984375e+002 3.9950991821289062e+002 + 2.5857431030273437e+002 3.7419876098632812e+002 + 2.9152529907226562e+002 3.4787673950195312e+002 + 3.2415054321289063e+002 3.2200128173828125e+002 + 3.5392132568359375e+002 2.9865594482421875e+002 + 2.2571826171875000e+002 4.5763577270507812e+002 + 2.5400585937500000e+002 4.3521679687500000e+002 + 2.8548422241210937e+002 4.1020266723632812e+002 + 3.1728106689453125e+002 3.8313482666015625e+002 + 3.4811096191406250e+002 3.5612838745117187e+002 + 3.7569650268554688e+002 3.3102221679687500e+002 + 2.5387190246582031e+002 4.8773727416992187e+002 + 2.8233282470703125e+002 4.6685296630859375e+002 + 3.1231384277343750e+002 4.4206326293945312e+002 + 3.4242144775390625e+002 4.1537680053710937e+002 + 3.7083157348632812e+002 3.8831539916992187e+002 + 3.9678823852539062e+002 3.6202618408203125e+002 + 2.8197827148437500e+002 5.1316595458984375e+002 + 3.0927148437500000e+002 4.9260528564453125e+002 + 3.3763082885742187e+002 4.6894064331054687e+002 + 3.6575967407226562e+002 4.4311325073242187e+002 + 3.9210394287109375e+002 4.1605166625976562e+002 + 4.1529830932617187e+002 3.9018496704101562e+002 + 3.0776440429687500e+002 5.3242144775390625e+002 + 3.3417050170898437e+002 5.1346148681640625e+002 + 3.6065261840820312e+002 4.9127917480468750e+002 + 3.8654626464843750e+002 4.6561108398437500e+002 + 4.1047024536132812e+002 4.3986962890625000e+002 + 4.3215371704101562e+002 4.1409579467773437e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 8.7393341064453125e+001 2.0304212951660156e+002 + 1.1273602294921875e+002 1.6859410095214844e+002 + 1.4384899902343750e+002 1.3637660217285156e+002 + 1.7922142028808594e+002 1.0801432037353516e+002 + 2.1601806640625000e+002 8.5311737060546875e+001 + 2.5168167114257812e+002 6.8132026672363281e+001 + 1.0176625061035156e+002 2.3547706604003906e+002 + 1.2761727142333984e+002 2.0042086791992187e+002 + 1.5914683532714844e+002 1.6790519714355469e+002 + 1.9451683044433594e+002 1.3789768981933594e+002 + 2.3114154052734375e+002 1.1360969543457031e+002 + 2.6694122314453125e+002 9.4877052307128906e+001 + 1.2139710235595703e+002 2.6830041503906250e+002 + 1.4705302429199219e+002 2.3525231933593750e+002 + 1.7840213012695312e+002 2.0156437683105469e+002 + 2.1318832397460937e+002 1.7167747497558594e+002 + 2.4938815307617187e+002 1.4547543334960937e+002 + 2.8363018798828125e+002 1.2593746948242187e+002 + 1.4480131530761719e+002 3.0170339965820313e+002 + 1.7087023925781250e+002 2.6953921508789062e+002 + 2.0081840515136719e+002 2.3756985473632812e+002 + 2.3470732116699219e+002 2.0655604553222656e+002 + 2.6910888671875000e+002 1.8010639953613281e+002 + 3.0144244384765625e+002 1.5894775390625000e+002 + 1.7185314941406250e+002 3.3347286987304687e+002 + 1.9698973083496094e+002 3.0259222412109375e+002 + 2.2643444824218750e+002 2.7143487548828125e+002 + 2.5784695434570312e+002 2.4151707458496094e+002 + 2.8961273193359375e+002 2.1530905151367187e+002 + 3.1951766967773437e+002 1.9256394958496094e+002 + 1.9929553222656250e+002 3.6106011962890625e+002 + 2.2407501220703125e+002 3.3302035522460937e+002 + 2.5148051452636719e+002 3.0359942626953125e+002 + 2.8063372802734375e+002 2.7507284545898437e+002 + 3.0963681030273437e+002 2.4791481018066406e+002 + 3.3705004882812500e+002 2.2472257995605469e+002 + 2.2637937927246094e+002 3.8362722778320312e+002 + 2.4961903381347656e+002 3.5817443847656250e+002 + 2.7535992431640625e+002 3.3145175170898437e+002 + 3.0165457153320312e+002 3.0359240722656250e+002 + 3.2810562133789062e+002 2.7832482910156250e+002 + 3.5263073730468750e+002 2.5453082275390625e+002 + 2.5055741882324219e+002 4.0273898315429687e+002 + 2.7285708618164062e+002 3.7940426635742187e+002 + 2.9663601684570312e+002 3.5456903076171875e+002 + 3.2078005981445312e+002 3.2898022460937500e+002 + 3.4390426635742187e+002 3.0480798339843750e+002 + 3.6634384155273438e+002 2.8150442504882812e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.3247393798828125e+002 2.1941508483886719e+002 + 2.6543295288085937e+002 1.8373118591308594e+002 + 3.0423803710937500e+002 1.4974131774902344e+002 + 3.4413516235351562e+002 1.1961538696289063e+002 + 3.8250222778320312e+002 9.6102050781250000e+001 + 4.1660440063476562e+002 7.8561805725097656e+001 + 2.6208984375000000e+002 2.5437300109863281e+002 + 2.9633090209960937e+002 2.2131890869140625e+002 + 3.3438058471679687e+002 1.8726797485351562e+002 + 3.7336959838867187e+002 1.5763549804687500e+002 + 4.0939663696289062e+002 1.3272402954101562e+002 + 4.4185357666015625e+002 1.1400006103515625e+002 + 2.9283020019531250e+002 2.8959762573242187e+002 + 3.2680950927734375e+002 2.5743432617187500e+002 + 3.6378707885742187e+002 2.2659436035156250e+002 + 4.0024487304687500e+002 1.9759977722167969e+002 + 4.3448648071289062e+002 1.7216107177734375e+002 + 4.6367120361328125e+002 1.5151803588867187e+002 + 3.2162347412109375e+002 3.1955484008789062e+002 + 3.5543551635742187e+002 2.9260150146484375e+002 + 3.8987689208984375e+002 2.6351995849609375e+002 + 4.2378698730468750e+002 2.3550224304199219e+002 + 4.5532205200195312e+002 2.0993708801269531e+002 + 4.8236157226562500e+002 1.8849958801269531e+002 + 3.4851007080078125e+002 3.4773696899414062e+002 + 3.7962466430664062e+002 3.2210784912109375e+002 + 4.1242221069335937e+002 2.9551763916015625e+002 + 4.4314883422851563e+002 2.6958294677734375e+002 + 4.7212237548828125e+002 2.4524090576171875e+002 + 4.9652740478515625e+002 2.2309829711914062e+002 + 3.7105560302734375e+002 3.6957116699218750e+002 + 4.0061654663085937e+002 3.4776773071289063e+002 + 4.3021408081054687e+002 3.2372470092773437e+002 + 4.5866513061523437e+002 2.9951840209960937e+002 + 4.8484436035156250e+002 2.7565859985351562e+002 + 5.0840087890625000e+002 2.5329977416992188e+002 + 3.9031921386718750e+002 3.8808978271484375e+002 + 4.1735873413085937e+002 3.6785293579101562e+002 + 4.4447015380859375e+002 3.4724633789062500e+002 + 4.7082180786132812e+002 3.2382867431640625e+002 + 4.9473291015625000e+002 3.0170718383789062e+002 + 5.1569647216796875e+002 2.8062826538085937e+002 + 4.0534713745117187e+002 4.0341967773437500e+002 + 4.3104406738281250e+002 3.8525509643554687e+002 + 4.5617553710937500e+002 3.6541107177734375e+002 + 4.7991671752929687e+002 3.4454394531250000e+002 + 5.0250738525390625e+002 3.2362503051757813e+002 + 5.2169354248046875e+002 3.0348312377929687e+002
+ + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 197. 82. 2.2720941162109375e+002 7.1443656921386719e+001 + 2.6526123046875000e+002 6.4269180297851562e+001 + 3.1135729980468750e+002 5.9361694335937500e+001 + 3.6215856933593750e+002 6.1320884704589844e+001 + 4.1483734130859375e+002 6.9252204895019531e+001 + 1.8174520874023437e+002 1.1511978912353516e+002 + 2.1312260437011719e+002 1.0730918121337891e+002 + 2.5216734313964844e+002 1.0144420623779297e+002 + 3.0020162963867187e+002 9.8961624145507813e+001 + 3.5552404785156250e+002 1.0146884155273437e+002 + 4.1291729736328125e+002 1.1049095153808594e+002 + 1.6949475097656250e+002 1.5642324829101562e+002 + 1.9887879943847656e+002 1.5215815734863281e+002 + 2.3823164367675781e+002 1.4950430297851562e+002 + 2.8768432617187500e+002 1.4882575988769531e+002 + 3.4641549682617187e+002 1.5302746582031250e+002 + 4.0825708007812500e+002 1.6396650695800781e+002 + 1.5948106384277344e+002 2.0210423278808594e+002 + 1.8849992370605469e+002 2.0232087707519531e+002 + 2.2713320922851562e+002 2.0445036315917969e+002 + 2.7638317871093750e+002 2.0851496887207031e+002 + 3.3672091674804687e+002 2.1646299743652344e+002 + 4.0064074707031250e+002 2.2745191955566406e+002 + 1.5307701110839844e+002 2.4879789733886719e+002 + 1.8104777526855469e+002 2.5565878295898437e+002 + 2.1853112792968750e+002 2.6351843261718750e+002 + 2.6750958251953125e+002 2.7285342407226562e+002 + 3.2657138061523437e+002 2.8376568603515625e+002 + 3.9019552612304687e+002 2.9547375488281250e+002 + 1.5140339660644531e+002 2.9569943237304687e+002 + 1.7875170898437500e+002 3.0675027465820312e+002 + 2.1543229675292969e+002 3.1940103149414062e+002 + 2.6191143798828125e+002 3.3306442260742187e+002 + 3.1834231567382812e+002 3.4717276000976563e+002 + 3.7755072021484375e+002 3.5771261596679687e+002 + 1.5380444335937500e+002 3.3815856933593750e+002 + 1.8092079162597656e+002 3.5263537597656250e+002 + 2.1585163879394531e+002 3.6833901977539062e+002 + 2.5958074951171875e+002 3.8394808959960937e+002 + 3.1064172363281250e+002 3.9782757568359375e+002 + 3.6522851562500000e+002 4.0781399536132812e+002 + 1.5862858581542969e+002 3.7516677856445312e+002 + 1.8554963684082031e+002 3.9137442016601562e+002 + 2.1861750793457031e+002 4.0789639282226562e+002 + 2.5908026123046875e+002 4.2382254028320312e+002 + 3.0611975097656250e+002 4.3742028808593750e+002 + 3.5506451416015625e+002 4.4661376953125000e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.8885025024414062e+002 1.2868571472167969e+002 + 2.1940495300292969e+002 1.2314788818359375e+002 + 2.5802456665039062e+002 1.1683652496337891e+002 + 3.0322348022460937e+002 1.1484284973144531e+002 + 3.5399465942382812e+002 1.1641961669921875e+002 + 4.0796203613281250e+002 1.2297351074218750e+002 + 1.7310934448242187e+002 1.6635493469238281e+002 + 2.0337179565429687e+002 1.6170866394042969e+002 + 2.4212171936035156e+002 1.5890231323242187e+002 + 2.9111611938476562e+002 1.5775895690917969e+002 + 3.4745977783203125e+002 1.6033096313476562e+002 + 4.0702218627929687e+002 1.6861499023437500e+002 + 1.5829951477050781e+002 2.0906207275390625e+002 + 1.8819346618652344e+002 2.0887733459472656e+002 + 2.2732676696777344e+002 2.0961596679687500e+002 + 2.7795974731445312e+002 2.1299592590332031e+002 + 3.3899600219726562e+002 2.1877767944335937e+002 + 4.0372378540039062e+002 2.2768582153320312e+002 + 1.4745211791992187e+002 2.5657388305664062e+002 + 1.7551440429687500e+002 2.6205712890625000e+002 + 2.1517704772949219e+002 2.6924514770507813e+002 + 2.6574758911132812e+002 2.7777023315429687e+002 + 3.2929153442382812e+002 2.8742639160156250e+002 + 3.9682690429687500e+002 2.9709188842773437e+002 + 1.3995358276367187e+002 3.0524124145507812e+002 + 1.6797488403320312e+002 3.1716934204101562e+002 + 2.0578279113769531e+002 3.2999444580078125e+002 + 2.5654946899414062e+002 3.4458340454101562e+002 + 3.1920385742187500e+002 3.5849545288085937e+002 + 3.8683477783203125e+002 3.6845672607421875e+002 + 1.3802487182617187e+002 3.5235955810546875e+002 + 1.6548860168457031e+002 3.6857592773437500e+002 + 2.0295089721679687e+002 3.8679876708984375e+002 + 2.5176100158691406e+002 4.0528332519531250e+002 + 3.1087322998046875e+002 4.2065597534179687e+002 + 3.7471343994140625e+002 4.3042770385742187e+002 + 1.3998754882812500e+002 3.9499490356445312e+002 + 1.6770181274414062e+002 4.1378182983398437e+002 + 2.0419345092773437e+002 4.3472500610351562e+002 + 2.5042477416992187e+002 4.5404052734375000e+002 + 3.0462469482421875e+002 4.6987689208984375e+002 + 3.6273510742187500e+002 4.7817181396484375e+002 + 1.4533381652832031e+002 4.3124023437500000e+002 + 1.7308050537109375e+002 4.5158215332031250e+002 + 2.0783235168457031e+002 4.7236935424804688e+002 + 2.5115522766113281e+002 4.9075070190429687e+002 + 3.0056707763671875e+002 5.0566351318359375e+002 + 3.5316433715820313e+002 5.1361584472656250e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0094776916503906e+002 1.5520213317871094e+002 + 2.2927296447753906e+002 1.4676406860351562e+002 + 2.6514782714843750e+002 1.3875062561035156e+002 306. 136. + 3.5859338378906250e+002 1.2902023315429687e+002 + 4.1178091430664062e+002 1.3039543151855469e+002 + 1.8951002502441406e+002 1.9153785705566406e+002 + 2.1758355712890625e+002 1.8689489746093750e+002 + 2.5380043029785156e+002 1.8134605407714844e+002 + 3.0032192993164062e+002 1.7711616516113281e+002 + 3.5507934570312500e+002 1.7492227172851562e+002 + 4.1356832885742187e+002 1.7729586791992187e+002 + 1.7871757507324219e+002 2.3342147827148437e+002 + 2.0714880371093750e+002 2.3282965087890625e+002 + 2.4351139831542969e+002 2.3232650756835937e+002 + 2.9124023437500000e+002 2.3226669311523437e+002 + 3.4955126953125000e+002 2.3346505737304688e+002 + 4.1387197875976562e+002 2.3767984008789063e+002 + 1.7077917480468750e+002 2.7852490234375000e+002 + 1.9791098022460937e+002 2.8296087646484375e+002 + 2.3497259521484375e+002 2.8866741943359375e+002 + 2.8316815185546875e+002 2.9471557617187500e+002 + 3.4349993896484375e+002 3.0136962890625000e+002 + 4.0951882934570312e+002 3.0732559204101562e+002 + 1.6631785583496094e+002 3.2478738403320312e+002 + 1.9341018676757812e+002 3.3502212524414062e+002 + 2.2928427124023437e+002 3.4634024047851562e+002 + 2.7764904785156250e+002 3.5854193115234375e+002 + 3.3674786376953125e+002 3.6980120849609375e+002 + 4.0246115112304687e+002 3.7731478881835937e+002 + 1.6525445556640625e+002 3.6841491699218750e+002 + 1.9218322753906250e+002 3.8304812622070312e+002 + 2.2822654724121094e+002 3.9907641601562500e+002 + 2.7443624877929687e+002 4.1554013061523437e+002 + 3.3052944946289062e+002 4.2901165771484375e+002 + 3.9240112304687500e+002 4.3741784667968750e+002 + 1.6825325012207031e+002 4.0852203369140625e+002 + 1.9490322875976562e+002 4.2541351318359375e+002 + 2.2973951721191406e+002 4.4374710083007812e+002 + 2.7355853271484375e+002 4.6136480712890625e+002 + 3.2549746704101562e+002 4.7581845092773437e+002 + 3.8203570556640625e+002 4.8426330566406250e+002 + 1.7330050659179687e+002 4.4212777709960937e+002 + 1.9983802795410156e+002 4.6091326904296875e+002 + 2.3321446228027344e+002 4.7951412963867187e+002 + 2.7426065063476562e+002 4.9707614135742187e+002 + 3.2153433227539062e+002 5.1080972290039062e+002 + 3.7241540527343750e+002 5.1843627929687500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0580984497070312e+002 1.7838311767578125e+002 + 2.3477000427246094e+002 1.6893225097656250e+002 + 2.7068652343750000e+002 1.6039509582519531e+002 311. 153. 364. + 147. 4.1279769897460937e+002 1.4323776245117187e+002 + 1.9564799499511719e+002 2.1538555908203125e+002 + 2.2480979919433594e+002 2.0825555419921875e+002 + 2.6262481689453125e+002 2.0105216979980469e+002 + 3.0835412597656250e+002 1.9513078308105469e+002 + 3.6194509887695312e+002 1.9039396667480469e+002 + 4.1955770874023437e+002 1.8787768554687500e+002 + 1.8649514770507812e+002 2.5679025268554687e+002 + 2.1559808349609375e+002 2.5446284484863281e+002 + 2.5437489318847656e+002 2.5148399353027344e+002 + 3.0341125488281250e+002 2.4896798706054687e+002 + 3.6217300415039063e+002 2.4656753540039062e+002 + 4.2496173095703125e+002 2.4543003845214844e+002 + 1.7989031982421875e+002 3.0258267211914062e+002 + 2.0925387573242187e+002 3.0538726806640625e+002 + 2.4841506958007812e+002 3.0867276000976562e+002 + 2.9902236938476562e+002 3.1153271484375000e+002 + 3.6067025756835937e+002 3.1336633300781250e+002 + 4.2696356201171875e+002 3.1331771850585937e+002 + 1.7644367980957031e+002 3.4888858032226562e+002 + 2.0551130676269531e+002 3.5759530639648438e+002 + 2.4500767517089844e+002 3.6775146484375000e+002 + 2.9587377929687500e+002 3.7651617431640625e+002 + 3.5838177490234375e+002 3.8248324584960937e+002 + 4.2465707397460937e+002 3.8360458374023437e+002 + 1.7651614379882812e+002 3.9366412353515625e+002 + 2.0566857910156250e+002 4.0696102905273438e+002 + 2.4511419677734375e+002 4.2151119995117187e+002 + 2.9453979492187500e+002 4.3516390991210937e+002 + 3.5479321289062500e+002 4.4430819702148437e+002 + 4.1859152221679687e+002 4.4585403442382812e+002 + 1.8052780151367187e+002 4.3394006347656250e+002 + 2.0952693176269531e+002 4.5053137207031250e+002 + 2.4742626953125000e+002 4.6746548461914062e+002 + 2.9528823852539062e+002 4.8251736450195312e+002 + 3.5104156494140625e+002 4.9270755004882812e+002 + 4.0978665161132812e+002 4.9475241088867187e+002 + 1.8633276367187500e+002 4.6837307739257812e+002 + 2.1619882202148437e+002 4.8620230102539062e+002 + 2.5207182312011719e+002 5.0406536865234375e+002 + 2.9689334106445312e+002 5.1883941650390625e+002 + 3.4736700439453125e+002 5.2858032226562500e+002 + 4.0125399780273437e+002 5.3134710693359375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.9815507507324219e+002 1.6423843383789063e+002 + 2.2345178222656250e+002 1.5145697021484375e+002 + 2.5416481018066406e+002 1.3714605712890625e+002 + 2.9131515502929687e+002 1.2267896270751953e+002 + 3.3550964355468750e+002 1.0993415832519531e+002 + 3.8463430786132812e+002 1.0037955474853516e+002 + 1.9415220642089844e+002 1.9962039184570312e+002 + 2.1939964294433594e+002 1.8850418090820313e+002 + 2.5082754516601562e+002 1.7692204284667969e+002 + 2.9051901245117187e+002 1.6404505920410156e+002 + 3.3845693969726562e+002 1.5179626464843750e+002 + 3.9263204956054687e+002 1.4272557067871094e+002 + 1.9113308715820312e+002 2.3883255004882812e+002 + 2.1659776306152344e+002 2.3156063842773437e+002 + 2.4915350341796875e+002 2.2321609497070312e+002 + 2.9077972412109375e+002 2.1453202819824219e+002 + 3.4179827880859375e+002 2.0470581054687500e+002 + 4.0025833129882812e+002 1.9744987487792969e+002 + 1.9110958862304688e+002 2.8065365600585937e+002 + 2.1600064086914062e+002 2.7770767211914062e+002 + 2.4949067687988281e+002 2.7533059692382812e+002 + 2.9210983276367188e+002 2.7081896972656250e+002 + 3.4543890380859375e+002 2.6579534912109375e+002 + 4.0603497314453125e+002 2.6126947021484375e+002 + 1.9302655029296875e+002 3.2284194946289062e+002 + 2.1835688781738281e+002 3.2528573608398437e+002 + 2.5180834960937500e+002 3.2820397949218750e+002 + 2.9546173095703125e+002 3.2942193603515625e+002 + 3.4852200317382812e+002 3.2966033935546875e+002 + 4.0947772216796875e+002 3.2834262084960937e+002 + 1.9796008300781250e+002 3.6352822875976562e+002 + 2.2355749511718750e+002 3.7027194213867187e+002 + 2.5730209350585937e+002 3.7737289428710937e+002 + 2.9989572143554687e+002 3.8360635375976562e+002 + 3.5168725585937500e+002 3.8838006591796875e+002 + 4.0927255249023437e+002 3.8854086303710937e+002 + 2.0478356933593750e+002 4.0049462890625000e+002 + 2.3047744750976562e+002 4.1024148559570312e+002 + 2.6414398193359375e+002 4.2050396728515625e+002 + 3.0480618286132812e+002 4.2941595458984375e+002 + 3.5353713989257812e+002 4.3625952148437500e+002 + 4.0696667480468750e+002 4.3775024414062500e+002 + 2.1323722839355469e+002 4.3246014404296875e+002 + 2.3942247009277344e+002 4.4394601440429687e+002 + 2.7116186523437500e+002 4.5584274291992187e+002 + 3.1005010986328125e+002 4.6585305786132813e+002 + 3.5526126098632812e+002 4.7328820800781250e+002 + 4.0309173583984375e+002 4.7588442993164062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0092871093750000e+002 1.0377958679199219e+002 + 2.2474862670898437e+002 8.6354782104492188e+001 + 2.5482092285156250e+002 6.7415420532226563e+001 + 2.9162356567382812e+002 4.8171840667724609e+001 + 3.3557312011718750e+002 3.1562601089477539e+001 + 3.8464041137695312e+002 2.0024744033813477e+001 + 2.0153320312500000e+002 1.3662707519531250e+002 + 2.2634468078613281e+002 1.2020697784423828e+002 + 2.5733035278320312e+002 1.0334932708740234e+002 + 2.9626211547851562e+002 8.5413459777832031e+001 + 3.4325189208984375e+002 6.9041717529296875e+001 + 3.9640975952148437e+002 5.7673271179199219e+001 + 2.0466014099121094e+002 1.7303405761718750e+002 + 2.2948304748535156e+002 1.5986682128906250e+002 + 2.6153091430664062e+002 1.4546781921386719e+002 + 3.0199740600585937e+002 1.3090780639648437e+002 + 3.5199911499023437e+002 1.1654225158691406e+002 + 4.0823077392578125e+002 1.0705214691162109e+002 + 2.0964459228515625e+002 2.1166081237792969e+002 + 2.3482260131835937e+002 2.0295175170898437e+002 + 2.6768417358398437e+002 1.9310482788085937e+002 + 3.0943469238281250e+002 1.8244853210449219e+002 + 3.6055001831054687e+002 1.7267668151855469e+002 + 4.1826669311523437e+002 1.6556668090820312e+002 + 2.1632197570800781e+002 2.5077903747558594e+002 + 2.4245878601074219e+002 2.4695518493652344e+002 + 2.7515753173828125e+002 2.4252929687500000e+002 + 3.1738644409179687e+002 2.3703398132324219e+002 + 3.6770040893554687e+002 2.3248031616210937e+002 + 4.2494616699218750e+002 2.2851121520996094e+002 + 2.2536701965332031e+002 2.8965997314453125e+002 + 2.5082624816894531e+002 2.8979281616210937e+002 + 2.8397045898437500e+002 2.8979437255859375e+002 + 3.2491036987304687e+002 2.8961846923828125e+002 + 3.7368719482421875e+002 2.8868893432617187e+002 + 4.2746572875976562e+002 2.8757067871093750e+002 + 2.3508308410644531e+002 3.2448403930664062e+002 + 2.6149685668945312e+002 3.2849328613281250e+002 + 2.9325088500976562e+002 3.3193228149414062e+002 + 3.3275418090820312e+002 3.3545498657226562e+002 + 3.7784451293945313e+002 3.3770251464843750e+002 + 4.2729452514648437e+002 3.3815295410156250e+002 + 2.4596897888183594e+002 3.5555557250976562e+002 + 2.7094876098632812e+002 3.6192028808593750e+002 + 3.0210317993164062e+002 3.6773251342773437e+002 + 3.3916925048828125e+002 3.7265963745117187e+002 + 3.8098541259765625e+002 3.7675711059570312e+002 + 4.2503427124023437e+002 3.7869274902343750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0025698852539062e+002 7.4481903076171875e+001 + 2.2713739013671875e+002 6.0857147216796875e+001 + 2.6073492431640625e+002 4.6749332427978516e+001 + 3.0134194946289062e+002 3.4238628387451172e+001 + 3.4830911254882812e+002 2.5837272644042969e+001 + 3.9930282592773437e+002 2.3502777099609375e+001 + 2.0025488281250000e+002 1.0795819091796875e+002 + 2.2723373413085937e+002 9.5765197753906250e+001 + 2.6098336791992187e+002 8.4439170837402344e+001 + 3.0250903320312500e+002 7.3652557373046875e+001 + 3.5073577880859375e+002 6.6836021423339844e+001 + 4.0359896850585937e+002 6.5513343811035156e+001 + 2.0175141906738281e+002 1.4391958618164062e+002 + 2.2894094848632812e+002 1.3610682678222656e+002 + 2.6308697509765625e+002 1.2719033813476562e+002 + 3.0475476074218750e+002 1.1946985626220703e+002 + 3.5337042236328125e+002 1.1458718872070312e+002 + 4.0704653930664062e+002 1.1459195709228516e+002 + 2.0583883666992187e+002 1.8191976928710937e+002 + 2.3256207275390625e+002 1.7722724914550781e+002 + 2.6651165771484375e+002 1.7240469360351562e+002 + 3.0715283203125000e+002 1.6838438415527344e+002 + 3.5546420288085937e+002 1.6694664001464844e+002 + 4.0733578491210937e+002 1.6864717102050781e+002 + 2.1126727294921875e+002 2.1943159484863281e+002 + 2.3757279968261719e+002 2.1776844787597656e+002 + 2.7105972290039062e+002 2.1730943298339844e+002 + 3.1035540771484375e+002 2.1707366943359375e+002 + 3.5655310058593750e+002 2.1781103515625000e+002 + 4.0580691528320312e+002 2.2150975036621094e+002 + 2.1803051757812500e+002 2.5503312683105469e+002 + 2.4367300415039062e+002 2.5653890991210937e+002 + 2.7642483520507812e+002 2.5869323730468750e+002 + 3.1364422607421875e+002 2.6151257324218750e+002 + 3.5641323852539062e+002 2.6482922363281250e+002 + 4.0264666748046875e+002 2.6945254516601562e+002 + 2.2563090515136719e+002 2.8647561645507812e+002 + 2.5169604492187500e+002 2.9095141601562500e+002 + 2.8238931274414062e+002 2.9576651000976562e+002 + 3.1714852905273438e+002 3.0006134033203125e+002 + 3.5656808471679687e+002 3.0526385498046875e+002 + 3.9801971435546875e+002 3.0888510131835937e+002 + 2.3467616271972656e+002 3.1444165039062500e+002 + 2.5874783325195312e+002 3.1993524169921875e+002 + 2.8763424682617187e+002 3.2671337890625000e+002 + 3.2038699340820312e+002 3.3180047607421875e+002 + 3.5654403686523437e+002 3.3801803588867187e+002 + 3.9458895874023437e+002 3.4170211791992187e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 209. 94. 237. 8.4500000000000000e+001 2.7869885253906250e+002 + 7.1452575683593750e+001 3.2985308837890625e+002 + 6.4404342651367188e+001 3.9026391601562500e+002 + 6.4313690185546875e+001 4.5564553833007812e+002 + 7.4115409851074219e+001 1.9240014648437500e+002 + 1.3146128845214844e+002 2.2152857971191406e+002 + 1.2412722015380859e+002 2.6107165527343750e+002 + 1.1679236602783203e+002 3.1474127197265625e+002 + 1.1228987884521484e+002 3.8160763549804687e+002 + 1.1466155242919922e+002 4.5537835693359375e+002 + 1.2778687286376953e+002 1.7851136779785156e+002 + 1.7571856689453125e+002 2.0593481445312500e+002 + 1.7481787109375000e+002 2.4446177673339844e+002 + 1.7452168273925781e+002 2.9847854614257813e+002 + 1.7626876831054687e+002 3.6933599853515625e+002 + 1.8418939208984375e+002 4.4851232910156250e+002 + 2.0059803771972656e+002 1.6813301086425781e+002 + 2.2595860290527344e+002 1.9356489562988281e+002 + 2.3096928405761719e+002 2.3033898925781250e+002 + 2.3938458251953125e+002 2.8245379638671875e+002 + 2.5154878234863281e+002 3.5294836425781250e+002 + 2.6750909423828125e+002 4.3350439453125000e+002 + 2.8749230957031250e+002 1.6199024963378906e+002 + 2.7492788696289062e+002 1.8659698486328125e+002 + 2.8798431396484375e+002 2.2144160461425781e+002 + 3.0439141845703125e+002 2.7108267211914062e+002 + 3.2502883911132812e+002 3.3653512573242187e+002 + 3.4774526977539062e+002 4.1160449218750000e+002 + 3.6883505249023437e+002 1.6004812622070312e+002 + 3.2117752075195312e+002 1.8445892333984375e+002 + 3.3945504760742187e+002 2.1790031433105469e+002 + 3.6135156250000000e+002 2.6416613769531250e+002 + 3.8630041503906250e+002 3.2300485229492187e+002 + 4.1136682128906250e+002 3.8928665161132812e+002 + 4.3168502807617187e+002 1.6238012695312500e+002 + 3.6205575561523437e+002 1.8654824829101562e+002 + 3.8293630981445312e+002 2.1860414123535156e+002 + 4.0704595947265625e+002 2.6074517822265625e+002 + 4.3259201049804687e+002 3.1264321899414062e+002 + 4.5639926147460937e+002 3.6993167114257812e+002 + 4.7478726196289062e+002 1.6666227722167969e+002 + 3.9642849731445312e+002 1.9054829406738281e+002 + 4.1812844848632812e+002 2.2095324707031250e+002 + 4.4227026367187500e+002 2.5979873657226562e+002 + 4.6570358276367187e+002 3.0546740722656250e+002 + 4.8771459960937500e+002 3.5504550170898437e+002 + 5.0443521118164062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7552990722656250e+002 4.8742698669433594e+001 + 3.0839810180664062e+002 4.3907390594482422e+001 + 3.4867681884765625e+002 4.0898658752441406e+001 + 3.9549978637695312e+002 4.2764762878417969e+001 + 4.4660995483398438e+002 5.1583938598632813e+001 + 4.9825683593750000e+002 6.7932968139648438e+001 + 2.6059579467773437e+002 8.0898262023925781e+001 + 2.9349530029296875e+002 7.7010871887207031e+001 + 3.3452560424804687e+002 7.6218338012695312e+001 + 3.8459930419921875e+002 7.9198173522949219e+001 + 4.3947558593750000e+002 9.0078140258789063e+001 + 4.9592706298828125e+002 1.0917436981201172e+002 + 2.4567597961425781e+002 1.1848165893554687e+002 + 2.7813049316406250e+002 1.1722573089599609e+002 + 3.1869805908203125e+002 1.1984860992431641e+002 + 3.6915188598632812e+002 1.2681442260742187e+002 + 4.2783880615234375e+002 1.4042300415039062e+002 + 4.8787265014648437e+002 1.6223577880859375e+002 + 2.3211035156250000e+002 1.5986766052246094e+002 + 2.6287103271484375e+002 1.6360116577148437e+002 + 3.0201229858398437e+002 1.7164840698242187e+002 + 3.5269995117187500e+002 1.8365737915039062e+002 + 4.1181872558593750e+002 2.0153279113769531e+002 + 4.7296923828125000e+002 2.2555763244628906e+002 + 2.2023696899414062e+002 2.0432968139648437e+002 + 2.4883340454101562e+002 2.1370413208007812e+002 + 2.8599746704101562e+002 2.2699273681640625e+002 + 3.3455953979492187e+002 2.4499926757812500e+002 + 3.9203958129882813e+002 2.6677920532226562e+002 + 4.5135910034179687e+002 2.9159295654296875e+002 + 2.1184986877441406e+002 2.4768948364257812e+002 + 2.3867210388183594e+002 2.6266918945312500e+002 + 2.7356823730468750e+002 2.8103027343750000e+002 + 3.1795706176757812e+002 3.0272323608398437e+002 + 3.7056710815429687e+002 3.2752661132812500e+002 + 4.2558917236328125e+002 3.5168923950195313e+002 + 2.0747038269042969e+002 2.8829434204101562e+002 + 2.3188685607910156e+002 3.0623175048828125e+002 + 2.6438946533203125e+002 3.2815356445312500e+002 + 3.0438259887695312e+002 3.5163369750976562e+002 + 3.5145092773437500e+002 3.7663403320312500e+002 + 4.0170214843750000e+002 3.9946182250976562e+002 + 2.0488038635253906e+002 3.2424810791015625e+002 + 2.2841096496582031e+002 3.4429318237304687e+002 + 2.5794210815429687e+002 3.6701071166992187e+002 + 2.9471945190429687e+002 3.9087506103515625e+002 + 3.3590274047851562e+002 4.1388223266601562e+002 + 3.8063262939453125e+002 4.3526235961914062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7360159301757813e+002 2.5205781936645508e+001 + 3.1096432495117187e+002 2.4628013610839844e+001 + 3.5506146240234375e+002 2.8339456558227539e+001 + 4.0408776855468750e+002 3.8499496459960938e+001 + 4.5434750366210937e+002 5.6449882507324219e+001 + 5.0203967285156250e+002 8.2020179748535156e+001 + 2.5537905883789062e+002 5.7798183441162109e+001 + 2.9243359375000000e+002 5.8553703308105469e+001 + 3.3764141845703125e+002 6.3639980316162109e+001 + 3.8852719116210937e+002 7.5763885498046875e+001 + 4.4266448974609375e+002 9.6240051269531250e+001 + 4.9334124755859375e+002 1.2243223571777344e+002 + 2.3788639831542969e+002 9.6370223999023437e+001 + 2.7370098876953125e+002 9.9898498535156250e+001 + 3.1868905639648437e+002 1.0820242309570312e+002 + 3.7051956176757812e+002 1.2235251617431641e+002 + 4.2654211425781250e+002 1.4441143798828125e+002 + 4.7923367309570312e+002 1.7202281188964844e+002 + 2.2099580383300781e+002 1.3947836303710937e+002 + 2.5599291992187500e+002 1.4716134643554687e+002 + 2.9898065185546875e+002 1.5976675415039063e+002 + 3.5055480957031250e+002 1.7709461975097656e+002 + 4.0613998413085937e+002 2.0034272766113281e+002 + 4.5945010375976562e+002 2.2706454467773437e+002 + 2.0809417724609375e+002 1.8530169677734375e+002 + 2.4031069946289062e+002 1.9775102233886719e+002 + 2.8047061157226563e+002 2.1392324829101562e+002 + 3.2991244506835937e+002 2.3423036193847656e+002 + 3.8320614624023437e+002 2.5822204589843750e+002 + 4.3479733276367187e+002 2.8298712158203125e+002 + 1.9920870971679687e+002 2.3027775573730469e+002 + 2.2869706726074219e+002 2.4599017333984375e+002 + 2.6626159667968750e+002 2.6510134887695312e+002 + 3.1198962402343750e+002 2.8800830078125000e+002 + 3.6141448974609375e+002 3.1073638916015625e+002 + 4.1016244506835937e+002 3.3283432006835937e+002 + 1.9305104064941406e+002 2.7100195312500000e+002 + 2.2130241394042969e+002 2.8914462280273437e+002 + 2.5582427978515625e+002 3.1009783935546875e+002 + 2.9733026123046875e+002 3.3241830444335937e+002 + 3.4235430908203125e+002 3.5402804565429687e+002 + 3.8653521728515625e+002 3.7382531738281250e+002 + 1.9078620910644531e+002 3.0617114257812500e+002 + 2.1703494262695312e+002 3.2551022338867187e+002 + 2.4875410461425781e+002 3.4688653564453125e+002 + 2.8603329467773438e+002 3.6834136962890625e+002 + 3.2637124633789062e+002 3.8830209350585937e+002 + 3.6686145019531250e+002 4.0562457275390625e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.7001583862304687e+002 5.7182895660400391e+001 + 2.1108045959472656e+002 4.7799243927001953e+001 + 2.5956008911132812e+002 4.3719604492187500e+001 + 3.1143792724609375e+002 4.6172756195068359e+001 + 3.6333203125000000e+002 5.5096183776855469e+001 + 4.0965356445312500e+002 6.9549232482910156e+001 + 1.6503564453125000e+002 1.0154321289062500e+002 + 2.0445137023925781e+002 9.4304229736328125e+001 + 2.5156283569335938e+002 9.1287895202636719e+001 + 3.0265682983398438e+002 9.3232055664062500e+001 + 3.5326828002929687e+002 1.0106951904296875e+002 + 3.9997918701171875e+002 1.1306182098388672e+002 + 1.6425099182128906e+002 1.4689244079589844e+002 + 2.0249627685546875e+002 1.4248432922363281e+002 + 2.4730621337890625e+002 1.4117642211914062e+002 + 2.9582864379882813e+002 1.4342593383789063e+002 + 3.4432342529296875e+002 1.4872006225585937e+002 + 3.8843289184570312e+002 1.5726179504394531e+002 + 1.6663575744628906e+002 1.9060403442382812e+002 + 2.0346289062500000e+002 1.8878169250488281e+002 + 2.4531300354003906e+002 1.8823811340332031e+002 + 2.9017977905273437e+002 1.9024853515625000e+002 + 3.3558779907226562e+002 1.9370622253417969e+002 + 3.7750982666015625e+002 1.9969061279296875e+002 + 1.7187074279785156e+002 2.3000723266601562e+002 + 2.0641810607910156e+002 2.2977960205078125e+002 + 2.4541024780273437e+002 2.3103010559082031e+002 + 2.8675823974609375e+002 2.3248098754882812e+002 + 3.2815093994140625e+002 2.3474520874023437e+002 + 3.6774411010742188e+002 2.3826007080078125e+002 + 1.7917341613769531e+002 2.6455392456054687e+002 + 2.1136041259765625e+002 2.6571255493164062e+002 + 2.4708076477050781e+002 2.6685156250000000e+002 + 2.8435787963867187e+002 2.6834265136718750e+002 + 3.2259283447265625e+002 2.6944644165039062e+002 + 3.5872302246093750e+002 2.7110305786132812e+002 + 1.8649298095703125e+002 2.9337048339843750e+002 + 2.1665324401855469e+002 2.9526562500000000e+002 + 2.4945761108398437e+002 2.9697543334960937e+002 + 2.8342358398437500e+002 2.9839685058593750e+002 + 3.1846646118164062e+002 2.9897912597656250e+002 + 3.5103195190429687e+002 2.9938061523437500e+002 + 1.9418367004394531e+002 3.1663012695312500e+002 + 2.2180123901367187e+002 3.1953906250000000e+002 + 2.5181367492675781e+002 3.2111636352539062e+002 + 2.8307571411132812e+002 3.2224307250976562e+002 + 3.1434524536132812e+002 3.2236422729492187e+002 + 3.4445501708984375e+002 3.2204623413085937e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.3594654846191406e+002 1.0054103088378906e+002 + 1.7601734924316406e+002 8.2119407653808594e+001 + 2.2607170104980469e+002 6.7323181152343750e+001 + 2.8345169067382812e+002 5.8504489898681641e+001 + 3.4250555419921875e+002 5.8322742462158203e+001 + 3.9747656250000000e+002 6.5511375427246094e+001 + 1.3734251403808594e+002 1.4873536682128906e+002 + 1.7626100158691406e+002 1.3432502746582031e+002 + 2.2558230590820312e+002 1.2163390350341797e+002 + 2.8228369140625000e+002 1.1337725067138672e+002 + 3.4118841552734375e+002 1.1247806549072266e+002 + 3.9575750732421875e+002 1.1727284240722656e+002 + 1.4380694580078125e+002 1.9781712341308594e+002 + 1.8194888305664062e+002 1.8773309326171875e+002 + 2.2927095031738281e+002 1.7842025756835937e+002 + 2.8337817382812500e+002 1.7212915039062500e+002 + 3.3992144775390625e+002 1.6898034667968750e+002 + 3.9223742675781250e+002 1.7007241821289062e+002 + 1.5451528930664062e+002 2.4533543395996094e+002 + 1.9112248229980469e+002 2.3883230590820313e+002 + 2.3631869506835937e+002 2.3245520019531250e+002 + 2.8659225463867187e+002 2.2709069824218750e+002 + 3.3846520996093750e+002 2.2318006896972656e+002 + 3.8712377929687500e+002 2.2137194824218750e+002 + 1.6700929260253906e+002 2.8648928833007812e+002 + 2.0256639099121094e+002 2.8263684082031250e+002 + 2.4501641845703125e+002 2.7933819580078125e+002 + 2.9098217773437500e+002 2.7435324096679687e+002 + 3.3786062622070313e+002 2.7063244628906250e+002 + 3.8241333007812500e+002 2.6576730346679687e+002 + 1.8161585998535156e+002 3.2141937255859375e+002 + 2.1490039062500000e+002 3.1959436035156250e+002 + 2.5362635803222656e+002 3.1755740356445312e+002 + 2.9475396728515625e+002 3.1372708129882813e+002 + 3.3726959228515625e+002 3.0918765258789063e+002 + 3.7767855834960937e+002 3.0398196411132812e+002 + 1.9459613037109375e+002 3.4955651855468750e+002 + 2.2623347473144531e+002 3.4876431274414062e+002 + 2.6128665161132812e+002 3.4730236816406250e+002 + 2.9904144287109375e+002 3.4362268066406250e+002 + 3.3668518066406250e+002 3.3919522094726562e+002 + 3.7344659423828125e+002 3.3425466918945312e+002 + 2.0652621459960937e+002 3.7195111083984375e+002 + 2.3638980102539062e+002 3.7230123901367187e+002 + 2.6852398681640625e+002 3.7135952758789063e+002 + 3.0218490600585937e+002 3.6767279052734375e+002 + 3.3635467529296875e+002 3.6386495971679687e+002 + 3.6889657592773437e+002 3.5823019409179687e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.6417164611816406e+002 7.6351463317871094e+001 + 2.0617816162109375e+002 6.8905738830566406e+001 + 2.5405767822265625e+002 6.6496276855468750e+001 + 3.0486709594726562e+002 7.0331047058105469e+001 + 3.5289373779296875e+002 7.8850540161132813e+001 + 3.9688143920898437e+002 9.2615310668945313e+001 + 1.5293682861328125e+002 1.2063140869140625e+002 + 1.9504454040527344e+002 1.1467189788818359e+002 + 2.4435140991210937e+002 1.1253511047363281e+002 + 2.9682214355468750e+002 1.1568982696533203e+002 + 3.4785159301757812e+002 1.2370596313476562e+002 + 3.9351245117187500e+002 1.3498025512695312e+002 + 1.4497479248046875e+002 1.7174838256835937e+002 + 1.8763226318359375e+002 1.6751916503906250e+002 + 2.3718200683593750e+002 1.6644885253906250e+002 + 2.9009448242187500e+002 1.6871429443359375e+002 + 3.4216040039062500e+002 1.7455743408203125e+002 + 3.8795556640625000e+002 1.8259931945800781e+002 + 1.4345043945312500e+002 2.2542236328125000e+002 + 1.8440023803710937e+002 2.2372932434082031e+002 + 2.3266679382324219e+002 2.2365432739257812e+002 + 2.8541030883789062e+002 2.2498530578613281e+002 + 3.3623608398437500e+002 2.2794012451171875e+002 + 3.8187667846679687e+002 2.3240528869628906e+002 + 1.4627874755859375e+002 2.7664584350585937e+002 + 1.8612446594238281e+002 2.7747045898437500e+002 + 2.3249781799316406e+002 2.7878125000000000e+002 + 2.8236730957031250e+002 2.7896490478515625e+002 + 3.3155261230468750e+002 2.7934204101562500e+002 + 3.7505349731445312e+002 2.8044149780273437e+002 + 1.5365731811523438e+002 3.2274075317382812e+002 + 1.9179774475097656e+002 3.2564263916015625e+002 + 2.3526158142089844e+002 3.2681088256835937e+002 + 2.8113098144531250e+002 3.2703042602539062e+002 + 3.2720913696289062e+002 3.2454263305664062e+002 + 3.6807266235351562e+002 3.2248974609375000e+002 + 1.6368103027343750e+002 3.6155044555664062e+002 + 1.9937178039550781e+002 3.6488137817382812e+002 + 2.3938957214355469e+002 3.6662371826171875e+002 + 2.8219235229492187e+002 3.6546664428710937e+002 + 3.2339410400390625e+002 3.6277227783203125e+002 + 3.6166659545898437e+002 3.5951364135742187e+002 + 1.7365939331054687e+002 3.9286773681640625e+002 + 2.0749069213867187e+002 3.9650820922851562e+002 + 2.4434919738769531e+002 3.9824865722656250e+002 + 2.8271774291992187e+002 3.9685394287109375e+002 + 3.2045401000976562e+002 3.9439822387695312e+002 + 3.5505792236328125e+002 3.8922320556640625e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.8836120605468750e+002 5.9227943420410156e+001 + 2.2921588134765625e+002 5.1671657562255859e+001 + 2.7570205688476562e+002 4.7925788879394531e+001 + 3.2269845581054687e+002 4.9867816925048828e+001 + 3.6889819335937500e+002 5.6886310577392578e+001 + 4.1040322875976562e+002 6.8506301879882813e+001 + 1.7652212524414062e+002 9.7684593200683594e+001 + 2.1958569335937500e+002 8.9533660888671875e+001 + 2.6858685302734375e+002 8.6037582397460938e+001 + 3.1922488403320312e+002 8.7850990295410156e+001 + 3.6905123901367187e+002 9.4673988342285156e+001 + 4.1246643066406250e+002 1.0535327148437500e+002 + 1.6762762451171875e+002 1.4386169433593750e+002 + 2.1099221801757813e+002 1.3730455017089844e+002 + 2.6209143066406250e+002 1.3372830200195312e+002 + 3.1578701782226562e+002 1.3495137023925781e+002 + 3.6761190795898437e+002 1.4010426330566406e+002 + 4.1270675659179687e+002 1.4933305358886719e+002 + 1.6281869506835937e+002 1.9564372253417969e+002 + 2.0676971435546875e+002 1.9111604309082031e+002 + 2.5831259155273437e+002 1.8851136779785156e+002 + 3.1266168212890625e+002 1.8908554077148437e+002 + 3.6540142822265625e+002 1.9266377258300781e+002 + 4.1152709960937500e+002 1.9800389099121094e+002 + 1.6310388183593750e+002 2.5011343383789063e+002 + 2.0611062622070312e+002 2.4772575378417969e+002 + 2.5692697143554687e+002 2.4670475769042969e+002 + 3.1107287597656250e+002 2.4667152404785156e+002 + 3.6316622924804687e+002 2.4771394348144531e+002 + 4.0829925537109375e+002 2.4905491638183594e+002 + 1.6845463562011719e+002 3.0180444335937500e+002 + 2.1033898925781250e+002 3.0264935302734375e+002 + 2.5854293823242187e+002 3.0296658325195312e+002 + 3.1022576904296875e+002 3.0178704833984375e+002 + 3.5967010498046875e+002 2.9986700439453125e+002 + 4.0351028442382812e+002 2.9841363525390625e+002 + 1.7672894287109375e+002 3.4747134399414062e+002 + 2.1687564086914062e+002 3.4988427734375000e+002 + 2.6214953613281250e+002 3.5090914916992187e+002 + 3.1021151733398437e+002 3.4974960327148437e+002 + 3.5641461181640625e+002 3.4637667846679688e+002 + 3.9772714233398437e+002 3.4138320922851562e+002 + 1.8744743347167969e+002 3.8571844482421875e+002 + 2.2485710144042969e+002 3.8926107788085937e+002 + 2.6670828247070312e+002 3.9061557006835937e+002 + 3.1027178955078125e+002 3.8870050048828125e+002 + 3.5305053710937500e+002 3.8474472045898437e+002 + 3.9142144775390625e+002 3.7876580810546875e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.8235786437988281e+002 1.7880033874511719e+002 + 2.1361668395996094e+002 1.6641311645507812e+002 + 2.4956755065917969e+002 1.5441252136230469e+002 + 2.9016558837890625e+002 1.4383676147460937e+002 + 3.3160989379882812e+002 1.3639218139648437e+002 + 3.7293298339843750e+002 1.3152859497070312e+002 + 1.8996148681640625e+002 2.1656478881835937e+002 + 2.2119946289062500e+002 2.0563630676269531e+002 + 2.5674810791015625e+002 1.9549073791503906e+002 + 2.9689675903320312e+002 1.8598820495605469e+002 + 3.3794998168945312e+002 1.7846524047851562e+002 + 3.7830578613281250e+002 1.7256184387207031e+002 + 1.9928634643554687e+002 2.5334864807128906e+002 + 2.2972135925292969e+002 2.4526300048828125e+002 + 2.6497476196289062e+002 2.3668713378906250e+002 + 3.0418432617187500e+002 2.2884085083007812e+002 + 3.4435336303710937e+002 2.2046250915527344e+002 + 3.8339187622070312e+002 2.1432641601562500e+002 + 2.0951829528808594e+002 2.8849841308593750e+002 + 2.4047460937500000e+002 2.8189776611328125e+002 + 2.7451226806640625e+002 2.7544415283203125e+002 + 3.1137908935546875e+002 2.6814096069335937e+002 + 3.4966198730468750e+002 2.6075079345703125e+002 + 3.8664935302734375e+002 2.5386822509765625e+002 + 2.2105107116699219e+002 3.2052920532226562e+002 + 2.5091227722167969e+002 3.1661453247070312e+002 + 2.8299035644531250e+002 3.1033526611328125e+002 + 3.1870153808593750e+002 3.0436773681640625e+002 + 3.5427566528320313e+002 2.9692114257812500e+002 + 3.8907284545898437e+002 2.8996481323242187e+002 + 2.3266865539550781e+002 3.4863619995117187e+002 + 2.6120645141601562e+002 3.4517651367187500e+002 + 2.9201492309570312e+002 3.4057711791992187e+002 + 3.2499108886718750e+002 3.3480883789062500e+002 + 3.5870913696289062e+002 3.2829534912109375e+002 + 3.9099023437500000e+002 3.2115478515625000e+002 + 2.4351995849609375e+002 3.7265509033203125e+002 + 2.7046218872070312e+002 3.7034622192382812e+002 + 3.0001135253906250e+002 3.6665893554687500e+002 + 3.3082830810546875e+002 3.6131164550781250e+002 + 3.6160327148437500e+002 3.5465127563476562e+002 + 3.9207946777343750e+002 3.4795779418945312e+002 + 2.5384948730468750e+002 3.9303674316406250e+002 + 2.7959381103515625e+002 3.9075363159179687e+002 + 3.0708459472656250e+002 3.8846423339843750e+002 + 3.3558914184570312e+002 3.8340951538085937e+002 + 3.6441833496093750e+002 3.7753869628906250e+002 + 3.9243655395507812e+002 3.7034323120117187e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.3650102233886719e+002 1.6150401306152344e+002 + 1.6361271667480469e+002 1.3913356018066406e+002 + 1.9439115905761719e+002 1.1695137023925781e+002 + 2.2962243652343750e+002 9.6321166992187500e+001 + 2.6678042602539062e+002 7.9305412292480469e+001 + 3.0408853149414062e+002 6.5989540100097656e+001 + 1.4994486999511719e+002 1.9293312072753906e+002 + 1.7678016662597656e+002 1.7155081176757813e+002 + 2.0848612976074219e+002 1.5041423034667969e+002 + 2.4248576354980469e+002 1.3092166137695312e+002 + 2.7916464233398437e+002 1.1378553771972656e+002 + 3.1646112060546875e+002 9.9707344055175781e+001 + 1.6601750183105469e+002 2.2373587036132812e+002 + 1.9265223693847656e+002 2.0440525817871094e+002 + 2.2309980773925781e+002 1.8471961975097656e+002 + 2.5687469482421875e+002 1.6639863586425781e+002 + 2.9278622436523437e+002 1.4906803894042969e+002 + 3.2823440551757812e+002 1.3492875671386719e+002 + 1.8281675720214844e+002 2.5425236511230469e+002 + 2.0925675964355469e+002 2.3739176940917969e+002 + 2.3945889282226562e+002 2.1899415588378906e+002 + 2.7244430541992187e+002 2.0157722473144531e+002 + 3.0632672119140625e+002 1.8492550659179687e+002 + 3.3992739868164062e+002 1.7044166564941406e+002 + 2.0053552246093750e+002 2.8225732421875000e+002 + 2.2649098205566406e+002 2.6706814575195312e+002 + 2.5561010742187500e+002 2.5086483764648437e+002 + 2.8715203857421875e+002 2.3417439270019531e+002 + 3.1861972045898437e+002 2.1842491149902344e+002 + 3.5003237915039062e+002 2.0402880859375000e+002 + 2.1843518066406250e+002 3.0744509887695312e+002 + 2.4332847595214844e+002 2.9392697143554687e+002 + 2.7132876586914062e+002 2.7931591796875000e+002 + 3.0052911376953125e+002 2.6404708862304688e+002 + 3.2970413208007812e+002 2.4848629760742187e+002 + 3.5952856445312500e+002 2.3432980346679687e+002 + 2.3440406799316406e+002 3.2951281738281250e+002 + 2.5883688354492187e+002 3.1705703735351562e+002 + 2.8520626831054687e+002 3.0367672729492187e+002 + 3.1247360229492187e+002 2.8976339721679687e+002 + 3.3995822143554687e+002 2.7612875366210937e+002 + 3.6736294555664062e+002 2.6163821411132812e+002 + 2.4953947448730469e+002 3.4802947998046875e+002 + 2.7272106933593750e+002 3.3727890014648437e+002 + 2.9738583374023437e+002 3.2533169555664062e+002 + 3.2329251098632812e+002 3.1192181396484375e+002 + 3.4920220947265625e+002 2.9886911010742187e+002 + 3.7349841308593750e+002 2.8567309570312500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.7246737670898437e+002 5.3653038024902344e+001 + 3.0442034912109375e+002 4.3793937683105469e+001 + 3.4101300048828125e+002 3.5418807983398437e+001 + 3.8237911987304687e+002 3.1318746566772461e+001 + 4.2619897460937500e+002 3.1460136413574219e+001 + 4.7039819335937500e+002 3.6716648101806641e+001 + 2.7421270751953125e+002 8.5632064819335937e+001 + 3.0577465820312500e+002 7.7399765014648437e+001 + 3.4341287231445312e+002 7.1538558959960937e+001 + 3.8560937500000000e+002 6.7949203491210937e+001 + 4.3002014160156250e+002 6.9198341369628906e+001 + 4.7462344360351562e+002 7.5745376586914063e+001 + 2.7649215698242187e+002 1.1980583190917969e+002 + 3.0834301757812500e+002 1.1457288360595703e+002 + 3.4525357055664062e+002 1.1111225128173828e+002 + 3.8717294311523437e+002 1.0990641784667969e+002 + 4.3176901245117187e+002 1.1234471130371094e+002 + 4.7603256225585937e+002 1.1951204681396484e+002 + 2.7857174682617188e+002 1.5659533691406250e+002 + 3.1030734252929687e+002 1.5364202880859375e+002 + 3.4706219482421875e+002 1.5271664428710937e+002 + 3.8783917236328125e+002 1.5365629577636719e+002 + 4.3125213623046875e+002 1.5779220581054687e+002 + 4.7449645996093750e+002 1.6455572509765625e+002 + 2.8221801757812500e+002 1.9169747924804687e+002 + 3.1272286987304687e+002 1.9258717346191406e+002 + 3.4847961425781250e+002 1.9379718017578125e+002 + 3.8772775268554687e+002 1.9728660583496094e+002 + 4.2862026977539062e+002 2.0240084838867187e+002 + 4.6967691040039062e+002 2.0890147399902344e+002 + 2.8662442016601562e+002 2.2634190368652344e+002 + 3.1592196655273438e+002 2.2866772460937500e+002 + 3.4961145019531250e+002 2.3235057067871094e+002 + 3.8604464721679687e+002 2.3684603881835937e+002 + 4.2498440551757812e+002 2.4263674926757812e+002 + 4.6317929077148437e+002 2.4948016357421875e+002 + 2.9129718017578125e+002 2.5683203125000000e+002 + 3.1848452758789063e+002 2.6122930908203125e+002 + 3.4988241577148437e+002 2.6711712646484375e+002 + 3.8462948608398437e+002 2.7286602783203125e+002 + 4.1992892456054687e+002 2.7896176147460938e+002 + 4.5545147705078125e+002 2.8503793334960937e+002 + 2.9486087036132812e+002 2.8366900634765625e+002 + 3.2130773925781250e+002 2.8987866210937500e+002 + 3.5075036621093750e+002 2.9671929931640625e+002 + 3.8244757080078125e+002 3.0297216796875000e+002 + 4.1479821777343750e+002 3.0869885253906250e+002 + 4.4767315673828125e+002 3.1495336914062500e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.7837840270996094e+002 1.6745861816406250e+002 + 2.0926123046875000e+002 1.7041326904296875e+002 + 2.4644110107421875e+002 1.7488302612304687e+002 + 2.8847763061523437e+002 1.8244380187988281e+002 + 3.3407507324218750e+002 1.9193455505371094e+002 + 3.8030270385742187e+002 2.0446931457519531e+002 + 1.6455059814453125e+002 2.0729643249511719e+002 + 1.9503150939941406e+002 2.1276541137695312e+002 + 2.3217729187011719e+002 2.1957310485839844e+002 + 2.7610284423828125e+002 2.2854319763183594e+002 + 3.2377459716796875e+002 2.4028013610839844e+002 + 3.7154690551757813e+002 2.5179435729980469e+002 + 1.5296398925781250e+002 2.4994779968261719e+002 + 1.8324339294433594e+002 2.5875592041015625e+002 + 2.2010264587402344e+002 2.6914123535156250e+002 + 2.6437817382812500e+002 2.8042059326171875e+002 + 3.1260052490234375e+002 2.9232684326171875e+002 + 3.6204986572265625e+002 3.0311856079101562e+002 + 1.4427069091796875e+002 2.9376708984375000e+002 + 1.7419172668457031e+002 3.0545059204101562e+002 + 2.1116181945800781e+002 3.1866696166992187e+002 + 2.5433355712890625e+002 3.3198526000976563e+002 + 3.0230813598632812e+002 3.4397827148437500e+002 + 3.5122027587890625e+002 3.5411901855468750e+002 + 1.4001318359375000e+002 3.3598278808593750e+002 + 1.6932873535156250e+002 3.5043267822265625e+002 + 2.0514967346191406e+002 3.6536663818359375e+002 + 2.4717855834960937e+002 3.7960797119140625e+002 + 2.9344906616210937e+002 3.9183865356445312e+002 + 3.4093356323242187e+002 4.0050747680664062e+002 + 1.3933982849121094e+002 3.7467224121093750e+002 + 1.6769392395019531e+002 3.9091720581054687e+002 + 2.0256588745117187e+002 4.0695544433593750e+002 + 2.4301745605468750e+002 4.2085028076171875e+002 + 2.8645983886718750e+002 4.3245474243164062e+002 + 3.3151913452148437e+002 4.4021636962890625e+002 + 1.4170318603515625e+002 4.0893341064453125e+002 + 1.6920660400390625e+002 4.2537210083007812e+002 + 2.0246380615234375e+002 4.4140267944335937e+002 + 2.4063006591796875e+002 4.5525744628906250e+002 + 2.8105111694335937e+002 4.6589947509765625e+002 + 3.2333105468750000e+002 4.7245309448242187e+002 + 1.4534066772460937e+002 4.3751367187500000e+002 + 1.7236315917968750e+002 4.5422381591796875e+002 + 2.0395715332031250e+002 4.6958795166015625e+002 + 2.3943508911132812e+002 4.8249044799804687e+002 + 2.7749969482421875e+002 4.9250592041015625e+002 + 3.1584771728515625e+002 4.9817904663085937e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.1166473388671875e+002 1.9514389038085937e+002 + 2.4524975585937500e+002 2.0299987792968750e+002 + 2.8427554321289062e+002 2.1267237854003906e+002 + 3.2836251831054687e+002 2.2432853698730469e+002 + 3.7409640502929687e+002 2.3872772216796875e+002 + 4.1826239013671875e+002 2.5345281982421875e+002 + 1.9421856689453125e+002 2.3415464782714844e+002 + 2.2773759460449219e+002 2.4497567749023437e+002 + 2.6810052490234375e+002 2.5739474487304687e+002 + 3.1436291503906250e+002 2.7157101440429687e+002 + 3.6250213623046875e+002 2.8696902465820312e+002 + 4.0925180053710937e+002 3.0085205078125000e+002 + 1.7868606567382812e+002 2.7623037719726562e+002 + 2.1160426330566406e+002 2.9030053710937500e+002 + 2.5232427978515625e+002 3.0676873779296875e+002 + 2.9902142333984375e+002 3.2336492919921875e+002 + 3.4904000854492187e+002 3.3905627441406250e+002 + 3.9731530761718750e+002 3.5189294433593750e+002 + 1.6575794982910156e+002 3.2019186401367187e+002 + 1.9864787292480469e+002 3.3750961303710938e+002 + 2.3825119018554687e+002 3.5649252319335938e+002 + 2.8477917480468750e+002 3.7475125122070313e+002 + 3.3459344482421875e+002 3.9041213989257812e+002 + 3.8334445190429688e+002 4.0201184082031250e+002 + 1.5659434509277344e+002 3.6217974853515625e+002 + 1.8836674499511719e+002 3.8265002441406250e+002 + 2.2735578918457031e+002 4.0316879272460937e+002 + 2.7255838012695312e+002 4.2235754394531250e+002 + 3.2083892822265625e+002 4.3743478393554687e+002 + 3.6911163330078125e+002 4.4745004272460937e+002 + 1.5123968505859375e+002 4.0053125000000000e+002 + 1.8211456298828125e+002 4.2233758544921875e+002 + 2.1948654174804687e+002 4.4352542114257812e+002 + 2.6250637817382812e+002 4.6227975463867187e+002 + 3.0846749877929687e+002 4.7673034667968750e+002 + 3.5461163330078125e+002 4.8573983764648437e+002 + 1.4931323242187500e+002 4.3426083374023437e+002 + 1.7922804260253906e+002 4.5601599121093750e+002 + 2.1442158508300781e+002 4.7652450561523437e+002 + 2.5534941101074219e+002 4.9463537597656250e+002 + 2.9853863525390625e+002 5.0857305908203125e+002 + 3.4164642333984375e+002 5.1656372070312500e+002 + 1.4981091308593750e+002 4.6215292358398437e+002 + 1.7847320556640625e+002 4.8342572021484375e+002 + 2.1191889953613281e+002 5.0336242675781250e+002 + 2.4997665405273437e+002 5.2017108154296875e+002 + 2.9027685546875000e+002 5.3286035156250000e+002 + 3.3030676269531250e+002 5.4025433349609375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.9738394165039062e+002 1.1224095916748047e+002 + 2.2443896484375000e+002 9.7065155029296875e+001 + 2.5575772094726562e+002 8.1795135498046875e+001 + 2.9134497070312500e+002 6.8509895324707031e+001 + 3.3013122558593750e+002 5.8412899017333984e+001 + 3.6942333984375000e+002 5.0993480682373047e+001 + 1.9647511291503906e+002 1.4175041198730469e+002 + 2.2477650451660156e+002 1.2745121002197266e+002 + 2.5736923217773437e+002 1.1256245422363281e+002 + 2.9559265136718750e+002 9.8407341003417969e+001 + 3.3647198486328125e+002 8.7929252624511719e+001 + 3.7886495971679687e+002 8.0916992187500000e+001 + 1.9726051330566406e+002 1.7528515625000000e+002 + 2.2613885498046875e+002 1.6222125244140625e+002 + 2.6057653808593750e+002 1.4850808715820312e+002 + 3.0034371948242187e+002 1.3539747619628906e+002 + 3.4374102783203125e+002 1.2513888549804687e+002 + 3.8899118041992187e+002 1.1717333221435547e+002 + 1.9982228088378906e+002 2.1294816589355469e+002 + 2.2929902648925781e+002 2.0171205139160156e+002 + 2.6524847412109375e+002 1.8964622497558594e+002 + 3.0722396850585937e+002 1.7814860534667969e+002 + 3.5259381103515625e+002 1.6776728820800781e+002 + 3.9922607421875000e+002 1.6089704895019531e+002 + 2.0460494995117187e+002 2.5315820312500000e+002 + 2.3481781005859375e+002 2.4440615844726562e+002 + 2.7132778930664062e+002 2.3537051391601562e+002 + 3.1381396484375000e+002 2.2593696594238281e+002 + 3.6103900146484375e+002 2.1671649169921875e+002 + 4.0812438964843750e+002 2.0943247985839844e+002 + 2.1232192993164062e+002 2.9321453857421875e+002 + 2.4272831726074219e+002 2.8755487060546875e+002 + 2.7948101806640625e+002 2.8144732666015625e+002 + 3.2177255249023437e+002 2.7491537475585937e+002 + 3.6864657592773437e+002 2.6708718872070312e+002 + 4.1504595947265625e+002 2.5978192138671875e+002 + 2.2173133850097656e+002 3.3142803955078125e+002 + 2.5222180175781250e+002 3.2957330322265625e+002 + 2.8819940185546875e+002 3.2624118041992187e+002 + 3.3014706420898437e+002 3.2186242675781250e+002 + 3.7504113769531250e+002 3.1526245117187500e+002 + 4.1983218383789062e+002 3.0772360229492187e+002 + 2.3245191955566406e+002 3.6598059082031250e+002 + 2.6260736083984375e+002 3.6674832153320312e+002 + 2.9763058471679687e+002 3.6589349365234375e+002 + 3.3729699707031250e+002 3.6309756469726562e+002 + 3.8008654785156250e+002 3.5828939819335937e+002 + 4.2274783325195312e+002 3.5088388061523437e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.9739215087890625e+002 1.0587763977050781e+002 + 2.2548576354980469e+002 9.1286560058593750e+001 + 2.5775613403320312e+002 7.6718307495117188e+001 + 2.9434518432617188e+002 6.4568824768066406e+001 + 3.3337722778320312e+002 5.4576992034912109e+001 + 3.7341531372070313e+002 4.9379707336425781e+001 + 1.9627896118164062e+002 1.3578916931152344e+002 + 2.2491828918457031e+002 1.2144824218750000e+002 + 2.5878680419921875e+002 1.0730403137207031e+002 + 2.9741754150390625e+002 9.4547775268554688e+001 + 3.3952651977539062e+002 8.4735786437988281e+001 + 3.8222692871093750e+002 7.8730262756347656e+001 + 1.9595693969726562e+002 1.7005430603027344e+002 + 2.2547554016113281e+002 1.5678283691406250e+002 + 2.6098175048828125e+002 1.4330615234375000e+002 + 3.0194058227539062e+002 1.3136526489257812e+002 + 3.4622671508789063e+002 1.2183640289306641e+002 + 3.9163809204101562e+002 1.1582347106933594e+002 + 1.9797586059570312e+002 2.0816328430175781e+002 + 2.2802325439453125e+002 1.9694920349121094e+002 + 2.6490988159179687e+002 1.8542794799804687e+002 + 3.0755038452148437e+002 1.7437118530273438e+002 + 3.5419616699218750e+002 1.6480737304687500e+002 + 4.0099414062500000e+002 1.5908491516113281e+002 + 2.0220266723632812e+002 2.4849215698242187e+002 + 2.3308509826660156e+002 2.3987425231933594e+002 + 2.7011486816406250e+002 2.3158035278320312e+002 + 3.1377700805664062e+002 2.2293681335449219e+002 + 3.6134454345703125e+002 2.1434486389160156e+002 + 4.0919036865234375e+002 2.0829397583007812e+002 + 2.0937780761718750e+002 2.8906222534179687e+002 + 2.4012644958496094e+002 2.8433255004882812e+002 + 2.7752197265625000e+002 2.7907070922851562e+002 + 3.2147686767578125e+002 2.7226861572265625e+002 + 3.6860739135742187e+002 2.6547314453125000e+002 + 4.1597256469726562e+002 2.5885076904296875e+002 + 2.1797999572753906e+002 3.2849447631835937e+002 + 2.4883102416992187e+002 3.2694689941406250e+002 + 2.8628955078125000e+002 3.2443133544921875e+002 + 3.2844613647460937e+002 3.1980096435546875e+002 + 3.7452346801757812e+002 3.1399343872070313e+002 + 4.1964608764648437e+002 3.0746643066406250e+002 + 2.2858824157714844e+002 3.6434890747070312e+002 + 2.5897933959960937e+002 3.6530865478515625e+002 + 2.9502014160156250e+002 3.6473443603515625e+002 + 3.3565216064453125e+002 3.6193106079101562e+002 + 3.7902673339843750e+002 3.5750778198242187e+002 + 4.2149499511718750e+002 3.5099053955078125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.6822442626953125e+002 2.4008656311035156e+002 + 2.9070654296875000e+002 2.2056822204589844e+002 + 3.1757363891601562e+002 1.9813229370117187e+002 + 3.4930169677734375e+002 1.7279872131347656e+002 + 3.8428540039062500e+002 1.4655470275878906e+002 + 4.2213000488281250e+002 1.2175158691406250e+002 + 2.7706515502929687e+002 2.7428814697265625e+002 + 3.0161596679687500e+002 2.5639001464843750e+002 + 3.3123556518554687e+002 2.3533209228515625e+002 + 3.6646438598632812e+002 2.1065528869628906e+002 + 4.0618121337890625e+002 1.8462944030761719e+002 + 4.4775518798828125e+002 1.5845857238769531e+002 + 2.8782800292968750e+002 3.1086019897460938e+002 + 3.1395745849609375e+002 2.9601510620117187e+002 + 3.4648013305664062e+002 2.7797116088867187e+002 + 3.8599011230468750e+002 2.5556666564941406e+002 + 4.2946029663085937e+002 2.3047912597656250e+002 + 4.7500729370117187e+002 2.0411773681640625e+002 + 2.9947738647460937e+002 3.4926666259765625e+002 + 3.2810287475585937e+002 3.3843762207031250e+002 + 3.6357427978515625e+002 3.2378787231445312e+002 + 4.0530972290039062e+002 3.0547250366210937e+002 + 4.5212115478515625e+002 2.8265661621093750e+002 + 4.9962380981445312e+002 2.5768753051757813e+002 + 3.1273556518554687e+002 3.8686230468750000e+002 + 3.4273712158203125e+002 3.7986633300781250e+002 + 3.7973696899414062e+002 3.7038986206054687e+002 + 4.2343887329101562e+002 3.5594061279296875e+002 + 4.7149053955078125e+002 3.3647348022460937e+002 + 5.1954309082031250e+002 3.1330352783203125e+002 + 3.2647396850585937e+002 4.2253649902343750e+002 + 3.5715408325195312e+002 4.1938366699218750e+002 + 3.9438674926757812e+002 4.1338021850585937e+002 + 4.3812377929687500e+002 4.0281912231445312e+002 + 4.8538482666015625e+002 3.8670669555664062e+002 + 5.3271191406250000e+002 3.6555712890625000e+002 + 3.3934649658203125e+002 4.5414926147460937e+002 + 3.7043768310546875e+002 4.5365594482421875e+002 + 4.0770382690429687e+002 4.5044808959960937e+002 + 4.4935568237304687e+002 4.4309701538085937e+002 + 4.9470053100585937e+002 4.2953518676757812e+002 + 5.3949871826171875e+002 4.1113757324218750e+002 + 3.5164358520507812e+002 4.8114984130859375e+002 + 3.8253826904296875e+002 4.8243450927734375e+002 + 4.1743527221679687e+002 4.8105902099609375e+002 + 4.5756820678710937e+002 4.7524966430664062e+002 + 5.0011929321289063e+002 4.6462640380859375e+002 + 5.4165386962890625e+002 4.4799038696289062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.3003479003906250e+002 2.0737373352050781e+002 + 1.4866926574707031e+002 1.8398992919921875e+002 + 1.7303520202636719e+002 1.5777470397949219e+002 + 2.0249278259277344e+002 1.3057046508789062e+002 + 2.3766433715820312e+002 1.0327043914794922e+002 + 2.7715426635742187e+002 7.9372337341308594e+001 + 1.4643794250488281e+002 2.3693443298339844e+002 + 1.6573986816406250e+002 2.1521826171875000e+002 + 1.9078918457031250e+002 1.9127677917480469e+002 + 2.2126823425292969e+002 1.6541952514648437e+002 + 2.5672271728515625e+002 1.3921260070800781e+002 + 2.9694876098632812e+002 1.1533818054199219e+002 + 1.6443966674804687e+002 2.6663464355468750e+002 + 1.8538964843750000e+002 2.4753227233886719e+002 + 2.1144834899902344e+002 2.2583900451660156e+002 + 2.4238636779785156e+002 2.0240379333496094e+002 + 2.7835873413085937e+002 1.7771739196777344e+002 + 3.1767086791992187e+002 1.5481472778320312e+002 + 1.8451625061035156e+002 2.9560656738281250e+002 + 2.0635713195800781e+002 2.7871987915039062e+002 + 2.3273893737792969e+002 2.5984979248046875e+002 + 2.6394033813476562e+002 2.3871148681640625e+002 + 2.9981539916992187e+002 2.1632020568847656e+002 + 3.3794692993164062e+002 1.9436102294921875e+002 + 2.0509422302246094e+002 3.2254663085937500e+002 + 2.2790527343750000e+002 3.0849981689453125e+002 + 2.5451188659667969e+002 2.9179046630859375e+002 + 2.8532434082031250e+002 2.7324002075195312e+002 + 3.1970004272460937e+002 2.5328439331054687e+002 + 3.5597808837890625e+002 2.3272837829589844e+002 + 2.2583001708984375e+002 3.4663317871093750e+002 + 2.4841854858398437e+002 3.3458721923828125e+002 + 2.7519577026367187e+002 3.2027291870117187e+002 + 3.0530963134765625e+002 3.0370773315429687e+002 + 3.3779397583007812e+002 2.8584375000000000e+002 + 3.7166363525390625e+002 2.6741744995117187e+002 + 2.4551525878906250e+002 3.6739392089843750e+002 + 2.6850360107421875e+002 3.5684466552734375e+002 + 2.9435690307617187e+002 3.4424645996093750e+002 + 3.2327902221679687e+002 3.3014801025390625e+002 + 3.5352316284179687e+002 3.1442721557617187e+002 + 3.8536239624023437e+002 2.9667779541015625e+002 + 2.6367367553710937e+002 3.8444241333007812e+002 + 2.8589642333984375e+002 3.7571841430664062e+002 + 3.1094891357421875e+002 3.6481320190429687e+002 + 3.3819848632812500e+002 3.5200665283203125e+002 + 3.6728549194335937e+002 3.3760061645507812e+002 + 3.9623217773437500e+002 3.2167398071289062e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.2104422760009766e+002 2.6323342895507812e+002 + 1.4659393310546875e+002 2.5661331176757812e+002 + 1.7623132324218750e+002 2.4903153991699219e+002 + 2.1062576293945312e+002 2.4187670898437500e+002 + 2.4838075256347656e+002 2.3483999633789063e+002 + 2.8797589111328125e+002 2.2889019775390625e+002 + 1.2154541015625000e+002 3.0097201538085937e+002 + 1.4726095581054687e+002 2.9590768432617187e+002 + 1.7773031616210937e+002 2.9011010742187500e+002 + 2.1369670104980469e+002 2.8383813476562500e+002 + 2.5284750366210937e+002 2.7682669067382812e+002 + 2.9330725097656250e+002 2.7019491577148437e+002 + 1.2469777679443359e+002 3.4046401977539062e+002 + 1.5098295593261719e+002 3.3775964355468750e+002 + 1.8260154724121094e+002 3.3421865844726562e+002 + 2.1928509521484375e+002 3.2833322143554687e+002 + 2.5930303955078125e+002 3.2201141357421875e+002 + 3.0131921386718750e+002 3.1371130371093750e+002 + 1.3110339355468750e+002 3.8016491699218750e+002 + 1.5829032897949219e+002 3.7959197998046875e+002 + 1.9053800964355469e+002 3.7743780517578125e+002 + 2.2733467102050781e+002 3.7329373168945312e+002 + 2.6780563354492187e+002 3.6666064453125000e+002 + 3.0965774536132812e+002 3.5857568359375000e+002 + 1.4087307739257812e+002 4.1841809082031250e+002 + 1.6854266357421875e+002 4.1949826049804687e+002 + 2.0062602233886719e+002 4.1859002685546875e+002 + 2.3760568237304688e+002 4.1559667968750000e+002 + 2.7794451904296875e+002 4.0934991455078125e+002 + 3.1883627319335938e+002 4.0059088134765625e+002 + 1.5325030517578125e+002 4.5325537109375000e+002 + 1.8053645324707031e+002 4.5536987304687500e+002 + 2.1306137084960937e+002 4.5544427490234375e+002 + 2.5005780029296875e+002 4.5294244384765625e+002 + 2.8838088989257812e+002 4.4704031372070312e+002 + 3.2795251464843750e+002 4.3743698120117187e+002 + 1.6683460998535156e+002 4.8319500732421875e+002 + 1.9546427917480469e+002 4.8703466796875000e+002 + 2.2665493774414062e+002 4.8730511474609375e+002 + 2.6180609130859375e+002 4.8490786743164063e+002 + 2.9924615478515625e+002 4.7897695922851562e+002 + 3.3626516723632812e+002 4.6939453125000000e+002 + 1.8154464721679687e+002 5.0914895629882813e+002 + 2.0896336364746094e+002 5.1244415283203125e+002 + 2.3994398498535156e+002 5.1372448730468750e+002 + 2.7375592041015625e+002 5.1105667114257813e+002 + 3.0885763549804687e+002 5.0537197875976562e+002 + 3.4393814086914062e+002 4.9616387939453125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.3937307739257812e+002 1.5381077575683594e+002 + 1.6038864135742187e+002 1.6570022583007812e+002 + 1.8376007080078125e+002 1.7922540283203125e+002 + 2.0956678771972656e+002 1.9360334777832031e+002 + 2.3668365478515625e+002 2.0898406982421875e+002 + 2.6362500000000000e+002 2.2451243591308594e+002 + 1.2163760375976562e+002 1.8129240417480469e+002 + 1.4312561035156250e+002 1.9430174255371094e+002 + 1.6727124023437500e+002 2.0842822265625000e+002 + 1.9364099121093750e+002 2.2345896911621094e+002 + 2.2179484558105469e+002 2.3866944885253906e+002 + 2.5083377075195313e+002 2.5437602233886719e+002 + 1.0476881408691406e+002 2.1141342163085937e+002 + 1.2647509765625000e+002 2.2558738708496094e+002 + 1.5116107177734375e+002 2.4031248474121094e+002 + 1.7924765014648437e+002 2.5613253784179687e+002 + 2.0847218322753906e+002 2.7126535034179687e+002 + 2.3867022705078125e+002 2.8702282714843750e+002 + 9.0344108581542969e+001 2.4376466369628906e+002 + 1.1173908996582031e+002 2.5928869628906250e+002 + 1.3747230529785156e+002 2.7482882690429687e+002 + 1.6561442565917969e+002 2.9084930419921875e+002 + 1.9571585083007812e+002 3.0609027099609375e+002 + 2.2646200561523437e+002 3.2046646118164062e+002 + 7.8558143615722656e+001 2.7812982177734375e+002 + 1.0020967864990234e+002 2.9385952758789063e+002 + 1.2557929229736328e+002 3.1088137817382812e+002 + 1.5418733215332031e+002 3.2645739746093750e+002 + 1.8477856445312500e+002 3.4169808959960937e+002 + 2.1647000122070312e+002 3.5520907592773437e+002 + 6.9968360900878906e+001 3.1248602294921875e+002 + 9.1588615417480469e+001 3.2942941284179687e+002 + 1.1708594512939453e+002 3.4600616455078125e+002 + 1.4554133605957031e+002 3.6184063720703125e+002 + 1.7604438781738281e+002 3.7577825927734375e+002 + 2.0764952087402344e+002 3.8776010131835937e+002 + 6.5314735412597656e+001 3.4553314208984375e+002 + 8.6143600463867187e+001 3.6261727905273438e+002 + 1.1153878784179687e+002 3.7938092041015625e+002 + 1.3962799072265625e+002 3.9494290161132812e+002 + 1.6992620849609375e+002 4.0780990600585937e+002 + 2.0140124511718750e+002 4.1901651000976562e+002 + 6.3450622558593750e+001 3.7641946411132812e+002 + 8.4475975036621094e+001 3.9402755737304687e+002 + 1.0893721008300781e+002 4.1005371093750000e+002 + 1.3680917358398437e+002 4.2499734497070312e+002 + 1.6610684204101562e+002 4.3731768798828125e+002 + 1.9656358337402344e+002 4.4648822021484375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.0802473449707031e+002 1.1255024719238281e+002 + 2.3760588073730469e+002 1.0638483428955078e+002 + 2.7193350219726562e+002 1.0040081787109375e+002 + 3.1034252929687500e+002 9.7948982238769531e+001 + 3.5185202026367188e+002 9.7754867553710937e+001 + 3.9274203491210937e+002 1.0175122070312500e+002 + 2.0119204711914062e+002 1.4571533203125000e+002 + 2.3168411254882812e+002 1.4081744384765625e+002 + 2.6650299072265625e+002 1.3643354797363281e+002 + 3.0706829833984375e+002 1.3423451232910156e+002 + 3.4976214599609375e+002 1.3497346496582031e+002 + 3.9262048339843750e+002 1.3860818481445312e+002 + 1.9558905029296875e+002 1.8279119873046875e+002 + 2.2611965942382812e+002 1.7958126831054687e+002 + 2.6201419067382812e+002 1.7693395996093750e+002 + 3.0264654541015625e+002 1.7611520385742187e+002 + 3.4710076904296875e+002 1.7831663513183594e+002 + 3.9110543823242187e+002 1.8161508178710937e+002 + 1.9235888671875000e+002 2.2210964965820312e+002 + 2.2246267700195312e+002 2.2132341003417969e+002 + 2.5856195068359375e+002 2.2139974975585937e+002 + 2.9955319213867187e+002 2.2246673583984375e+002 + 3.4429977416992188e+002 2.2428495788574219e+002 + 3.8902563476562500e+002 2.2808396911621094e+002 + 1.9134326171875000e+002 2.6238821411132812e+002 + 2.2105798339843750e+002 2.6400335693359375e+002 + 2.5632949829101563e+002 2.6636590576171875e+002 + 2.9726416015625000e+002 2.6938986206054687e+002 + 3.4165740966796875e+002 2.7194714355468750e+002 + 3.8579312133789062e+002 2.7542672729492187e+002 + 1.9230525207519531e+002 3.0060739135742187e+002 + 2.2148333740234375e+002 3.0529205322265625e+002 + 2.5654483032226562e+002 3.1039709472656250e+002 + 2.9583343505859375e+002 3.1401379394531250e+002 + 3.3849111938476562e+002 3.1762307739257812e+002 + 3.8155474853515625e+002 3.2049139404296875e+002 + 1.9590739440917969e+002 3.3675585937500000e+002 + 2.2472146606445312e+002 3.4285635375976562e+002 + 2.5836550903320312e+002 3.4935034179687500e+002 + 2.9575567626953125e+002 3.5472558593750000e+002 + 3.3601510620117187e+002 3.5849920654296875e+002 + 3.7657949829101562e+002 3.6066433715820312e+002 + 2.0100540161132812e+002 3.6847964477539062e+002 + 2.2872590637207031e+002 3.7650939941406250e+002 + 2.6094659423828125e+002 3.8347000122070313e+002 + 2.9623818969726562e+002 3.8912585449218750e+002 + 3.3372262573242187e+002 3.9319000244140625e+002 + 3.7204150390625000e+002 3.9508642578125000e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.9253829956054687e+002 1.7666793823242187e+002 + 2.2092472839355469e+002 1.7816407775878906e+002 + 2.5450471496582031e+002 1.8064866638183594e+002 + 2.9172927856445312e+002 1.8492027282714844e+002 + 3.3163308715820312e+002 1.9134786987304688e+002 + 3.7204782104492187e+002 1.9914372253417969e+002 + 1.7994387817382812e+002 2.1062715148925781e+002 + 2.0916287231445312e+002 2.1433047485351562e+002 + 2.4329905700683594e+002 2.1854037475585937e+002 + 2.8230355834960937e+002 2.2425605773925781e+002 + 3.2468313598632812e+002 2.3173370361328125e+002 + 3.6775109863281250e+002 2.4003758239746094e+002 + 1.6905540466308594e+002 2.4857388305664062e+002 + 1.9794456481933594e+002 2.5443492126464844e+002 + 2.3253137207031250e+002 2.6112719726562500e+002 + 2.7277734375000000e+002 2.6857852172851562e+002 + 3.1675445556640625e+002 2.7650186157226562e+002 + 3.6073773193359375e+002 2.8485681152343750e+002 + 1.6045989990234375e+002 2.8834310913085937e+002 + 1.8892225646972656e+002 2.9699011230468750e+002 + 2.2362922668457031e+002 3.0630169677734375e+002 + 2.6441308593750000e+002 3.1641159057617187e+002 + 3.0899291992187500e+002 3.2462097167968750e+002 + 3.5429559326171875e+002 3.3270574951171875e+002 + 1.5425645446777344e+002 3.2875631713867187e+002 + 1.8279353332519531e+002 3.3973736572265625e+002 + 2.1708808898925781e+002 3.5146392822265625e+002 + 2.5769207763671875e+002 3.6258703613281250e+002 + 3.0196875000000000e+002 3.7255883789062500e+002 + 3.4735443115234375e+002 3.7937939453125000e+002 + 1.5145359802246094e+002 3.6695669555664062e+002 + 1.7979283142089844e+002 3.8033654785156250e+002 + 2.1378921508789063e+002 3.9387835693359375e+002 + 2.5310304260253906e+002 4.0567169189453125e+002 + 2.9585595703125000e+002 4.1556201171875000e+002 + 3.4037545776367187e+002 4.2183197021484375e+002 + 1.5157664489746094e+002 4.0224444580078125e+002 + 1.7948303222656250e+002 4.1666781616210937e+002 + 2.1227598571777344e+002 4.3072094726562500e+002 + 2.5002114868164062e+002 4.4306521606445312e+002 + 2.9099218750000000e+002 4.5274813842773437e+002 + 3.3341720581054687e+002 4.5846105957031250e+002 + 1.5354914855957031e+002 4.3297006225585937e+002 + 1.8130723571777344e+002 4.4866021728515625e+002 + 2.1289338684082031e+002 4.6262091064453125e+002 + 2.4881596374511719e+002 4.7484161376953125e+002 + 2.8804968261718750e+002 4.8355838012695312e+002 + 3.2713543701171875e+002 4.8878240966796875e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.9443359375000000e+002 2.3671203613281250e+002 + 2.2241497802734375e+002 2.2963148498535156e+002 + 2.5427357482910156e+002 2.2224876403808594e+002 + 2.9009811401367187e+002 2.1438049316406250e+002 + 3.2942227172851562e+002 2.0832928466796875e+002 + 3.6916183471679687e+002 2.0243862915039062e+002 + 1.9221551513671875e+002 2.7176156616210937e+002 + 2.2029853820800781e+002 2.6680340576171875e+002 + 2.5407563781738281e+002 2.6098513793945313e+002 + 2.9235711669921875e+002 2.5409892272949219e+002 + 3.3395248413085937e+002 2.4780184936523437e+002 + 3.7635110473632812e+002 2.4194679260253906e+002 + 1.9176831054687500e+002 3.1039511108398437e+002 + 2.2105955505371094e+002 3.0683905029296875e+002 + 2.5549624633789063e+002 3.0300796508789063e+002 + 2.9558416748046875e+002 2.9836862182617187e+002 + 3.3858621215820313e+002 2.9251733398437500e+002 + 3.8335284423828125e+002 2.8632904052734375e+002 + 1.9318630981445312e+002 3.4967327880859375e+002 + 2.2311123657226562e+002 3.4906008911132812e+002 + 2.5864190673828125e+002 3.4826556396484375e+002 + 2.9980490112304687e+002 3.4498406982421875e+002 + 3.4409201049804687e+002 3.4034588623046875e+002 + 3.8894284057617187e+002 3.3336328125000000e+002 + 1.9705062866210937e+002 3.8855068969726562e+002 + 2.2751509094238281e+002 3.9075115966796875e+002 + 2.6367651367187500e+002 3.9208807373046875e+002 + 3.0481381225585937e+002 3.9073855590820312e+002 + 3.4976370239257812e+002 3.8685986328125000e+002 + 3.9457742309570312e+002 3.7985845947265625e+002 + 2.0331918334960937e+002 4.2530661010742187e+002 + 2.3364744567871094e+002 4.3046316528320312e+002 + 2.6994488525390625e+002 4.3268774414062500e+002 + 3.1086114501953125e+002 4.3279223632812500e+002 + 3.5448004150390625e+002 4.2991195678710937e+002 + 3.9848663330078125e+002 4.2265631103515625e+002 + 2.1114546203613281e+002 4.5861663818359375e+002 + 2.4173469543457031e+002 4.6454113769531250e+002 + 2.7711996459960937e+002 4.6866964721679687e+002 + 3.1710476684570312e+002 4.6968862915039062e+002 + 3.5898089599609375e+002 4.6655914306640625e+002 + 4.0113323974609375e+002 4.6039312744140625e+002 + 2.2030920410156250e+002 4.8728347778320312e+002 + 2.5043615722656250e+002 4.9382522583007812e+002 + 2.8417904663085937e+002 4.9878988647460937e+002 + 3.2246951293945313e+002 4.9978683471679687e+002 + 3.6231713867187500e+002 4.9761297607421875e+002 + 4.0228164672851563e+002 4.9122601318359375e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.6468949890136719e+002 5.3180915832519531e+001 + 1.9547587585449219e+002 4.1574821472167969e+001 + 2.3047291564941406e+002 3.1616912841796875e+001 + 2.6987237548828125e+002 2.5713516235351563e+001 + 3.1042465209960937e+002 2.4633863449096680e+001 + 3.5104907226562500e+002 2.7085699081420898e+001 + 1.5940153503417969e+002 8.5298866271972656e+001 + 1.9106449890136719e+002 7.4148872375488281e+001 + 2.2599386596679687e+002 6.5447418212890625e+001 + 2.6544070434570312e+002 5.9492092132568359e+001 + 3.0788000488281250e+002 5.7038726806640625e+001 + 3.4942132568359375e+002 5.9414051055908203e+001 + 1.5721818542480469e+002 1.1995565032958984e+002 + 1.8816139221191406e+002 1.1013637542724609e+002 + 2.2369296264648437e+002 1.0256072998046875e+002 + 2.6338803100585937e+002 9.6611572265625000e+001 + 3.0533670043945312e+002 9.5402069091796875e+001 + 3.4731597900390625e+002 9.6923431396484375e+001 + 1.5764701843261719e+002 1.5663424682617187e+002 + 1.8767741394042969e+002 1.4887019348144531e+002 + 2.2280422973632812e+002 1.4250959777832031e+002 + 2.6184680175781250e+002 1.3743280029296875e+002 + 3.0353137207031250e+002 1.3632562255859375e+002 + 3.4522973632812500e+002 1.3748583984375000e+002 + 1.6057028198242187e+002 1.9403329467773437e+002 + 1.9000785827636719e+002 1.8821299743652344e+002 + 2.2451312255859375e+002 1.8319659423828125e+002 + 2.6239715576171875e+002 1.7945388793945312e+002 + 3.0235687255859375e+002 1.7841618347167969e+002 + 3.4289450073242187e+002 1.7852563476562500e+002 + 1.6602676391601562e+002 2.2970957946777344e+002 + 1.9420118713378906e+002 2.2636227416992187e+002 + 2.2764262390136719e+002 2.2253077697753906e+002 + 2.6429263305664062e+002 2.2049848937988281e+002 + 3.0232293701171875e+002 2.1871647644042969e+002 + 3.4069152832031250e+002 2.1766073608398438e+002 + 1.7318965148925781e+002 2.6342864990234375e+002 + 2.0103724670410156e+002 2.6106411743164062e+002 + 2.3252487182617188e+002 2.5961901855468750e+002 + 2.6648431396484375e+002 2.5750674438476562e+002 + 3.0246304321289062e+002 2.5635064697265625e+002 + 3.3871148681640625e+002 2.5369876098632812e+002 + 1.8150636291503906e+002 2.9294061279296875e+002 + 2.0774707031250000e+002 2.9249325561523437e+002 + 2.3760902404785156e+002 2.9153884887695312e+002 + 2.6964648437500000e+002 2.8987216186523437e+002 + 3.0353713989257812e+002 2.8864797973632812e+002 + 3.3714611816406250e+002 2.8634063720703125e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.5441897583007813e+002 1.6613870239257812e+002 + 1.7650827026367187e+002 1.6631884765625000e+002 + 2.0148481750488281e+002 1.6741561889648438e+002 + 2.2869082641601562e+002 1.6981973266601562e+002 + 2.5744985961914062e+002 1.7286692810058594e+002 + 2.8803839111328125e+002 1.7731474304199219e+002 + 1.4607637023925781e+002 1.9399189758300781e+002 + 1.6808514404296875e+002 1.9529283142089844e+002 + 1.9325042724609375e+002 1.9747297668457031e+002 + 2.2133262634277344e+002 1.9966006469726562e+002 + 2.5155979919433594e+002 2.0340777587890625e+002 + 2.8274588012695312e+002 2.0846081542968750e+002 + 1.3844108581542969e+002 2.2469718933105469e+002 + 1.6058381652832031e+002 2.2678462219238281e+002 + 1.8653430175781250e+002 2.2973921203613281e+002 + 2.1482469177246094e+002 2.3338439941406250e+002 + 2.4503909301757812e+002 2.3690806579589844e+002 + 2.7769775390625000e+002 2.4195111083984375e+002 + 1.3264593505859375e+002 2.5659811401367187e+002 + 1.5510156250000000e+002 2.5974905395507812e+002 + 1.8100151062011719e+002 2.6382571411132812e+002 + 2.0927462768554687e+002 2.6841168212890625e+002 + 2.4047984313964844e+002 2.7257797241210937e+002 + 2.7320791625976562e+002 2.7706173706054687e+002 + 1.2890335083007813e+002 2.8869668579101562e+002 + 1.5145930480957031e+002 2.9349945068359375e+002 + 1.7660194396972656e+002 2.9867013549804687e+002 + 2.0568075561523437e+002 3.0383666992187500e+002 + 2.3661387634277344e+002 3.0859414672851562e+002 + 2.6957293701171875e+002 3.1261154174804688e+002 + 1.2814846801757813e+002 3.2090509033203125e+002 + 1.4940550231933594e+002 3.2686093139648437e+002 + 1.7536868286132812e+002 3.3311645507812500e+002 + 2.0359295654296875e+002 3.3841876220703125e+002 + 2.3457095336914062e+002 3.4349581909179687e+002 + 2.6671859741210937e+002 3.4746987915039062e+002 + 1.2830876159667969e+002 3.5162771606445312e+002 + 1.5065673828125000e+002 3.5865673828125000e+002 + 1.7526635742187500e+002 3.6548324584960937e+002 + 2.0343365478515625e+002 3.7152569580078125e+002 + 2.3371678161621094e+002 3.7637008666992187e+002 + 2.6536779785156250e+002 3.7983935546875000e+002 + 1.3068347167968750e+002 3.7994442749023437e+002 + 1.5273191833496094e+002 3.8802938842773437e+002 + 1.7753459167480469e+002 3.9547338867187500e+002 + 2.0443832397460937e+002 4.0111117553710937e+002 + 2.3415042114257812e+002 4.0632867431640625e+002 + 2.6436553955078125e+002 4.0947976684570312e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.7370266723632812e+002 1.3438679504394531e+002 + 1.9637240600585937e+002 1.1757235717773437e+002 + 2.2421786499023437e+002 9.9530479431152344e+001 + 2.5734353637695312e+002 8.1556762695312500e+001 + 2.9641128540039062e+002 6.4711936950683594e+001 + 3.4007113647460937e+002 5.1720169067382812e+001 + 1.7700553894042969e+002 1.6568067932128906e+002 + 1.9973159790039062e+002 1.5132649230957031e+002 + 2.2850166320800781e+002 1.3441078186035156e+002 + 2.6307540893554687e+002 1.1766706848144531e+002 + 3.0421228027343750e+002 1.0158131408691406e+002 + 3.4989172363281250e+002 8.8373657226562500e+001 + 1.8217860412597656e+002 2.0051080322265625e+002 + 2.0539692687988281e+002 1.8785760498046875e+002 + 2.3470951843261719e+002 1.7409780883789063e+002 + 2.7047976684570312e+002 1.5948243713378906e+002 + 3.1311456298828125e+002 1.4525968933105469e+002 + 3.6054827880859375e+002 1.3260859680175781e+002 + 1.8943176269531250e+002 2.3635137939453125e+002 + 2.1353262329101562e+002 2.2677250671386719e+002 + 2.4354132080078125e+002 2.1624514770507812e+002 + 2.7993521118164062e+002 2.0481312561035156e+002 + 3.2292248535156250e+002 1.9300155639648437e+002 + 3.7121041870117187e+002 1.8250210571289062e+002 + 1.9847045898437500e+002 2.7247601318359375e+002 + 2.2300814819335938e+002 2.6564059448242187e+002 + 2.5309912109375000e+002 2.5928713989257812e+002 + 2.9003536987304687e+002 2.5161386108398438e+002 + 3.3305670166015625e+002 2.4227992248535156e+002 + 3.8028915405273437e+002 2.3408541870117187e+002 + 2.0959469604492187e+002 3.0655566406250000e+002 + 2.3406565856933594e+002 3.0397387695312500e+002 + 2.6459643554687500e+002 2.9994485473632812e+002 + 3.0078497314453125e+002 2.9554483032226562e+002 + 3.4252929687500000e+002 2.8982553100585937e+002 + 3.8807220458984375e+002 2.8291806030273437e+002 + 2.2141125488281250e+002 3.3782479858398437e+002 + 2.4647418212890625e+002 3.3774664306640625e+002 + 2.7627581787109375e+002 3.3667837524414062e+002 + 3.1103790283203125e+002 3.3480932617187500e+002 + 3.5086141967773437e+002 3.3111807250976562e+002 + 3.9350457763671875e+002 3.2587265014648437e+002 + 2.3366567993164062e+002 3.6551751708984375e+002 + 2.5837750244140625e+002 3.6763192749023437e+002 + 2.8731631469726562e+002 3.6857003784179687e+002 + 3.2089758300781250e+002 3.6774172973632812e+002 + 3.5771026611328125e+002 3.6571621704101562e+002 + 3.9711297607421875e+002 3.6183920288085937e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.0526953125000000e+002 2.5896508789062500e+002 + 1.2656654357910156e+002 2.4474024963378906e+002 + 1.5068653869628906e+002 2.2959620666503906e+002 + 1.7695504760742187e+002 2.1534713745117187e+002 + 2.0522479248046875e+002 2.0161729431152344e+002 + 2.3333944702148437e+002 1.8966360473632812e+002 + 1.0818422698974609e+002 2.8737445068359375e+002 + 1.2992694091796875e+002 2.7238073730468750e+002 + 1.5543544006347656e+002 2.5697940063476562e+002 + 1.8325471496582031e+002 2.4148214721679687e+002 + 2.1298818969726562e+002 2.2680686950683594e+002 + 2.4357525634765625e+002 2.1309342956542969e+002 + 1.1253370666503906e+002 3.1923190307617187e+002 + 1.3540219116210937e+002 3.0468569946289062e+002 + 1.6244915771484375e+002 2.8868518066406250e+002 + 1.9172105407714844e+002 2.7238055419921875e+002 + 2.2405233764648437e+002 2.5556632995605469e+002 + 2.5659545898437500e+002 2.4050701904296875e+002 + 1.2007905578613281e+002 3.5427221679687500e+002 + 1.4438632202148437e+002 3.3973553466796875e+002 + 1.7253227233886719e+002 3.2408444213867187e+002 + 2.0380209350585937e+002 3.0692871093750000e+002 + 2.3762220764160156e+002 2.8918908691406250e+002 + 2.7149551391601562e+002 2.7222726440429687e+002 + 1.3167845153808594e+002 3.9162780761718750e+002 + 1.5669052124023437e+002 3.7831506347656250e+002 + 1.8603605651855469e+002 3.6260202026367188e+002 + 2.1941960144042969e+002 3.4499154663085937e+002 + 2.5463104248046875e+002 3.2581469726562500e+002 + 2.8975460815429687e+002 3.0665811157226563e+002 + 1.4738092041015625e+002 4.3016833496093750e+002 + 1.7373771667480469e+002 4.1776162719726562e+002 + 2.0405062866210937e+002 4.0308755493164062e+002 + 2.3863723754882812e+002 3.8476367187500000e+002 + 2.7452239990234375e+002 3.6473074340820312e+002 + 3.1035162353515625e+002 3.4354992675781250e+002 + 1.6726031494140625e+002 4.6689187622070312e+002 + 1.9426292419433594e+002 4.5639160156250000e+002 + 2.2622428894042969e+002 4.4218261718750000e+002 + 2.6085989379882812e+002 4.2422894287109375e+002 + 2.9694686889648437e+002 4.0322521972656250e+002 + 3.3233435058593750e+002 3.8041522216796875e+002 + 1.9000495910644531e+002 5.0066082763671875e+002 + 2.1825032043457031e+002 4.9119262695312500e+002 + 2.5039102172851562e+002 4.7780404663085937e+002 + 2.8452566528320312e+002 4.5996481323242187e+002 + 3.2006314086914062e+002 4.3836526489257812e+002 + 3.5413653564453125e+002 4.1473974609375000e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.1420428466796875e+002 2.8888894653320312e+002 + 2.3227047729492187e+002 2.7500308227539062e+002 + 2.5249357604980469e+002 2.6045181274414062e+002 + 2.7260745239257812e+002 2.4649340820312500e+002 + 2.9334606933593750e+002 2.3268151855468750e+002 + 3.1451992797851562e+002 2.1897401428222656e+002 + 2.2276826477050781e+002 3.1053356933593750e+002 + 2.4235111999511719e+002 2.9641632080078125e+002 + 2.6241406250000000e+002 2.8213031005859375e+002 + 2.8386291503906250e+002 2.6644869995117187e+002 + 3.0614880371093750e+002 2.5231419372558594e+002 + 3.2752005004882812e+002 2.3781265258789062e+002 + 2.3275614929199219e+002 3.3363208007812500e+002 + 2.5311102294921875e+002 3.1970153808593750e+002 + 2.7463195800781250e+002 3.0467752075195312e+002 + 2.9724810791015625e+002 2.8911373901367187e+002 + 3.1962637329101563e+002 2.7365164184570312e+002 + 3.4223510742187500e+002 2.5831655883789062e+002 + 2.4435995483398437e+002 3.5810894775390625e+002 + 2.6545437622070313e+002 3.4371194458007812e+002 + 2.8815945434570312e+002 3.2888223266601562e+002 + 3.1100289916992187e+002 3.1244653320312500e+002 + 3.3443508911132812e+002 2.9659082031250000e+002 + 3.5728158569335938e+002 2.8066629028320312e+002 + 2.5682943725585937e+002 3.8288409423828125e+002 + 2.7925234985351562e+002 3.6925524902343750e+002 + 3.0238565063476562e+002 3.5399011230468750e+002 + 3.2642135620117187e+002 3.3749774169921875e+002 + 3.5010360717773437e+002 3.2054763793945312e+002 + 3.7293136596679687e+002 3.0372967529296875e+002 + 2.7164382934570312e+002 4.0807296752929687e+002 + 2.9410830688476562e+002 3.9458898925781250e+002 + 3.1794100952148437e+002 3.7903784179687500e+002 + 3.4237860107421875e+002 3.6253768920898437e+002 + 3.6649523925781250e+002 3.4540112304687500e+002 + 3.8946878051757812e+002 3.2780661010742187e+002 + 2.8690408325195312e+002 4.3240264892578125e+002 + 3.1012280273437500e+002 4.1935211181640625e+002 + 3.3413281250000000e+002 4.0442428588867187e+002 + 3.5878985595703125e+002 3.8764389038085937e+002 + 3.8277471923828125e+002 3.6982577514648437e+002 + 4.0602178955078125e+002 3.5165090942382812e+002 + 3.0270544433593750e+002 4.5556439208984375e+002 + 3.2621252441406250e+002 4.4271795654296875e+002 + 3.5046466064453125e+002 4.2794439697265625e+002 + 3.7497219848632812e+002 4.1147271728515625e+002 + 3.9879156494140625e+002 3.9362936401367187e+002 + 4.2134396362304688e+002 3.7498886108398437e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 2.4562251281738281e+002 2.0373670959472656e+002 + 2.5909262084960937e+002 1.8652943420410156e+002 + 2.7365792846679687e+002 1.6849024963378906e+002 + 2.8972363281250000e+002 1.5000402832031250e+002 + 3.0660998535156250e+002 1.3190055847167969e+002 + 3.2460745239257812e+002 1.1367031097412109e+002 + 2.5841610717773437e+002 2.2061692810058594e+002 + 2.7261706542968750e+002 2.0388200378417969e+002 + 2.8813909912109375e+002 1.8536820983886719e+002 + 3.0468936157226562e+002 1.6684196472167969e+002 + 3.2245492553710937e+002 1.4847993469238281e+002 + 3.4116912841796875e+002 1.2992178344726562e+002 + 2.7154885864257812e+002 2.3869288635253906e+002 + 2.8655590820312500e+002 2.2199595642089844e+002 + 3.0279666137695312e+002 2.0403919982910156e+002 + 3.2056231689453125e+002 1.8543121337890625e+002 + 3.3936584472656250e+002 1.6676190185546875e+002 + 3.5877514648437500e+002 1.4825135803222656e+002 + 2.8573974609375000e+002 2.5752984619140625e+002 + 3.0136871337890625e+002 2.4129231262207031e+002 + 3.1856750488281250e+002 2.2363269042968750e+002 + 3.3730453491210937e+002 2.0521472167968750e+002 + 3.5695181274414062e+002 1.8670486450195312e+002 + 3.7660791015625000e+002 1.6822602844238281e+002 + 3.0041110229492187e+002 2.7713180541992187e+002 + 3.1722100830078125e+002 2.6146401977539063e+002 + 3.3513473510742187e+002 2.4458380126953125e+002 + 3.5441113281250000e+002 2.2650328063964844e+002 + 3.7448040771484375e+002 2.0804573059082031e+002 + 3.9478659057617187e+002 1.8966294860839844e+002 + 3.1634332275390625e+002 2.9670852661132812e+002 + 3.3314920043945312e+002 2.8174331665039062e+002 + 3.5168194580078125e+002 2.6535464477539062e+002 + 3.7153198242187500e+002 2.4802993774414062e+002 + 3.9209609985351562e+002 2.3040005493164062e+002 + 4.1256643676757812e+002 2.1212394714355469e+002 + 3.3142242431640625e+002 3.1585980224609375e+002 + 3.4924060058593750e+002 3.0193035888671875e+002 + 3.6815182495117187e+002 2.8664663696289062e+002 + 3.8831549072265625e+002 2.7015829467773437e+002 + 4.0866662597656250e+002 2.5254908752441406e+002 + 4.2946725463867187e+002 2.3504879760742187e+002 + 3.4650833129882812e+002 3.3457098388671875e+002 + 3.6462210083007812e+002 3.2168914794921875e+002 + 3.8407458496093750e+002 3.0726388549804687e+002 + 4.0414212036132812e+002 2.9152847290039062e+002 + 4.2460678100585937e+002 2.7481945800781250e+002 + 4.4502890014648437e+002 2.5764831542968750e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.1113698577880859e+002 1.6357449340820312e+002 + 1.2291122436523437e+002 1.4165034484863281e+002 + 1.3644914245605469e+002 1.1860313415527344e+002 + 1.5219450378417969e+002 9.5364074707031250e+001 + 1.6997375488281250e+002 7.2965614318847656e+001 + 1.9030349731445312e+002 5.1691478729248047e+001 + 1.2536482238769531e+002 1.7634202575683594e+002 + 1.3741094970703125e+002 1.5465663146972656e+002 + 1.5141896057128906e+002 1.3184400939941406e+002 + 1.6738740539550781e+002 1.0933669281005859e+002 + 1.8557466125488281e+002 8.6847579956054688e+001 + 2.0557023620605469e+002 6.5647895812988281e+001 + 1.4101351928710937e+002 1.8952091979980469e+002 + 1.5331748962402344e+002 1.6830906677246094e+002 + 1.6744911193847656e+002 1.4643350219726562e+002 + 1.8379411315917969e+002 1.2450414276123047e+002 + 2.0224324035644531e+002 1.0212133789062500e+002 + 2.2245115661621094e+002 8.1499900817871094e+001 + 1.5769918823242187e+002 2.0397569274902344e+002 + 1.7003167724609375e+002 1.8348559570312500e+002 + 1.8468145751953125e+002 1.6186503601074219e+002 + 2.0149737548828125e+002 1.4042778015136719e+002 + 2.1930650329589844e+002 1.1888777160644531e+002 + 2.3925010681152344e+002 9.8347816467285156e+001 + 1.7450898742675781e+002 2.1748254394531250e+002 + 1.8783386230468750e+002 1.9787358093261719e+002 + 2.0254502868652344e+002 1.7763798522949219e+002 + 2.1895150756835937e+002 1.5645854187011719e+002 + 2.3732089233398437e+002 1.3567562866210937e+002 + 2.5660852050781250e+002 1.1576937866210937e+002 + 1.9241796875000000e+002 2.3140776062011719e+002 + 2.0555372619628906e+002 2.1262821960449219e+002 + 2.2036996459960937e+002 1.9334136962890625e+002 + 2.3679211425781250e+002 1.7327601623535156e+002 + 2.5474868774414062e+002 1.5345164489746094e+002 + 2.7403561401367187e+002 1.3420983886718750e+002 + 2.0963447570800781e+002 2.4443675231933594e+002 + 2.2294952392578125e+002 2.2658012390136719e+002 + 2.3766198730468750e+002 2.0842362976074219e+002 + 2.5447799682617187e+002 1.8960833740234375e+002 + 2.7209036254882812e+002 1.7048693847656250e+002 + 2.9041308593750000e+002 1.5211561584472656e+002 + 2.2643389892578125e+002 2.5669570922851563e+002 + 2.4013029479980469e+002 2.4016291809082031e+002 + 2.5484764099121094e+002 2.2268322753906250e+002 + 2.7088720703125000e+002 2.0534346008300781e+002 + 2.8770697021484375e+002 1.8728942871093750e+002 + 3.0556372070312500e+002 1.6925451660156250e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.3551335144042969e+002 2.4964784240722656e+002 + 1.5658290100097656e+002 2.3251905822753906e+002 + 1.8144166564941406e+002 2.1395532226562500e+002 + 2.0932627868652344e+002 1.9624780273437500e+002 + 2.3863180541992187e+002 1.7879356384277344e+002 + 2.6800274658203125e+002 1.6409538269042969e+002 + 1.4344090270996094e+002 2.7971420288085937e+002 + 1.6559048461914062e+002 2.6230310058593750e+002 + 1.9148986816406250e+002 2.4366691589355469e+002 + 2.2058102416992187e+002 2.2518508911132812e+002 + 2.5135652160644531e+002 2.0734295654296875e+002 + 2.8241360473632812e+002 1.9097888183593750e+002 + 1.5343066406250000e+002 3.1204476928710937e+002 + 1.7755268859863281e+002 2.9465359497070312e+002 + 2.0436677551269531e+002 2.7632885742187500e+002 + 2.3440495300292969e+002 2.5738430786132812e+002 + 2.6543463134765625e+002 2.3903804016113281e+002 + 2.9824316406250000e+002 2.2079838562011719e+002 + 1.6750418090820312e+002 3.4525192260742187e+002 + 1.9157458496093750e+002 3.2897625732421875e+002 + 2.1969345092773437e+002 3.1107049560546875e+002 + 2.5033551025390625e+002 2.9208691406250000e+002 + 2.8259799194335937e+002 2.7233486938476562e+002 + 3.1540875244140625e+002 2.5341592407226563e+002 + 1.8365829467773437e+002 3.7850866699218750e+002 + 2.0901194763183594e+002 3.6394995117187500e+002 + 2.3758525085449219e+002 3.4669958496093750e+002 + 2.6920370483398438e+002 3.2770013427734375e+002 + 3.0153009033203125e+002 3.0751879882812500e+002 + 3.3321890258789062e+002 2.8807455444335937e+002 + 2.0227095031738281e+002 4.1055450439453125e+002 + 2.2836053466796875e+002 3.9702404785156250e+002 + 2.5724002075195312e+002 3.8063833618164062e+002 + 2.8834472656250000e+002 3.6240383911132812e+002 + 3.2047857666015625e+002 3.4223080444335937e+002 + 3.5221060180664062e+002 3.2155111694335937e+002 + 2.2245227050781250e+002 4.4007073974609375e+002 + 2.4849409484863281e+002 4.2730068969726562e+002 + 2.7749932861328125e+002 4.1245559692382812e+002 + 3.0844982910156250e+002 3.9442993164062500e+002 + 3.3947866821289062e+002 3.7446008300781250e+002 + 3.6959039306640625e+002 3.5358370971679687e+002 + 2.4315701293945312e+002 4.6563592529296875e+002 + 2.6886026000976562e+002 4.5435034179687500e+002 + 2.9758422851562500e+002 4.3975015258789062e+002 + 3.2719766235351562e+002 4.2246875000000000e+002 + 3.5736584472656250e+002 4.0319088745117187e+002 + 3.8560894775390625e+002 3.8256094360351562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 7.5549308776855469e+001 2.5510282897949219e+002 + 9.5836242675781250e+001 2.3881352233886719e+002 + 1.1973059082031250e+002 2.2201226806640625e+002 + 1.4624465942382812e+002 2.0628733825683594e+002 + 1.7489663696289062e+002 1.9117424011230469e+002 + 2.0404061889648437e+002 1.7773648071289062e+002 + 8.1378135681152344e+001 2.8759286499023437e+002 + 1.0215756988525391e+002 2.7070837402343750e+002 + 1.2634820556640625e+002 2.5430567932128906e+002 + 1.5432931518554687e+002 2.3658752441406250e+002 + 1.8354627990722656e+002 2.2085206604003906e+002 + 2.1394161987304687e+002 2.0635720825195312e+002 + 9.0476028442382813e+001 3.2169039916992187e+002 + 1.1155056762695312e+002 3.0557974243164063e+002 + 1.3657116699218750e+002 2.8833795166015625e+002 + 1.6505255126953125e+002 2.7058840942382812e+002 + 1.9562532043457031e+002 2.5342010498046875e+002 + 2.2647079467773437e+002 2.3749620056152344e+002 + 1.0294146728515625e+002 3.5746154785156250e+002 + 1.2462596893310547e+002 3.4204507446289062e+002 + 1.5069268798828125e+002 3.2453408813476562e+002 + 1.7949212646484375e+002 3.0626293945312500e+002 + 2.1045092773437500e+002 2.8828652954101562e+002 + 2.4189447021484375e+002 2.7066619873046875e+002 + 1.1947385406494141e+002 3.9272677612304687e+002 + 1.4178750610351562e+002 3.7830291748046875e+002 + 1.6763095092773437e+002 3.6135079956054687e+002 + 1.9706710815429687e+002 3.4304632568359375e+002 + 2.2760614013671875e+002 3.2412661743164062e+002 + 2.5916567993164062e+002 3.0504159545898437e+002 + 1.3887268066406250e+002 4.2647601318359375e+002 + 1.6163279724121094e+002 4.1279507446289062e+002 + 1.8783302307128906e+002 3.9666445922851562e+002 + 2.1669651794433594e+002 3.7837326049804687e+002 + 2.4670425415039062e+002 3.5875109863281250e+002 + 2.7713192749023437e+002 3.3865835571289062e+002 + 1.6088009643554687e+002 4.5691171264648437e+002 + 1.8359988403320312e+002 4.4445858764648437e+002 + 2.0984178161621094e+002 4.2885153198242187e+002 + 2.3796560668945312e+002 4.1104025268554687e+002 + 2.6733956909179687e+002 3.9100515747070312e+002 + 2.9572573852539062e+002 3.7066073608398437e+002 + 1.8340353393554687e+002 4.8362966918945312e+002 + 2.0652793884277344e+002 4.7168350219726562e+002 + 2.3245803833007812e+002 4.5678906250000000e+002 + 2.5942431640625000e+002 4.3894961547851562e+002 + 2.8705108642578125e+002 4.1969241333007812e+002 + 3.1368389892578125e+002 3.9893399047851562e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 4.8649360656738281e+001 1.6148712158203125e+002 + 6.8872444152832031e+001 1.3572279357910156e+002 + 9.2741775512695313e+001 1.1114631652832031e+002 + 1.2068060302734375e+002 8.8769126892089844e+001 + 1.5095973205566406e+002 6.8475555419921875e+001 + 1.8257330322265625e+002 5.2207054138183594e+001 + 5.5437900543212891e+001 1.8895469665527344e+002 + 7.5169265747070313e+001 1.6376956176757812e+002 + 9.9380348205566406e+001 1.3924258422851562e+002 + 1.2757296752929687e+002 1.1539561462402344e+002 + 1.5775154113769531e+002 9.4928596496582031e+001 + 1.8981935119628906e+002 7.7931488037109375e+001 + 6.4469284057617188e+001 2.1881651306152344e+002 + 8.4503616333007813e+001 1.9344508361816406e+002 + 1.0859510040283203e+002 1.6914207458496094e+002 + 1.3667056274414062e+002 1.4538822937011719e+002 + 1.6757249450683594e+002 1.2416504669189453e+002 + 1.9967625427246094e+002 1.0632071685791016e+002 + 7.7409881591796875e+001 2.4809570312500000e+002 + 9.7357780456542969e+001 2.2504957580566406e+002 + 1.2165764617919922e+002 2.0039739990234375e+002 + 1.4913972473144531e+002 1.7733862304687500e+002 + 1.7976629638671875e+002 1.5577418518066406e+002 + 2.1073934936523437e+002 1.3694134521484375e+002 + 9.3488700866699219e+001 2.7789456176757812e+002 + 1.1338587951660156e+002 2.5581047058105469e+002 + 1.3751210021972656e+002 2.3277359008789062e+002 + 1.6463037109375000e+002 2.0945904541015625e+002 + 1.9365110778808594e+002 1.8812948608398438e+002 + 2.2422030639648437e+002 1.6843539428710937e+002 + 1.1230362701416016e+002 3.0624664306640625e+002 + 1.3204307556152344e+002 2.8535211181640625e+002 + 1.5554772949218750e+002 2.6321438598632812e+002 + 1.8140420532226562e+002 2.4122767639160156e+002 + 2.0968305969238281e+002 2.1960566711425781e+002 + 2.3807707214355469e+002 2.0002363586425781e+002 + 1.3187847900390625e+002 3.3155255126953125e+002 + 1.5156361389160156e+002 3.1194360351562500e+002 + 1.7417019653320312e+002 2.9168200683593750e+002 + 1.9911006164550781e+002 2.7023480224609375e+002 + 2.2539184570312500e+002 2.4967605590820312e+002 + 2.5235554504394531e+002 2.3008103942871094e+002 + 1.5211508178710937e+002 3.5375372314453125e+002 + 1.7130648803710937e+002 3.3589419555664062e+002 + 1.9326776123046875e+002 3.1673748779296875e+002 + 2.1658116149902344e+002 2.9676184082031250e+002 + 2.4127964782714844e+002 2.7649050903320312e+002 + 2.6576745605468750e+002 2.5722906494140625e+002 + <_ type_id="opencv-matrix"> + 48 + 1 +
"2d"
+ + 1.4323484802246094e+002 1.8785659790039062e+002 + 1.6823933410644531e+002 1.5935469055175781e+002 + 1.9958100891113281e+002 1.2952050781250000e+002 + 2.3552172851562500e+002 1.0163740539550781e+002 + 2.7441351318359375e+002 7.6696540832519531e+001 + 3.1425802612304687e+002 5.6747520446777344e+001 + 1.6160871887207031e+002 2.2035722351074219e+002 + 1.8763900756835937e+002 1.9323876953125000e+002 + 2.1958572387695312e+002 1.6448460388183594e+002 + 2.5637075805664062e+002 1.3648490905761719e+002 + 2.9611550903320312e+002 1.1163502502441406e+002 + 3.3574343872070312e+002 9.0622886657714844e+001 + 1.8300276184082031e+002 2.5344281005859375e+002 + 2.1037881469726562e+002 2.2790597534179687e+002 + 2.4249015808105469e+002 2.0163201904296875e+002 + 2.7934292602539062e+002 1.7487947082519531e+002 + 3.1826248168945312e+002 1.4960942077636719e+002 + 3.5713623046875000e+002 1.2842076110839844e+002 + 2.0634449768066406e+002 2.8574951171875000e+002 + 2.3363224792480469e+002 2.6351388549804687e+002 + 2.6626834106445312e+002 2.3862466430664062e+002 + 3.0237854003906250e+002 2.1350553894042969e+002 + 3.3988421630859375e+002 1.8941194152832031e+002 + 3.7672085571289062e+002 1.6748908996582031e+002 + 2.2977026367187500e+002 3.1555746459960937e+002 + 2.5753848266601562e+002 2.9556286621093750e+002 + 2.8975900268554688e+002 2.7363162231445312e+002 + 3.2450527954101562e+002 2.5057597351074219e+002 + 3.6024685668945312e+002 2.2761793518066406e+002 + 3.9465350341796875e+002 2.0551646423339844e+002 + 2.5332383728027344e+002 3.4197607421875000e+002 + 2.8044512939453125e+002 3.2515847778320313e+002 + 3.1130630493164062e+002 3.0510897827148437e+002 + 3.4466235351562500e+002 2.8341259765625000e+002 + 3.7763238525390625e+002 2.6172109985351562e+002 + 4.0911401367187500e+002 2.4132922363281250e+002 + 2.7443826293945313e+002 3.6463940429687500e+002 + 3.0142022705078125e+002 3.4937396240234375e+002 + 3.3101867675781250e+002 3.3145782470703125e+002 + 3.6150836181640625e+002 3.1210357666015625e+002 + 3.9204998779296875e+002 2.9163595581054687e+002 + 4.2138192749023437e+002 2.7150659179687500e+002 + 2.9359359741210937e+002 3.8332373046875000e+002 + 3.1955047607421875e+002 3.6954293823242187e+002 + 3.4706188964843750e+002 3.5349444580078125e+002 + 3.7550402832031250e+002 3.3593304443359375e+002 + 4.0373101806640625e+002 3.1739349365234375e+002 + 4.3048049926757812e+002 2.9821621704101562e+002
+ + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0. + <_ type_id="opencv-matrix"> + 48 + 1 +
"3d"
+ + 0. 0. 0. 0. 80. 0. 0. 160. 0. 0. 240. 0. 0. 320. 0. 0. 400. 0. 80. + 0. 0. 80. 80. 0. 80. 160. 0. 80. 240. 0. 80. 320. 0. 80. 400. 0. + 160. 0. 0. 160. 80. 0. 160. 160. 0. 160. 240. 0. 160. 320. 0. 160. + 400. 0. 240. 0. 0. 240. 80. 0. 240. 160. 0. 240. 240. 0. 240. 320. + 0. 240. 400. 0. 320. 0. 0. 320. 80. 0. 320. 160. 0. 320. 240. 0. + 320. 320. 0. 320. 400. 0. 400. 0. 0. 400. 80. 0. 400. 160. 0. 400. + 240. 0. 400. 320. 0. 400. 400. 0. 480. 0. 0. 480. 80. 0. 480. 160. + 0. 480. 240. 0. 480. 320. 0. 480. 400. 0. 560. 0. 0. 560. 80. 0. + 560. 160. 0. 560. 240. 0. 560. 320. 0. 560. 400. 0.
+ + 704 576 + + 704 576 +
diff --git a/modules/ccalib/tutorial/img/disparity.jpg b/modules/ccalib/tutorial/img/disparity.jpg new file mode 100644 index 000000000..ea83cc9ba Binary files /dev/null and b/modules/ccalib/tutorial/img/disparity.jpg differ diff --git a/modules/ccalib/tutorial/img/imgs.jpg b/modules/ccalib/tutorial/img/imgs.jpg new file mode 100644 index 000000000..5ff063e25 Binary files /dev/null and b/modules/ccalib/tutorial/img/imgs.jpg differ diff --git a/modules/ccalib/tutorial/img/lines.jpg b/modules/ccalib/tutorial/img/lines.jpg new file mode 100644 index 000000000..69ff63e9f Binary files /dev/null and b/modules/ccalib/tutorial/img/lines.jpg differ diff --git a/modules/ccalib/tutorial/img/pattern_img.jpg b/modules/ccalib/tutorial/img/pattern_img.jpg new file mode 100644 index 000000000..d50e8ac0b Binary files /dev/null and b/modules/ccalib/tutorial/img/pattern_img.jpg differ diff --git a/modules/ccalib/tutorial/img/pointCloud.jpg b/modules/ccalib/tutorial/img/pointCloud.jpg new file mode 100644 index 000000000..35c92c9de Binary files /dev/null and b/modules/ccalib/tutorial/img/pointCloud.jpg differ diff --git a/modules/ccalib/tutorial/img/random_pattern.jpg b/modules/ccalib/tutorial/img/random_pattern.jpg new file mode 100644 index 000000000..eb56ca29c Binary files /dev/null and b/modules/ccalib/tutorial/img/random_pattern.jpg differ diff --git a/modules/ccalib/tutorial/img/sample.jpg b/modules/ccalib/tutorial/img/sample.jpg new file mode 100644 index 000000000..6325a58c6 Binary files /dev/null and b/modules/ccalib/tutorial/img/sample.jpg differ diff --git a/modules/ccalib/tutorial/img/sample_rec_cyl.jpg b/modules/ccalib/tutorial/img/sample_rec_cyl.jpg new file mode 100644 index 000000000..4f1699fa0 Binary files /dev/null and b/modules/ccalib/tutorial/img/sample_rec_cyl.jpg differ diff --git a/modules/ccalib/tutorial/img/sample_rec_log.jpg b/modules/ccalib/tutorial/img/sample_rec_log.jpg new file mode 100644 index 000000000..9793404d1 Binary files /dev/null and b/modules/ccalib/tutorial/img/sample_rec_log.jpg differ diff --git a/modules/ccalib/tutorial/img/sample_rec_per.jpg b/modules/ccalib/tutorial/img/sample_rec_per.jpg new file mode 100644 index 000000000..73f4c10cf Binary files /dev/null and b/modules/ccalib/tutorial/img/sample_rec_per.jpg differ diff --git a/modules/ccalib/tutorial/img/sample_rec_ste.jpg b/modules/ccalib/tutorial/img/sample_rec_ste.jpg new file mode 100644 index 000000000..8e374e786 Binary files /dev/null and b/modules/ccalib/tutorial/img/sample_rec_ste.jpg differ diff --git a/modules/ccalib/tutorial/multi_camera_tutorial.markdown b/modules/ccalib/tutorial/multi_camera_tutorial.markdown new file mode 100644 index 000000000..d94da981b --- /dev/null +++ b/modules/ccalib/tutorial/multi_camera_tutorial.markdown @@ -0,0 +1,45 @@ +Multi-camera Calibration {#tutorial_multi_camera_main} +==================================== + +This tutorial will show how to use the multiple camera calibration toolbox. This toolbox is based on the usage of "random" pattern calibration object, so the tutorial is mainly two parts: an introduction to "random" pattern and multiple camera calibration. + +Random Pattern Calibration Object +------------------------------- +The random pattern is an image that is randomly generated. It is "random" so that it has many feature points. After generating it, one print it out and use it as a calibration object. The following two images are random pattern and a photo taken for it. + +![image](img/random_pattern.jpg) +![image](img/pattern_img.jpg) + +To generate a random pattern, use the class ```cv::randpattern::RandomPatternGenerator``` in ```ccalib``` module. Run it as +``` +cv::randpattern::RandomPatternGenerator generator(width, height); +generator.generatePattern(); +pattern = generator.getPattern(); +``` +Here ```width``` and ```height``` are width and height of pattern image. After getting the pattern, print it out and take some photos of it. + +Now we can use these images to calibrate camera. First, ```objectPoints``` and ```imagePoints``` need to be detected. Use class ```cv::randpattern::RandomPatternCornerFinder``` to detect them. A sample code can be +``` +cv::randpattern::RandomPatternCornerFinder finder(patternWidth, patternHeight, nMiniMatches); +finder.loadPattern(pattern); +finder.computeObjectImagePoints(vecImg); +vector objectPoints = finder.getObjectPoints(); +vector imagePoints = finder.getImagePoints(); +``` +Here variable ```patternWidth``` and ```patternHeight``` are physical pattern width and height with some user defined unit. ```vecImg``` is a vector of images that stores calibration images. + +Second, use calibration functions like ```cv::calibrateCamera``` or ```cv::omnidir::calibrate``` to calibrate camera. + +Multiple Cameras Calibration +------------------------------- +Now we move to multiple camera calibration, so far this toolbox must use random pattern object. + +To calibrate multiple cameras, we first need to take some photos of random pattern. Of cause, to calibrate the extrinsic parameters, one pattern need to be viewed by multiple cameras (at least two) at the same time. Another thing is that to help the program know which camera and which pattern the photo is taken, the image file should be named as "cameraIdx-timestamp.*". Photos with same timestamp means that they are the same object taken by several cameras. In addition, cameraIdx should start from 0. Some examples of files names are "0-129.png", "0-187.png", "1-187", "2-129". + +Then, we can run multiple cameras calibration as +``` +cv::multicalib::MultiCameraCalibration multiCalib(cameraType, nCamera, inputFilename,patternWidth, patternHeight, showFeatureExtraction, nMiniMatches); +multiCalib.run(); +multiCalib.writeParameters(outputFilename); +``` +Here ```cameraType``` indicates the camera type, ```multicalib::MultiCameraCalibration::PINHOLE``` and ```multicalib::MultiCameraCalibration::OMNIDIRECTIONAL``` are supported. For omnidirectional camera, you can refer to ```cv::omnidir``` module for detail. ```nCamera``` is the number of camers. ```inputFilename``` is the name of a file generated by ```imagelist_creator``` from ```opencv/sample```. It stores names of random pattern and calibration images, the first file name is the name of random pattern. ```patternWidth``` and ```patternHeight``` are physical width and height of pattern. ```showFeatureExtraction``` is a flags to indicate whether show feature extraction process. ```nMiniMatches``` is a minimal points that should be detected in each frame, otherwise this frame will be abandoned. ```outputFilename``` is a xml file name to store parameters. diff --git a/modules/ccalib/tutorial/omnidir_tutorial.markdown b/modules/ccalib/tutorial/omnidir_tutorial.markdown new file mode 100644 index 000000000..388fcb604 --- /dev/null +++ b/modules/ccalib/tutorial/omnidir_tutorial.markdown @@ -0,0 +1,185 @@ +Omnidirectional Cameara Calibration {#tutorial_omnidir_calib_main} +====================== + +This module includes calibration, rectification and stereo reconstruction of omnidirectional camearas. The camera model is described in this paper: + +*C. Mei and P. Rives, Single view point omnidirectional camera calibration from planar grids, in ICRA 2007.* + +The model is capable of modeling catadioptric cameras and fisheye cameras, which may both have very large field of view. + +The implementation of the calibration part is based on Li's calibration toolbox: + +*B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System Calibration Toolbox Using A Feature Descriptor-Based Calibration Pattern", in IROS 2013.* + +This tutorial will introduce the following parts of omnidirectional camera calibartion module: + +- calibrate a single camera. +- calibrate a stereo pair of cameras. +- rectify images so that large distoration is removed. +- reconstruct 3D from two stereo images, with large filed of view. +- comparison with fisheye model in opencv/calib3d/ + +Single Camera Calibration +--------------------- + +The first step to calibrate camera is to get a calibration pattern and take some photos. Several kinds of patterns are supported by OpenCV, like checkerborad and circle grid. A new pattern named random pattern can also be used, you can refer to opencv_contrib/modules/ccalib for more details. + +Next step is to extract corners from calibration pattern. For checkerboard, use OpenCV function ```cv::findChessboardCorners```; for circle grid, use ```cv::findCirclesGrid```, for random pattern, use the ```randomPatternCornerFinder``` class in opencv_contrib/modules/ccalib/src/randomPattern.hpp. Save the positions of corners in images in a variable like ```imagePoints```. The type of ```imagePoints``` may be ```std::vector>```, the first vector stores corners in each frame, the second vector stores corners in an individual frame. The type can also be ```std::vector``` where the ```cv::Mat``` is ```CV_32FC2```. + +Also, the corresponding 3D points in world (pattern) coordinate are required. You can compute they for yourself if you know the physical size of your pattern. Save 3D points in ```objectPoints```, similar to ```imagePoints```, it can be ```std::vector>``` or ```std::vector``` where ```cv::Mat``` is of type ```CV_32FC3```. Note the size of ```objectPoints``` and ```imagePoints``` must be the same because they are corresponding to each other. + +Another thing you should input is the size of images. The file opencv_contrib/modules/ccalib/tutorial/data/omni_calib_data.xml stores an example of objectPoints, imagePoints and imageSize. Use the following code to load them: + +``` +cv::FileStorage fs("omni_calib_data.xml", cv::FileStorage::READ); +std::vector objectPoints, imagePoints; +cv::Size imgSize; +fs["objectPoints"] >> objectPoints; +fs["imagePoints"] >> imagePoints; +fs["imageSize"] >> imgSize; +``` + +Then define some variables to store the output parameters and run the calibration function like: + +``` +cv::Mat K, xi, D, idx; +int flags = 0; +cv::TermCriteria critia(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 200, 0.0001); +std::vector rvecs, tvecs; +double rms = cv::omnidir::calibrate(objectPoints, imagePoints, imgSize, K, xi, D, rvecs, tvecs, flags, critia, idx); +``` + +```K```, ```xi```, ```D``` are internal parameters and ```rvecs```, ```tvecs``` are external parameters that store the pose of patterns. All of them have depth of ```CV_64F```. The ```xi``` is a single value variable of Mei's model. ```idx``` is a ```CV_32S``` Mat that stores indices of images that are really used in calibration. This is due to some images are failed in the initialization step so they are not used in the final optimization. The returned value *rms* is the root mean square of reprojection errors. + +The calibration supports some features, *flags* is a enumeration for some features, including: + +- cv::omnidir::CALIB_FIX_SKEW +- cv::omnidir::CALIB_FIX_K1 +- cv::omnidir::CALIB_FIX_K2 +- cv::omnidir::CALIB_FIX_P1 +- cv::omnidir::CALIB_FIX_P2 +- cv::omnidir::CALIB_FIX_XI +- cv::omnidir::CALIB_FIX_GAMMA +- cv::omnidir::CALIB_FIX_CENTER + +Your can specify ```flags``` to fix parameters during calibration. Use 'plus' operator to set multiple features. For example, ```CALIB_FIX_SKEW+CALIB_FIX_K1``` means fixing skew and K1. + +```critia``` is the stopping critia during optimization, set it to be, for example, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 200, 0.0001), which means using 200 iterations and stopping when relative change is smaller than 0.0001. + +Stereo Calibration +-------------------------- +Stereo calibration is to calibrate two cameras together. The output parameters include camera parameters of two cameras and the relative pose of them. To recover the relative pose, two cameras must observe the same pattern at the same time, so the ```objectPoints``` of two cameras are the same. + +Now detect image corners for both cameras as discussed above to get ```imagePoints1``` and ```imagePoints2```. Then compute the shared ```objectPoints```. + +An example of of stereo calibration data is stored in opencv_contrib/modules/ccalib/tutorial/data/omni_stereocalib_data.xml. Load the data by +``` +cv::FileStorage fs("omni_stereocalib_data.xml", cv::FileStorage::READ); +std::vector objectPoints, imagePoints1, imagePoints2; +cv::Size imgSize1, imgSize2; +fs["objectPoints"] >> objectPoints; +fs["imagePoints1"] >> imagePoints1; +fs["imagePoints2"] >> imagePoints2; +fs["imageSize1"] >> imgSize1; +fs["imageSize2"] >> imgSize2; +``` + +Then do stereo calibration by +``` +cv::Mat K1, K2, xi1, xi2, D1, D2; +int flags = 0; +cv::TermCriteria critia(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 200, 0.0001); +std::vector rvecsL, tvecsL; +cv::Mat rvec, tvec; +double rms = cv::omnidir::calibrate(objectPoints, imagePoints1, imagePoints2, imgSize1, imgSize2, K1, xi1, D1, K2, xi2, D2, rvec, tvec, rvecsL, tvecsL, flags, critia, idx); +``` +Here ```rvec``` and ```tvec``` are the transform between the first and the second camera. ```rvecsL``` and ```tvecsL``` are the transforms between patterns and the first camera. + +Image Rectificaiton +--------------------------- + +Omnidirectional images have very large distortion, so it is not compatible with human's eye balls. For better view, rectification can be applied if camera parameters are known. Here is an example of omnidirectional image of 360 degrees of horizontal field of view. + +![image](img/sample.jpg) + +After rectification, a perspective like view is generated. Here is one example to run image rectification in this module: + +``` +cv::omnidir::undistortImage(distorted, undistorted, K, D, xi, int flags, Knew, new_size) +``` + +The variable *distorted* and *undistorted* are the origional image and rectified image perspectively. *K*, *D*, *xi* are camera parameters. *KNew* and *new_size* are the camera matrix and image size for rectified image. *flags* is the rectification type, it can be: + +- RECTIFY_PERSPECTIVE: rectify to perspective images, which will lose some filed of view. +- RECTIFY_CYLINDRICAL: rectify to cylindrical images that preserve all view. +- RECTIFY_STEREOGRAPHIC: rectify to stereographic images that may lose a little view. +- RECTIFY_LONGLATI: rectify to longitude-latitude map like a world map of the earth. This rectification can be used to stereo reconstruction but may not be friendly for view. This map is described in paper: +*Li S. Binocular spherical stereo[J]. Intelligent Transportation Systems, IEEE Transactions on, 2008, 9(4): 589-600.* + +The following four images are four types of rectified images discribed above: + +![image](img/sample_rec_per.jpg) + +![image](img/sample_rec_cyl.jpg) + +![image](img/sample_rec_ste.jpg) + +![image](img/sample_rec_log.jpg) + +It can be observed that perspective rectified image perserves only a little field of view and is not goodlooking. Cylindrical rectification preserves all field of view and scene is unnatural only in the middle of bottom. The distortion of stereographic in the middle of bottom is smaller than cylindrical but the distortion of other places are larger, and it can not preserve all field of view. For images with very large distortion, the longitude-latitude rectification does not give a good result, but it is available to make epipolar constraint in a line so that stereo matching can be applied in omnidirectional images. + +**Note**: To have a better result, you should carefully choose ```Knew``` and it is related to your camera. In general, a smaller focal length leads to a smaller field of view and vice versa. Here are recommonded settings. + +For RECTIFY_PERSPECTIVE +``` +Knew = Matx33f(new_size.width/4, 0, new_size.width/2, + 0, new_size.height/4, new_size.height/2, + 0, 0, 1); +``` +For RECTIFY_CYLINDRICAL, RECTIFY_STEREOGRAPHIC, RECTIFY_LONGLATI +``` +Knew = Matx33f(new_size.width/3.1415, 0, 0, + 0, new_size.height/3.1415, 0, + 0, 0, 1); +``` + +Maybe you need to change ```(u0, v0)``` to get a better view. + +Stereo Reconstruction +------------------------------ +Stereo reconstruction is to reconstruct 3D points from a calibrated stereo camera pair. It is a basic problem of computer vison. However, for omnidirectional camera, it is not very popular because of the large distortion make it a little difficult. Conventional methods rectify images to perspective ones and do stereo reconstruction in perspective images. However, the last section shows that recifying to perspective images lose too much field of view, which waste the advantage of omnidirectional camera, i.e. large field of view. + +The first step of stereo reconstruction is stereo rectification so that epipolar lines are horizontal lines. Here, we use longitude-latitude rectification to preserve all filed of view, or perspective rectification which is available but is not recommended. The second step is stereo matching to get a disparity map. At last, 3D points can be generated from disparity map. + +The API of stereo reconstruction for omnidrectional camera is ```omnidir::stereoReconstruct```. Here we use an example to show how it works. + +First, calibrate a stereo pair of cameras as describe above and get parameters like ```K1```, ```D1```, ```xi1```, ```K2```, ```D2```, ```xi2```, ```rvec```, ```tvec```. Then read two images from the first and second camera respectively, for instance, ```image1``` and ```image2```, which are shown below. + +![image](img/imgs.jpg) + +Second, run ```omnidir::stereoReconstruct``` like: +``` +cv::Size imgSize = img1.size(); +int numDisparities = 16*5; +int SADWindowSize = 5; +cv::Mat disMap; +int flag = cv::omnidir::RECTIFY_LONGLATI; +int pointType = omnidir::XYZRGB; +// the range of theta is (0, pi) and the range of phi is (0, pi) +cv::Matx33d KNew(imgSize.width / 3.1415, 0, 0, 0, imgSize.height / 3.1415, 0, 0, 0, 1); +Mat imageRec1, imageRec2, pointCloud; + +cv::omnidir::stereoReconstruct(img1, img2, K1, D1, xi1, K2, D2, xi2, R, T, flag, numDisparities, SADWindowSize, imageRec1, imageRec2, disMap, imgSize, KNew, pointCloud); +``` + +Here variable ```flag``` indicates the recectify type, only ```RECTIFY_LONGLATI```(recommend) and ```RECTIFY_PERSPECTIVE``` make sense. ```numDisparities``` is the max disparity value and ```SADWindowSize``` is the window size of ```cv::StereoSGBM```. ```pointType``` is a flag to define the type of point cloud, ```omnidir::XYZRGB``` each point is a 6-dimensional vector, the first three elements are xyz coordinate, the last three elements are rgb color information. Another type ```omnidir::XYZ``` means each point is 3-dimensional and has only xyz coordiante. + +Moreover, ```imageRec1``` and ```imagerec2``` are rectified versions of the first and second images. The epipolar lines of them have the same y-coordinate so that stereo matching becomes easy. Here are an example of them: + +![image](img/lines.jpg) +It can be observed that they are well aligned. The variable ```disMap``` is the disparity map computed by ```cv::StereoSGBM``` from ```imageRec1``` and ```imageRec2```. The disparity map of the above two images is: + +![image](img/disparity.jpg) + +After we have disparity, we can compute 3D location for each pixel. The point cloud is stored in ```pointCloud```, which is a 3-channel or 6-channel ```cv::Mat```. We show the point cloud in the following image. +![image](img/pointCloud.jpg) diff --git a/modules/cvv/src/view/linematchview.cpp b/modules/cvv/src/view/linematchview.cpp index b3d03d7e2..ca4c711c9 100644 --- a/modules/cvv/src/view/linematchview.cpp +++ b/modules/cvv/src/view/linematchview.cpp @@ -45,7 +45,7 @@ LineMatchView::LineMatchView(std::vector leftKeyPoints, qtutil::MatchScene *matchscene_ptr = matchscene.get(); int updateAreaDelay=std::min(std::max(matches.size(), std::max(leftKeyPoints.size(), - rightKeyPoints.size()))/10,50lu); + rightKeyPoints.size()))/(std::size_t)10,(std::size_t)50); matchscene_ptr->getLeftImage().setUpdateAreaDelay(updateAreaDelay); matchscene_ptr->getRightImage().setUpdateAreaDelay(updateAreaDelay); diff --git a/modules/cvv/src/view/pointmatchview.cpp b/modules/cvv/src/view/pointmatchview.cpp index 1bd490a3e..a6ac4696b 100644 --- a/modules/cvv/src/view/pointmatchview.cpp +++ b/modules/cvv/src/view/pointmatchview.cpp @@ -30,7 +30,7 @@ PointMatchView::PointMatchView(std::vector leftKeyPoints, auto matchmnt = util::make_unique(matches); qtutil::MatchScene *matchscene_ptr = matchscene.get(); - int updateAreaDelay=std::min(std::max(matches.size(),std::max(leftKeyPoints.size(),rightKeyPoints.size()))/10,50lu); + int updateAreaDelay=std::min(std::max(matches.size(),std::max(leftKeyPoints.size(),rightKeyPoints.size()))/(std::size_t)10,(std::size_t)50); matchscene_ptr->getLeftImage().setUpdateAreaDelay(updateAreaDelay); matchscene_ptr->getRightImage().setUpdateAreaDelay(updateAreaDelay); diff --git a/modules/cvv/src/view/translationsmatchview.cpp b/modules/cvv/src/view/translationsmatchview.cpp index 6ef3ff660..804c9e709 100644 --- a/modules/cvv/src/view/translationsmatchview.cpp +++ b/modules/cvv/src/view/translationsmatchview.cpp @@ -39,7 +39,7 @@ TranslationMatchView::TranslationMatchView( auto keyPointmnt = util::make_unique(allkeypoints); qtutil::MatchScene *matchscene_ptr = matchscene.get(); - int updateAreaDelay=std::min(std::max(matches.size(),std::max(leftKeyPoints.size(),rightKeyPoints.size()))/10,50lu); + int updateAreaDelay=std::min(std::max(matches.size(),std::max(leftKeyPoints.size(),rightKeyPoints.size()))/(std::size_t)10,(std::size_t)50); matchscene_ptr->getLeftImage().setUpdateAreaDelay(updateAreaDelay); matchscene_ptr->getRightImage().setUpdateAreaDelay(updateAreaDelay); diff --git a/modules/datasets/include/opencv2/datasets/dataset.hpp b/modules/datasets/include/opencv2/datasets/dataset.hpp index 43540578b..ccf2b6649 100644 --- a/modules/datasets/include/opencv2/datasets/dataset.hpp +++ b/modules/datasets/include/opencv2/datasets/dataset.hpp @@ -477,6 +477,27 @@ To run benchmark execute: ./opencv/build/bin/example_datasets_tr_svt_benchmark -p=/home/user/path_to_unpacked_folders/svt/svt1/ ~~~ +@defgroup datasets_track Tracking + +### VOT 2015 Database + +Implements loading dataset: + +"VOT 2015 dataset comprises 60 short sequences showing various objects in challenging backgrounds. +The sequences were chosen from a large pool of sequences including the ALOV dataset, OTB2 dataset, +non-tracking datasets, Computer Vision Online, Professor Bob Fisher’s Image Database, Videezy, +Center for Research in Computer Vision, University of Central Florida, USA, NYU Center for Genomics +and Systems Biology, Data Wrangling, Open Access Directory and Learning and Recognition in Vision +Group, INRIA, France. The VOT sequence selection protocol was applied to obtain a representative +set of challenging sequences.": + +Usage: +-# From link above download dataset file: `vot2015.zip` +-# Unpack `vot2015.zip` into folder: `VOT2015/` +-# To load data run: +~~~ +./opencv/build/bin/example_datasets_track_vot -p=/home/user/path_to_unpacked_files/VOT2015/ +~~~ @} */ diff --git a/modules/datasets/include/opencv2/datasets/track_vot.hpp b/modules/datasets/include/opencv2/datasets/track_vot.hpp new file mode 100644 index 000000000..6249f0289 --- /dev/null +++ b/modules/datasets/include/opencv2/datasets/track_vot.hpp @@ -0,0 +1,96 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2014, Itseez Inc, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Itseez Inc 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. +// +//M*/ + +#ifndef OPENCV_DATASETS_TRACK_VOT_HPP +#define OPENCV_DATASETS_TRACK_VOT_HPP + +#include +#include + +#include "opencv2/datasets/dataset.hpp" +#include "opencv2/datasets/util.hpp" + +using namespace std; + +namespace cv +{ +namespace datasets +{ + +//! @addtogroup datasets_track +//! @{ + +struct TRACK_votObj : public Object +{ + int id; + std::string imagePath; + vector gtbb; +}; + +class CV_EXPORTS TRACK_vot : public Dataset +{ +public: + static Ptr create(); + + virtual void load(const std::string &path) = 0; + + virtual int getDatasetsNum() = 0; + + virtual int getDatasetLength(int id) = 0; + + virtual bool initDataset(int id) = 0; + + virtual bool getNextFrame(Mat &frame) = 0; + + virtual vector getGT() = 0; + +protected: + vector > > data; + int activeDatasetID; + int frameCounter; +}; + +//! @} + +} +} + +#endif diff --git a/modules/datasets/samples/track_vot.cpp b/modules/datasets/samples/track_vot.cpp new file mode 100644 index 000000000..4b5937604 --- /dev/null +++ b/modules/datasets/samples/track_vot.cpp @@ -0,0 +1,99 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2014, Itseez Inc, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Itseez Inc 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. +// +//M*/ + +#include "opencv2/datasets/track_vot.hpp" +#include +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace cv; +using namespace cv::datasets; + +int main(int argc, char *argv[]) +{ + const char *keys = + "{ help h usage ? | | show this message }" + "{ path p |true| path to folder with dataset }" + "{ datasetID id |1| Dataset ID}"; + CommandLineParser parser(argc, argv, keys); + string path(parser.get("path")); + int datasetID(parser.get("datasetID")); + if (parser.has("help") || path == "true") + { + parser.printMessage(); + getchar(); + return -1; + } + + Ptr dataset = TRACK_vot::create(); + dataset->load(path); + printf("Datasets number: %d\n", dataset->getDatasetsNum()); + for (int i = 1; i <= dataset->getDatasetsNum(); i++) + printf("\tDataset #%d size: %d\n", i, dataset->getDatasetLength(i)); + + dataset->initDataset(datasetID); + + for (int i = 0; i < dataset->getDatasetLength(datasetID); i++) + { + Mat frame; + if (!dataset->getNextFrame(frame)) + break; + //Draw Ground Truth BB + vector gtPoints = dataset->getGT(); + for (int j = 0; j < (int)(gtPoints.size()-1); j++) + line(frame, gtPoints[j], gtPoints[j + 1], Scalar(0, 255, 0), 2); + line(frame, gtPoints[0], gtPoints[(int)(gtPoints.size()-1)], Scalar(0, 255, 0), 2); + + imshow("VOT 2015 DATASET TEST...", frame); + waitKey(100); + } + + getchar(); + return 0; +} \ No newline at end of file diff --git a/modules/datasets/src/track_vot.cpp b/modules/datasets/src/track_vot.cpp new file mode 100644 index 000000000..64e32f2e9 --- /dev/null +++ b/modules/datasets/src/track_vot.cpp @@ -0,0 +1,236 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2014, Itseez Inc, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Itseez Inc 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. +// +//M*/ + +#include "opencv2/datasets/track_vot.hpp" + +#include +#include +#include + +using namespace std; + +namespace cv +{ + namespace datasets + { + + class TRACK_votImpl : public TRACK_vot + { + public: + //Constructor + TRACK_votImpl() + { + activeDatasetID = 1; + frameCounter = 0; + } + //Destructor + virtual ~TRACK_votImpl() {} + + //Load Dataset + virtual void load(const string &path); + + protected: + virtual int getDatasetsNum(); + + virtual int getDatasetLength(int id); + + virtual bool initDataset(int id); + + virtual bool getNextFrame(Mat &frame); + + virtual vector getGT(); + + void loadDataset(const string &path); + + string numberToString(int number); + }; + + void TRACK_votImpl::load(const string &path) + { + loadDataset(path); + } + + string TRACK_votImpl::numberToString(int number) + { + string out; + char numberStr[9]; + sprintf(numberStr, "%u", number); + for (unsigned int i = 0; i < 8 - strlen(numberStr); ++i) + { + out += "0"; + } + out += numberStr; + return out; + } + + inline bool fileExists(const std::string& name) + { + struct stat buffer; + return (stat(name.c_str(), &buffer) == 0); + } + + void TRACK_votImpl::loadDataset(const string &rootPath) + { + string nameListPath = rootPath + "/list.txt"; + ifstream namesList(nameListPath.c_str()); + vector datasetsLengths; + string datasetName; + + if (namesList.is_open()) + { + int currDatasetID = 0; + + //All datasets/folders loop + while (getline(namesList, datasetName)) + { + currDatasetID++; + vector > objects; + + //All frames/images loop + Ptr currDataset(new TRACK_votObj); + + //Open dataset's ground truth file + string gtListPath = rootPath + "/" + datasetName + "/groundtruth.txt"; + ifstream gtList(gtListPath.c_str()); + if (!gtList.is_open()) + printf("Error to open groundtruth.txt!!!"); + + //Make a list of datasets lengths + int currFrameID = 1; + if (currDatasetID == 0) + printf("VOT 2015 Dataset Initialization...\n"); + bool trFLG = true; + do + { + currFrameID++; + string fullPath = rootPath + "/" + datasetName + "/" + numberToString(currFrameID) + ".jpg"; + if (!fileExists(fullPath)) + break; + + //Make VOT Object + Ptr currObj(new TRACK_votObj); + currObj->imagePath = fullPath; + currObj->id = currFrameID; + + //Get Ground Truth data + double x1 = 0, y1 = 0, + x2 = 0, y2 = 0, + x3 = 0, y3 = 0, + x4 = 0, y4 = 0; + string tmp; + getline(gtList, tmp); + sscanf(tmp.c_str(), "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4); + currObj->gtbb.push_back(Point2d(x1, y1)); + currObj->gtbb.push_back(Point2d(x2, y2)); + currObj->gtbb.push_back(Point2d(x3, y3)); + currObj->gtbb.push_back(Point2d(x4, y4)); + + //Add object to storage + objects.push_back(currObj); + + } while (trFLG); + + datasetsLengths.push_back(currFrameID - 1); + data.push_back(objects); + } + } + else + { + printf("Couldn't find a *list.txt* in VOT 2015 folder!!!"); + } + + namesList.close(); + return; + } + + int TRACK_votImpl::getDatasetsNum() + { + return (int)(data.size()); + } + + int TRACK_votImpl::getDatasetLength(int id) + { + if (id > 0 && id <= (int)data.size()) + return (int)(data[id - 1].size()); + else + { + printf("Dataset ID is out of range...\nAllowed IDs are: 1~%d\n", (int)data.size()); + return -1; + } + } + + bool TRACK_votImpl::initDataset(int id) + { + if (id > 0 && id <= (int)data.size()) + { + activeDatasetID = id; + return true; + } + else + { + printf("Dataset ID is out of range...\nAllowed IDs are: 1~%d\n", (int)data.size()); + return false; + } + } + + bool TRACK_votImpl::getNextFrame(Mat &frame) + { + if (frameCounter >= (int)data[activeDatasetID - 1].size()) + return false; + string imgPath = data[activeDatasetID - 1][frameCounter]->imagePath; + frame = imread(imgPath); + frameCounter++; + return !frame.empty(); + } + + Ptr TRACK_vot::create() + { + return Ptr(new TRACK_votImpl); + } + + vector TRACK_votImpl::getGT() + { + Ptr currObj = data[activeDatasetID - 1][frameCounter - 1]; + return currObj->gtbb; + } + + } +} diff --git a/modules/datasets/src/util.cpp b/modules/datasets/src/util.cpp index 7f2235792..3ae90e76e 100644 --- a/modules/datasets/src/util.cpp +++ b/modules/datasets/src/util.cpp @@ -45,7 +45,7 @@ #include -#ifdef __GNUC__ +#ifndef _WIN32 #include #include #include @@ -73,7 +73,7 @@ void split(const string &s, vector &elems, char delim) void createDirectory(const string &path) { -#ifdef __GNUC__ +#ifndef _WIN32 mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); #else mkdir(path.c_str()); @@ -82,7 +82,7 @@ void createDirectory(const string &path) void getDirList(const string &dirName, vector &fileNames) { -#ifdef __GNUC__ +#ifndef _WIN32 struct dirent **namelist; int n = scandir(dirName.c_str(), &namelist, NULL, alphasort); for (int i=0; i() returns the + EnumDescriptor for that type -- useful for templates which cannot call + SomeGeneratedEnumType_descriptor(). + * Various optimizations and obscure bug fixes. + + Java + * Lite mode: The "optimize_for = LITE_RUNTIME" option causes the compiler + to generate code which only depends libprotobuf-lite, which is much smaller + than libprotobuf but lacks descriptors, reflection, and some other features. + * Lots of style cleanups. + + Python + * Fixed endianness bug with floats and doubles. + * Text format parsing support. + * Fix bug with parsing packed repeated fields in embedded messages. + * Ability to initialize fields by passing keyword args to constructor. + * Support iterators in extend and __setslice__ for containers. + +2009-05-13 version 2.1.0: + + General + * Repeated fields of primitive types (types other that string, group, and + nested messages) may now use the option [packed = true] to get a more + efficient encoding. In the new encoding, the entire list is written + as a single byte blob using the "length-delimited" wire type. Within + this blob, the individual values are encoded the same way they would + be normally except without a tag before each value (thus, they are + tightly "packed"). + * For each field, the generated code contains an integer constant assigned + to the field number. For example, the .proto file: + message Foo { optional int bar_baz = 123; } + would generate the following constants, all with the integer value 123: + C++: Foo::kBarBazFieldNumber + Java: Foo.BAR_BAZ_FIELD_NUMBER + Python: Foo.BAR_BAZ_FIELD_NUMBER + Constants are also generated for extensions, with the same naming scheme. + These constants may be used as switch cases. + * Updated bundled Google Test to version 1.3.0. Google Test is now bundled + in its verbatim form as a nested autoconf package, so you can drop in any + other version of Google Test if needed. + * optimize_for = SPEED is now the default, by popular demand. Use + optimize_for = CODE_SIZE if code size is more important in your app. + * It is now an error to define a default value for a repeated field. + Previously, this was silently ignored (it had no effect on the generated + code). + * Fields can now be marked deprecated like: + optional int32 foo = 1 [deprecated = true]; + Currently this does not have any actual effect, but in the future the code + generators may generate deprecation annotations in each language. + * Cross-compiling should now be possible using the --with-protoc option to + configure. See README.txt for more info. + + protoc + * --error_format=msvs option causes errors to be printed in Visual Studio + format, which should allow them to be clicked on in the build log to go + directly to the error location. + * The type name resolver will no longer resolve type names to fields. For + example, this now works: + message Foo {} + message Bar { + optional int32 Foo = 1; + optional Foo baz = 2; + } + Previously, the type of "baz" would resolve to "Bar.Foo", and you'd get + an error because Bar.Foo is a field, not a type. Now the type of "baz" + resolves to the message type Foo. This change is unlikely to make a + difference to anyone who follows the Protocol Buffers style guide. + + C++ + * Several optimizations, including but not limited to: + - Serialization, especially to flat arrays, is 10%-50% faster, possibly + more for small objects. + - Several descriptor operations which previously required locking no longer + do. + - Descriptors are now constructed lazily on first use, rather than at + process startup time. This should save memory in programs which do not + use descriptors or reflection. + - UnknownFieldSet completely redesigned to be more efficient (especially in + terms of memory usage). + - Various optimizations to reduce code size (though the serialization speed + optimizations increased code size). + * Message interface has method ParseFromBoundedZeroCopyStream() which parses + a limited number of bytes from an input stream rather than parsing until + EOF. + * GzipInputStream and GzipOutputStream support reading/writing gzip- or + zlib-compressed streams if zlib is available. + (google/protobuf/io/gzip_stream.h) + * DescriptorPool::FindAllExtensions() and corresponding + DescriptorDatabase::FindAllExtensions() can be used to enumerate all + extensions of a given type. + * For each enum type Foo, protoc will generate functions: + const string& Foo_Name(Foo value); + bool Foo_Parse(const string& name, Foo* result); + The former returns the name of the enum constant corresponding to the given + value while the latter finds the value corresponding to a name. + * RepeatedField and RepeatedPtrField now have back-insertion iterators. + * String fields now have setters that take a char* and a size, in addition + to the existing ones that took char* or const string&. + * DescriptorPool::AllowUnknownDependencies() may be used to tell + DescriptorPool to create placeholder descriptors for unknown entities + referenced in a FileDescriptorProto. This can allow you to parse a .proto + file without having access to other .proto files that it imports, for + example. + * Updated gtest to latest version. The gtest package is now included as a + nested autoconf package, so it should be able to drop new versions into the + "gtest" subdirectory without modification. + + Java + * Fixed bug where Message.mergeFrom(Message) failed to merge extensions. + * Message interface has new method toBuilder() which is equivalent to + newBuilderForType().mergeFrom(this). + * All enums now implement the ProtocolMessageEnum interface. + * Setting a field to null now throws NullPointerException. + * Fixed tendency for TextFormat's parsing to overflow the stack when + parsing large string values. The underlying problem is with Java's + regex implementation (which unfortunately uses recursive backtracking + rather than building an NFA). Worked around by making use of possesive + quantifiers. + * Generated service classes now also generate pure interfaces. For a service + Foo, Foo.Interface is a pure interface containing all of the service's + defined methods. Foo.newReflectiveService() can be called to wrap an + instance of this interface in a class that implements the generic + RpcService interface, which provides reflection support that is usually + needed by RPC server implementations. + * RPC interfaces now support blocking operation in addition to non-blocking. + The protocol compiler generates separate blocking and non-blocking stubs + which operate against separate blocking and non-blocking RPC interfaces. + RPC implementations will have to implement the new interfaces in order to + support blocking mode. + * New I/O methods parseDelimitedFrom(), mergeDelimitedFrom(), and + writeDelimitedTo() read and write "delemited" messages from/to a stream, + meaning that the message size precedes the data. This way, you can write + multiple messages to a stream without having to worry about delimiting + them yourself. + * Throw a more descriptive exception when build() is double-called. + * Add a method to query whether CodedInputStream is at the end of the input + stream. + * Add a method to reset a CodedInputStream's size counter; useful when + reading many messages with the same stream. + * equals() and hashCode() now account for unknown fields. + + Python + * Added slicing support for repeated scalar fields. Added slice retrieval and + removal of repeated composite fields. + * Updated RPC interfaces to allow for blocking operation. A client may + now pass None for a callback when making an RPC, in which case the + call will block until the response is received, and the response + object will be returned directly to the caller. This interface change + cannot be used in practice until RPC implementations are updated to + implement it. + * Changes to input_stream.py should make protobuf compatible with appengine. + +2008-11-25 version 2.0.3: + + protoc + * Enum values may now have custom options, using syntax similar to field + options. + * Fixed bug where .proto files which use custom options but don't actually + define them (i.e. they import another .proto file defining the options) + had to explicitly import descriptor.proto. + * Adjacent string literals in .proto files will now be concatenated, like in + C. + * If an input file is a Windows absolute path (e.g. "C:\foo\bar.proto") and + the import path only contains "." (or contains "." but does not contain + the file), protoc incorrectly thought that the file was under ".", because + it thought that the path was relative (since it didn't start with a slash). + This has been fixed. + + C++ + * Generated message classes now have a Swap() method which efficiently swaps + the contents of two objects. + * All message classes now have a SpaceUsed() method which returns an estimate + of the number of bytes of allocated memory currently owned by the object. + This is particularly useful when you are reusing a single message object + to improve performance but want to make sure it doesn't bloat up too large. + * New method Message::SerializeAsString() returns a string containing the + serialized data. May be more convenient than calling + SerializeToString(string*). + * In debug mode, log error messages when string-type fields are found to + contain bytes that are not valid UTF-8. + * Fixed bug where a message with multiple extension ranges couldn't parse + extensions. + * Fixed bug where MergeFrom(const Message&) didn't do anything if invoked on + a message that contained no fields (but possibly contained extensions). + * Fixed ShortDebugString() to not be O(n^2). Durr. + * Fixed crash in TextFormat parsing if the first token in the input caused a + tokenization error. + * Fixed obscure bugs in zero_copy_stream_impl.cc. + * Added support for HP C++ on Tru64. + * Only build tests on "make check", not "make". + * Fixed alignment issue that caused crashes when using DynamicMessage on + 64-bit Sparc machines. + * Simplify template usage to work with MSVC 2003. + * Work around GCC 4.3.x x86_64 compiler bug that caused crashes on startup. + (This affected Fedora 9 in particular.) + * Now works on "Solaris 10 using recent Sun Studio". + + Java + * New overload of mergeFrom() which parses a slice of a byte array instead + of the whole thing. + * New method ByteString.asReadOnlyByteBuffer() does what it sounds like. + * Improved performance of isInitialized() when optimizing for code size. + + Python + * Corrected ListFields() signature in Message base class to match what + subclasses actually implement. + * Some minor refactoring. + * Don't pass self as first argument to superclass constructor (no longer + allowed in Python 2.6). + +2008-09-29 version 2.0.2: + + General + * License changed from Apache 2.0 to New BSD. + * It is now possible to define custom "options", which are basically + annotations which may be placed on definitions in a .proto file. + For example, you might define a field option called "foo" like so: + import "google/protobuf/descriptor.proto" + extend google.protobuf.FieldOptions { + optional string foo = 12345; + } + Then you annotate a field using the "foo" option: + message MyMessage { + optional int32 some_field = 1 [(foo) = "bar"] + } + The value of this option is then visible via the message's + Descriptor: + const FieldDescriptor* field = + MyMessage::descriptor()->FindFieldByName("some_field"); + assert(field->options().GetExtension(foo) == "bar"); + This feature has been implemented and tested in C++ and Java. + Other languages may or may not need to do extra work to support + custom options, depending on how they construct descriptors. + + C++ + * Fixed some GCC warnings that only occur when using -pedantic. + * Improved static initialization code, making ordering more + predictable among other things. + * TextFormat will no longer accept messages which contain multiple + instances of a singular field. Previously, the latter instance + would overwrite the former. + * Now works on systems that don't have hash_map. + + Java + * Print @Override annotation in generated code where appropriate. + + Python + * Strings now use the "unicode" type rather than the "str" type. + String fields may still be assigned ASCII "str" values; they will + automatically be converted. + * Adding a property to an object representing a repeated field now + raises an exception. For example: + # No longer works (and never should have). + message.some_repeated_field.foo = 1 + + Windows + * We now build static libraries rather than DLLs by default on MSVC. + See vsprojects/readme.txt for more information. + +2008-08-15 version 2.0.1: + + protoc + * New flags --encode and --decode can be used to convert between protobuf text + format and binary format from the command-line. + * New flag --descriptor_set_out can be used to write FileDescriptorProtos for + all parsed files directly into a single output file. This is particularly + useful if you wish to parse .proto files from programs written in languages + other than C++: just run protoc as a background process and have it output + a FileDescriptorList, then parse that natively. + * Improved error message when an enum value's name conflicts with another + symbol defined in the enum type's scope, e.g. if two enum types declared + in the same scope have values with the same name. This is disallowed for + compatibility with C++, but this wasn't clear from the error. + * Fixed absolute output paths on Windows. + * Allow trailing slashes in --proto_path mappings. + + C++ + * Reflection objects are now per-class rather than per-instance. To make this + possible, the Reflection interface had to be changed such that all methods + take the Message instance as a parameter. This change improves performance + significantly in memory-bandwidth-limited use cases, since it makes the + message objects smaller. Note that source-incompatible interface changes + like this will not be made again after the library leaves beta. + * Heuristically detect sub-messages when printing unknown fields. + * Fix static initialization ordering bug that caused crashes at startup when + compiling on Mac with static linking. + * Fixed TokenizerTest when compiling with -DNDEBUG on Linux. + * Fixed incorrect definition of kint32min. + * Fix bytes type setter to work with byte sequences with embedded NULLs. + * Other irrelevant tweaks. + + Java + * Fixed UnknownFieldSet's parsing of varints larger than 32 bits. + * Fixed TextFormat's parsing of "inf" and "nan". + * Fixed TextFormat's parsing of comments. + * Added info to Java POM that will be required when we upload the + package to a Maven repo. + + Python + * MergeFrom(message) and CopyFrom(message) are now implemented. + * SerializeToString() raises an exception if the message is missing required + fields. + * Code organization improvements. + * Fixed doc comments for RpcController and RpcChannel, which had somehow been + swapped. + * Fixed text_format_test on Windows where floating-point exponents sometimes + contain extra zeros. + * Fix Python service CallMethod() implementation. + + Other + * Improved readmes. + * VIM syntax highlighting improvements. + +2008-07-07 version 2.0.0: + + * First public release. diff --git a/modules/dnn/3rdparty/protobuf/CMakeLists.txt b/modules/dnn/3rdparty/protobuf/CMakeLists.txt new file mode 100644 index 000000000..68dc7f837 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/CMakeLists.txt @@ -0,0 +1,183 @@ +project(libprotobuf) + +include(CheckIncludeFiles) +include(cmake/CheckCxxHashset.cmake) +include(cmake/CheckCxxHashmap.cmake) + +check_include_files("pthread.h" HAVE_PTHREAD) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + include(CheckIncludeFileCXX) + set(CMAKE_REQUIRED_FLAGS "-std=c++11") + check_include_file_cxx("unordered_map" HAVE_UNORDERED_MAP) + check_include_file_cxx("tr1/unordered_map" HAVE_TR1_UNORDERED_MAP) + set(CMAKE_REQUIRED_FLAGS ) + + if(HAVE_UNORDERED_MAP) + add_definitions("-std=c++11") # For unordered_map + set(HASH_MAP_H "") + set(HASH_MAP_CLASS "unordered_map") + set(HASH_NAMESPACE "std") + set(HAVE_HASH_MAP 1) + elseif(HAVE_TR1_UNORDERED_MAP) + add_definitions("-std=c++11") # For unordered_map + set(HASH_MAP_H "") + set(HASH_MAP_CLASS "unordered_map") + set(HASH_NAMESPACE "std::tr1") + set(HAVE_HASH_MAP 1) + else() + CHECK_HASHMAP() + if(HAVE_GNU_EXT_HASH_MAP) + set(HASH_MAP_H "") + set(HASH_NAMESPACE "__gnu_cxx") + set(HASH_MAP_CLASS "hash_map") + set(HAVE_HASH_MAP 1) + elseif(HAVE_STD_EXT_HASH_MAP) + set(HASH_MAP_H "") + set(HASH_NAMESPACE "std") + set(HASH_MAP_CLASS "hash_map") + set(HAVE_HASH_MAP 1) + elseif(HAVE_GLOBAL_HASH_MAP) + set(HASH_MAP_H "") + set(HASH_NAMESPACE "") + set(HASH_MAP_CLASS "hash_map") + set(HAVE_HASH_MAP 1) + else() + set(HAVE_HASH_MAP 0) + endif() + endif() + + set(CMAKE_REQUIRED_FLAGS "-std=c++11") + check_include_file_cxx("unordered_set" HAVE_UNORDERED_SET) + check_include_file_cxx("tr1/unordered_set" HAVE_TR1_UNORDERED_SET) + set(CMAKE_REQUIRED_FLAGS ) + + if(HAVE_UNORDERED_SET) + set(HASH_SET_H "") + set(HASH_SET_CLASS "unordered_set") + set(HAVE_HASH_SET 1) + elseif(HAVE_TR1_UNORDERED_SET) + add_definitions("-std=c++11") + set(HASH_SET_H "") + set(HASH_SET_CLASS "unordered_set") + set(HAVE_HASH_SET 1) + else() + CHECK_HASHSET() + if(HAVE_GNU_EXT_HASH_SET) + set(HASH_SET_H "") + set(HASH_NAMESPACE "__gnu_cxx") + set(HASH_SET_CLASS "hash_set") + set(HAVE_HASH_SET 1) + elseif(HAVE_STD_EXT_HASH_SET) + set(HASH_SET_H "") + set(HASH_NAMESPACE "std") + set(HASH_SET_CLASS "hash_set") + set(HAVE_HASH_SET 1) + elseif(HAVE_GLOBAL_HASH_SET) + set(HASH_SET_H "") + set(HASH_NAMESPACE "") + set(HASH_SET_CLASS "hash_set") + set(HAVE_HASH_SET 1) + else() + set(HAVE_HASH_SET 0) + endif() + endif() +endif() + +if(WIN32 AND BUILD_SHARED_LIBS AND MSVC) + add_definitions(-DPROTOBUF_USE_DLLS) + add_definitions(-DLIBPROTOBUF_EXPORTS) +endif() + +#add_definitions( -DGOOGLE_PROTOBUF_NO_THREAD_SAFETY ) #we don't need thread safety +add_definitions( -D_GNU_SOURCE=1 ) #it's maybe useful +add_definitions( -DHAVE_CONFIG_H ) #we will use config.h +configure_file("cmake/config.h.in" "config.h") + +if(MSVC) + add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 ) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305 /wd4127 /wd4100 /wd4512 /wd4125 /wd4389 /wd4510 /wd4610 /wd4702) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4456) # VS 2015 +else() + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-deprecated -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wunused-parameter -Wunused-local-typedefs -Wsign-compare -Wsign-promo -Wundef) +endif() + +# Easier to support different versions of protobufs +function(append_if_exist OUTPUT_LIST) + set(${OUTPUT_LIST}) + foreach(fil ${ARGN}) + if(EXISTS ${fil}) + list(APPEND ${OUTPUT_LIST} "${fil}") + else() + message(WARNING "file missing: ${fil}") + endif() + endforeach() + set(${OUTPUT_LIST} ${${OUTPUT_LIST}} PARENT_SCOPE) +endfunction() + +set(PROTOBUF_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) + +if(MSVC) + set(ATOMICOPS_INTERNALS ${PROTOBUF_ROOT}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc) +else() + set(ATOMICOPS_INTERNALS ${PROTOBUF_ROOT}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc) +endif() + +append_if_exist(PROTOBUF_SRCS + ${PROTOBUF_ROOT}/src/google/protobuf/compiler/importer.cc + ${PROTOBUF_ROOT}/src/google/protobuf/compiler/parser.cc + ${PROTOBUF_ROOT}/src/google/protobuf/descriptor.cc + ${PROTOBUF_ROOT}/src/google/protobuf/descriptor.pb.cc + ${PROTOBUF_ROOT}/src/google/protobuf/descriptor_database.cc + ${PROTOBUF_ROOT}/src/google/protobuf/dynamic_message.cc + ${PROTOBUF_ROOT}/src/google/protobuf/extension_set.cc + ${PROTOBUF_ROOT}/src/google/protobuf/extension_set_heavy.cc + ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_reflection.cc + ${PROTOBUF_ROOT}/src/google/protobuf/generated_message_util.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/coded_stream.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/gzip_stream.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/printer.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/tokenizer.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream_impl.cc + ${PROTOBUF_ROOT}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc + ${PROTOBUF_ROOT}/src/google/protobuf/message.cc + ${PROTOBUF_ROOT}/src/google/protobuf/message_lite.cc + ${PROTOBUF_ROOT}/src/google/protobuf/reflection_ops.cc + ${PROTOBUF_ROOT}/src/google/protobuf/repeated_field.cc + ${PROTOBUF_ROOT}/src/google/protobuf/service.cc + ${ATOMICOPS_INTERNALS} + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/common.cc + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/once.cc + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/stringprintf.cc + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/structurally_valid.cc + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/strutil.cc + ${PROTOBUF_ROOT}/src/google/protobuf/stubs/substitute.cc + ${PROTOBUF_ROOT}/src/google/protobuf/text_format.cc + ${PROTOBUF_ROOT}/src/google/protobuf/unknown_field_set.cc + ${PROTOBUF_ROOT}/src/google/protobuf/wire_format.cc + ${PROTOBUF_ROOT}/src/google/protobuf/wire_format_lite.cc + #${PROTOBUF_ROOT}/src/google/protobuf/stubs/hash.cc +) + +if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR CV_ICC)) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") +endif() + +add_library(libprotobuf STATIC ${PROTOBUF_SRCS}) +include_directories(${PROTOBUF_ROOT}/src ${CMAKE_CURRENT_BINARY_DIR}) + +set_target_properties(libprotobuf + PROPERTIES + OUTPUT_NAME libprotobuf + DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" + ARCHIVE_OUTPUT_DIRECTORY ${3P_LIBRARY_OUTPUT_PATH} + ) + +if(ENABLE_SOLUTION_FOLDERS) + set_target_properties(libprotobuf PROPERTIES FOLDER "3rdparty") +endif() + +if(NOT BUILD_SHARED_LIBS) + ocv_install_target(libprotobuf EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev) +endif() diff --git a/modules/dnn/3rdparty/protobuf/CONTRIBUTORS.txt b/modules/dnn/3rdparty/protobuf/CONTRIBUTORS.txt new file mode 100644 index 000000000..b39ec308b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/CONTRIBUTORS.txt @@ -0,0 +1,90 @@ +This file contains a list of people who have made large contributions +to the public version of Protocol Buffers. + +Original Protocol Buffers design and implementation: + Sanjay Ghemawat + Jeff Dean + Daniel Dulitz + Craig Silverstein + Paul Haahr + Corey Anderson + (and many others) + +Proto2 C++ and Java primary author: + Kenton Varda + +Proto2 Python primary authors: + Will Robinson + Petar Petrov + +Large code contributions: + Jason Hsueh + Joseph Schorr + Wenbo Zhu + +Large quantity of code reviews: + Scott Bruce + Frank Yellin + Neal Norwitz + Jeffrey Yasskin + Ambrose Feinstein + +Documentation: + Lisa Carey + +Maven packaging: + Gregory Kick + +Patch contributors: + Kevin Ko + * Small patch to handle trailing slashes in --proto_path flag. + Johan Euphrosine + * Small patch to fix Python CallMethod(). + Ulrich Kunitz + * Small optimizations to Python serialization. + Leandro Lucarella + * VI syntax highlighting tweaks. + * Fix compiler to not make output executable. + Dilip Joseph + * Heuristic detection of sub-messages when printing unknown fields in + text format. + Brian Atkinson + * Added @Override annotation to generated Java code where appropriate. + Vincent Choinière + * Tru64 support. + Monty Taylor + * Solaris 10 + Sun Studio fixes. + Alek Storm + * Slicing support for repeated scalar fields for the Python API. + Oleg Smolsky + * MS Visual Studio error format option. + * Detect unordered_map in stl_hash.m4. + Brian Olson + * gzip/zlib I/O support. + Michael Poole + * Fixed warnings about generated constructors not explicitly initializing + all fields (only present with certain compiler settings). + * Added generation of field number constants. + Wink Saville + * Fixed initialization ordering problem in logging code. + Will Pierce + * Small patch improving performance of in Python serialization. + Alexandre Vassalotti + * Emacs mode for Protocol Buffers (editors/protobuf-mode.el). + Scott Stafford + * Added Swap(), SwapElements(), and RemoveLast() to Reflection interface. + Alexander Melnikov + * HPUX support. + Oliver Jowett + * Detect whether zlib is new enough in configure script. + * Fixes for Solaris 10 32/64-bit confusion. + Evan Jones + * Optimize Java serialization code when writing a small message to a stream. + * Optimize Java serialization of strings so that UTF-8 encoding happens only + once per string per serialization call. + * Clean up some Java warnings. + * Fix bug with permanent callbacks that delete themselves when run. + Michael Kucharski + * Added CodedInputStream.getTotalBytesRead(). + Kacper Kowalik + * Fixed m4/acx_pthread.m4 problem for some Linux distributions. diff --git a/modules/dnn/3rdparty/protobuf/COPYING.txt b/modules/dnn/3rdparty/protobuf/COPYING.txt new file mode 100644 index 000000000..705db579c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/COPYING.txt @@ -0,0 +1,33 @@ +Copyright 2008, 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. + +Code generated by the Protocol Buffer compiler is owned by the owner +of the input file used when generating it. This code is not +standalone and requires a support library to be linked with it. This +support library is itself covered by the above license. diff --git a/modules/dnn/3rdparty/protobuf/README.txt b/modules/dnn/3rdparty/protobuf/README.txt new file mode 100644 index 000000000..17551a5a0 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/README.txt @@ -0,0 +1,152 @@ +Protocol Buffers - Google's data interchange format +Copyright 2008 Google Inc. +http://code.google.com/apis/protocolbuffers/ + +C++ Installation - Unix +======================= + +To build and install the C++ Protocol Buffer runtime and the Protocol +Buffer compiler (protoc) execute the following: + + $ ./configure + $ make + $ make check + $ make install + +If "make check" fails, you can still install, but it is likely that +some features of this library will not work correctly on your system. +Proceed at your own risk. + +"make install" may require superuser privileges. + +For advanced usage information on configure and make, see INSTALL.txt. + +** Hint on install location ** + + By default, the package will be installed to /usr/local. However, + on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH. + You can add it, but it may be easier to just install to /usr + instead. To do this, invoke configure as follows: + + ./configure --prefix=/usr + + If you already built the package with a different prefix, make sure + to run "make clean" before building again. + +** Compiling dependent packages ** + + To compile a package that uses Protocol Buffers, you need to pass + various flags to your compiler and linker. As of version 2.2.0, + Protocol Buffers integrates with pkg-config to manage this. If you + have pkg-config installed, then you can invoke it to get a list of + flags like so: + + pkg-config --cflags protobuf # print compiler flags + pkg-config --libs protobuf # print linker flags + pkg-config --cflags --libs protobuf # print both + + For example: + + c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf` + + Note that packages written prior to the 2.2.0 release of Protocol + Buffers may not yet integrate with pkg-config to get flags, and may + not pass the correct set of flags to correctly link against + libprotobuf. If the package in question uses autoconf, you can + often fix the problem by invoking its configure script like: + + configure CXXFLAGS="$(pkg-config --cflags protobuf)" \ + LIBS="$(pkg-config --libs protobuf)" + + This will force it to use the correct flags. + + If you are writing an autoconf-based package that uses Protocol + Buffers, you should probably use the PKG_CHECK_MODULES macro in your + configure script like: + + PKG_CHECK_MODULES([protobuf], [protobuf]) + + See the pkg-config man page for more info. + + If you only want protobuf-lite, substitute "protobuf-lite" in place + of "protobuf" in these examples. + +** Note for cross-compiling ** + + The makefiles normally invoke the protoc executable that they just + built in order to build tests. When cross-compiling, the protoc + executable may not be executable on the host machine. In this case, + you must build a copy of protoc for the host machine first, then use + the --with-protoc option to tell configure to use it instead. For + example: + + ./configure --with-protoc=protoc + + This will use the installed protoc (found in your $PATH) instead of + trying to execute the one built during the build process. You can + also use an executable that hasn't been installed. For example, if + you built the protobuf package for your host machine in ../host, + you might do: + + ./configure --with-protoc=../host/src/protoc + + Either way, you must make sure that the protoc executable you use + has the same version as the protobuf source code you are trying to + use it with. + +** Note for Solaris users ** + + Solaris 10 x86 has a bug that will make linking fail, complaining + about libstdc++.la being invalid. We have included a work-around + in this package. To use the work-around, run configure as follows: + + ./configure LDFLAGS=-L$PWD/src/solaris + + See src/solaris/libstdc++.la for more info on this bug. + +** Note for HP C++ Tru64 users ** + + To compile invoke configure as follows: + + ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM" + + Also, you will need to use gmake instead of make. + +C++ Installation - Windows +========================== + +If you are using Microsoft Visual C++, see vsprojects/readme.txt. + +If you are using Cygwin or MinGW, follow the Unix installation +instructions, above. + +Binary Compatibility Warning +============================ + +Due to the nature of C++, it is unlikely that any two versions of the +Protocol Buffers C++ runtime libraries will have compatible ABIs. +That is, if you linked an executable against an older version of +libprotobuf, it is unlikely to work with a newer version without +re-compiling. This problem, when it occurs, will normally be detected +immediately on startup of your app. Still, you may want to consider +using static linkage. You can configure this package to install +static libraries only using: + + ./configure --disable-shared + +Java and Python Installation +============================ + +The Java and Python runtime libraries for Protocol Buffers are located +in the java and python directories. See the README file in each +directory for more information on how to compile and install them. +Note that both of them require you to first install the Protocol +Buffer compiler (protoc), which is part of the C++ package. + +Usage +===== + +The complete documentation for Protocol Buffers is available via the +web at: + + http://code.google.com/apis/protocolbuffers/ diff --git a/modules/dnn/3rdparty/protobuf/cmake/.gitignore b/modules/dnn/3rdparty/protobuf/cmake/.gitignore new file mode 100644 index 000000000..fe06a514f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/cmake/.gitignore @@ -0,0 +1,2 @@ +build +build-* diff --git a/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashmap.cmake b/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashmap.cmake new file mode 100644 index 000000000..122c512b4 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashmap.cmake @@ -0,0 +1,55 @@ +# From LLVM + +# - Check if for hash_map. +# CHECK_HASHMAP () +# + +include(CheckCXXSourceCompiles) + +macro(CHECK_HASHMAP) + message(STATUS "Checking for C++ hash_map implementation...") + check_cxx_source_compiles(" + #include + int main() { + __gnu_cxx::hash_map t; + } +" + HAVE_GNU_EXT_HASH_MAP + ) + if(HAVE_GNU_EXT_HASH_MAP) + message(STATUS "C++ hash_map found in 'ext' dir in namespace __gnu_cxx::") + endif(HAVE_GNU_EXT_HASH_MAP) + + check_cxx_source_compiles(" + #include + int main() { + std::hash_map t; + } +" + HAVE_STD_EXT_HASH_MAP + ) + if(HAVE_STD_EXT_HASH_MAP) + message(STATUS "C++ hash_map found in 'ext' dir in namespace std::") + endif(HAVE_STD_EXT_HASH_MAP) + + check_cxx_source_compiles(" + #include + int main() { + hash_map t; + } +" + HAVE_GLOBAL_HASH_MAP + ) + if(HAVE_GLOBAL_HASH_MAP) + message(STATUS "C++ hash_map found in global namespace") + endif(HAVE_GLOBAL_HASH_MAP) + + if(NOT HAVE_GNU_EXT_HASH_MAP) + if(NOT HAVE_STD_EXT_HASH_MAP) + if(NOT HAVE_GLOBAL_HASH_MAP) + message(STATUS "C++ hash_map not found") + endif(NOT HAVE_GLOBAL_HASH_MAP) + endif(NOT HAVE_STD_EXT_HASH_MAP) + endif(NOT HAVE_GNU_EXT_HASH_MAP) + +endmacro(CHECK_HASHMAP) diff --git a/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashset.cmake b/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashset.cmake new file mode 100644 index 000000000..495b174c2 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/cmake/CheckCxxHashset.cmake @@ -0,0 +1,54 @@ +# From LLVM + +# - Check if for hash_set. +# CHECK_HASHSET () +# + +include(CheckCXXSourceCompiles) + +macro(CHECK_HASHSET) + message(STATUS "Checking for C++ hash_set implementation...") + check_cxx_source_compiles(" + #include + int main() { + __gnu_cxx::hash_set t; + } +" + HAVE_GNU_EXT_HASH_SET + ) + if(HAVE_GNU_EXT_HASH_SET) + message(STATUS "C++ hash_set found in 'ext' dir in namespace __gnu_cxx::") + endif(HAVE_GNU_EXT_HASH_SET) + + check_cxx_source_compiles(" + #include + int main() { + std::hash_set t; + } +" + HAVE_STD_EXT_HASH_SET + ) + if(HAVE_STD_EXT_HASH_SET) + message(STATUS "C++ hash_set found in 'ext' dir in namespace std::") + endif(HAVE_STD_EXT_HASH_SET) + + check_cxx_source_compiles(" + #include + int main() { + hash_set t; + } +" + HAVE_GLOBAL_HASH_SET + ) + if(HAVE_GLOBAL_HASH_SET) + message(STATUS "C++ hash_set found in global namespace") + endif(HAVE_GLOBAL_HASH_SET) + + if(NOT HAVE_GNU_EXT_HASH_SET) + if(NOT HAVE_STD_EXT_HASH_SET) + if(NOT HAVE_GLOBAL_HASH_SET) + message(STATUS "C++ hash_set not found") + endif(NOT HAVE_GLOBAL_HASH_SET) + endif(NOT HAVE_STD_EXT_HASH_SET) + endif(NOT HAVE_GNU_EXT_HASH_SET) +endmacro(CHECK_HASHSET) diff --git a/modules/dnn/3rdparty/protobuf/cmake/LICENSE b/modules/dnn/3rdparty/protobuf/cmake/LICENSE new file mode 100644 index 000000000..b97fb748e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/cmake/LICENSE @@ -0,0 +1,31 @@ +New BSD license: http://opensource.org/licenses/BSD-3-Clause + +Copyright (c) 2014, Jesper Eskilson and others +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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 +HOLDER 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. \ No newline at end of file diff --git a/modules/dnn/3rdparty/protobuf/cmake/config.h.in b/modules/dnn/3rdparty/protobuf/cmake/config.h.in new file mode 100644 index 000000000..96d4d9ae9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/cmake/config.h.in @@ -0,0 +1,62 @@ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* the name of */ +#define HASH_MAP_CLASS ${HASH_MAP_CLASS} + +/* the location of or */ +#define HASH_MAP_H ${HASH_MAP_H} + +/* the namespace of hash_map/hash_set */ +#define HASH_NAMESPACE ${HASH_NAMESPACE} + +/* the name of */ +#define HASH_SET_CLASS ${HASH_SET_CLASS} + +/* the location of or */ +#define HASH_SET_H ${HASH_SET_H} + +/* define if the compiler has hash_map */ +#cmakedefine HAVE_HASH_MAP + +/* define if the compiler has hash_set */ +#cmakedefine HAVE_HASH_SET + +/* Define if you have POSIX threads libraries and header files. */ +#cmakedefine HAVE_PTHREAD + +/* Enable classes using zlib compression. */ +#undef HAVE_ZLIB + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +#endif /* _CONFIG_H_ */ + diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.cc new file mode 100644 index 000000000..455c239a9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.cc @@ -0,0 +1,80 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +namespace google { +namespace protobuf { +namespace compiler { + +CodeGenerator::~CodeGenerator() {} +GeneratorContext::~GeneratorContext() {} + +io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( + const string& filename, const string& insertion_point) { + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; + return NULL; // make compiler happy +} + +void GeneratorContext::ListParsedFiles( + vector* output) { + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; +} + +// Parses a set of comma-delimited name/value pairs. +void ParseGeneratorParameter(const string& text, + vector >* output) { + vector parts; + SplitStringUsing(text, ",", &parts); + + for (int i = 0; i < parts.size(); i++) { + string::size_type equals_pos = parts[i].find_first_of('='); + pair value; + if (equals_pos == string::npos) { + value.first = parts[i]; + value.second = ""; + } else { + value.first = parts[i].substr(0, equals_pos); + value.second = parts[i].substr(equals_pos + 1); + } + output->push_back(value); + } +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.h new file mode 100644 index 000000000..252f68d1d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/code_generator.h @@ -0,0 +1,142 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Defines the abstract interface implemented by each of the language-specific +// code generators. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace io { class ZeroCopyOutputStream; } +class FileDescriptor; + +namespace compiler { + +// Defined in this file. +class CodeGenerator; +class GeneratorContext; + +// The abstract interface to a class which generates code implementing a +// particular proto file in a particular language. A number of these may +// be registered with CommandLineInterface to support various languages. +class LIBPROTOC_EXPORT CodeGenerator { + public: + inline CodeGenerator() {} + virtual ~CodeGenerator(); + + // Generates code for the given proto file, generating one or more files in + // the given output directory. + // + // A parameter to be passed to the generator can be specified on the + // command line. This is intended to be used by Java and similar languages + // to specify which specific class from the proto file is to be generated, + // though it could have other uses as well. It is empty if no parameter was + // given. + // + // Returns true if successful. Otherwise, sets *error to a description of + // the problem (e.g. "invalid parameter") and returns false. + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator); +}; + +// CodeGenerators generate one or more files in a given directory. This +// abstract interface represents the directory to which the CodeGenerator is +// to write and other information about the context in which the Generator +// runs. +class LIBPROTOC_EXPORT GeneratorContext { + public: + inline GeneratorContext() {} + virtual ~GeneratorContext(); + + // Opens the given file, truncating it if it exists, and returns a + // ZeroCopyOutputStream that writes to the file. The caller takes ownership + // of the returned object. This method never fails (a dummy stream will be + // returned instead). + // + // The filename given should be relative to the root of the source tree. + // E.g. the C++ generator, when generating code for "foo/bar.proto", will + // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that + // "foo/" is included in these filenames. The filename is not allowed to + // contain "." or ".." components. + virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; + + // Creates a ZeroCopyOutputStream which will insert code into the given file + // at the given insertion point. See plugin.proto (plugin.pb.h) for more + // information on insertion points. The default implementation + // assert-fails -- it exists only for backwards-compatibility. + // + // WARNING: This feature is currently EXPERIMENTAL and is subject to change. + virtual io::ZeroCopyOutputStream* OpenForInsert( + const string& filename, const string& insertion_point); + + // Returns a vector of FileDescriptors for all the files being compiled + // in this run. Useful for languages, such as Go, that treat files + // differently when compiled as a set rather than individually. + virtual void ListParsedFiles(vector* output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext); +}; + +// The type GeneratorContext was once called OutputDirectory. This typedef +// provides backward compatibility. +typedef GeneratorContext OutputDirectory; + +// Several code generators treat the parameter argument as holding a +// list of options separated by commas. This helper function parses +// a set of comma-delimited name/value pairs: e.g., +// "foo=bar,baz,qux=corge" +// parses to the pairs: +// ("foo", "bar"), ("baz", ""), ("qux", "corge") +extern void ParseGeneratorParameter(const string&, + vector >*); + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.cc new file mode 100644 index 000000000..b9293c97d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.cc @@ -0,0 +1,1437 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#ifdef _MSC_VER +#include +#include +#else +#include +#endif +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace compiler { + +#if defined(_WIN32) +#define mkdir(name, mode) mkdir(name) +#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 + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#endif +#endif + +namespace { +#if defined(_WIN32) && !defined(__CYGWIN__) +static const char* kPathSeparator = ";"; +#else +static const char* kPathSeparator = ":"; +#endif + +// Returns true if the text looks like a Windows-style absolute path, starting +// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with +// copy in importer.cc? +static bool IsWindowsAbsolutePath(const string& text) { +#if defined(_WIN32) || defined(__CYGWIN__) + return text.size() >= 3 && text[1] == ':' && + isalpha(text[0]) && + (text[2] == '/' || text[2] == '\\') && + text.find_last_of(':') == 1; +#else + return false; +#endif +} + +void SetFdToTextMode(int fd) { +#ifdef _WIN32 + if (_setmode(fd, _O_TEXT) == -1) { + // This should never happen, I think. + GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno); + } +#endif + // (Text and binary are the same on non-Windows platforms.) +} + +void SetFdToBinaryMode(int fd) { +#ifdef _WIN32 + if (_setmode(fd, _O_BINARY) == -1) { + // This should never happen, I think. + GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno); + } +#endif + // (Text and binary are the same on non-Windows platforms.) +} + +void AddTrailingSlash(string* path) { + if (!path->empty() && path->at(path->size() - 1) != '/') { + path->push_back('/'); + } +} + +bool VerifyDirectoryExists(const string& path) { + if (path.empty()) return true; + + if (access(path.c_str(), F_OK) == -1) { + cerr << path << ": " << strerror(errno) << endl; + return false; + } else { + return true; + } +} + +// Try to create the parent directory of the given file, creating the parent's +// parent if necessary, and so on. The full file name is actually +// (prefix + filename), but we assume |prefix| already exists and only create +// directories listed in |filename|. +bool TryCreateParentDirectory(const string& prefix, const string& filename) { + // Recursively create parent directories to the output file. + vector parts; + SplitStringUsing(filename, "/", &parts); + string path_so_far = prefix; + for (int i = 0; i < parts.size() - 1; i++) { + path_so_far += parts[i]; + if (mkdir(path_so_far.c_str(), 0777) != 0) { + if (errno != EEXIST) { + cerr << filename << ": while trying to create directory " + << path_so_far << ": " << strerror(errno) << endl; + return false; + } + } + path_so_far += '/'; + } + + return true; +} + +} // namespace + +// A MultiFileErrorCollector that prints errors to stderr. +class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, + public io::ErrorCollector { + public: + ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) + : format_(format), tree_(tree) {} + ~ErrorPrinter() {} + + // implements MultiFileErrorCollector ------------------------------ + void AddError(const string& filename, int line, int column, + const string& message) { + + // Print full path when running under MSVS + string dfile; + if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && + tree_ != NULL && + tree_->VirtualFileToDiskFile(filename, &dfile)) { + cerr << dfile; + } else { + cerr << filename; + } + + // Users typically expect 1-based line/column numbers, so we add 1 + // to each here. + if (line != -1) { + // Allow for both GCC- and Visual-Studio-compatible output. + switch (format_) { + case CommandLineInterface::ERROR_FORMAT_GCC: + cerr << ":" << (line + 1) << ":" << (column + 1); + break; + case CommandLineInterface::ERROR_FORMAT_MSVS: + cerr << "(" << (line + 1) << ") : error in column=" << (column + 1); + break; + } + } + + cerr << ": " << message << endl; + } + + // implements io::ErrorCollector ----------------------------------- + void AddError(int line, int column, const string& message) { + AddError("input", line, column, message); + } + + private: + const ErrorFormat format_; + DiskSourceTree *tree_; +}; + +// ------------------------------------------------------------------- + +// A GeneratorContext implementation that buffers files in memory, then dumps +// them all to disk on demand. +class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { + public: + GeneratorContextImpl(const vector& parsed_files); + ~GeneratorContextImpl(); + + // Write all files in the directory to disk at the given output location, + // which must end in a '/'. + bool WriteAllToDisk(const string& prefix); + + // Write the contents of this directory to a ZIP-format archive with the + // given name. + bool WriteAllToZip(const string& filename); + + // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR + // format, unless one has already been written. + void AddJarManifest(); + + // implements GeneratorContext -------------------------------------- + io::ZeroCopyOutputStream* Open(const string& filename); + io::ZeroCopyOutputStream* OpenForInsert( + const string& filename, const string& insertion_point); + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } + + private: + friend class MemoryOutputStream; + + // map instead of hash_map so that files are written in order (good when + // writing zips). + map files_; + const vector& parsed_files_; + bool had_error_; +}; + +class CommandLineInterface::MemoryOutputStream + : public io::ZeroCopyOutputStream { + public: + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename); + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, + const string& insertion_point); + virtual ~MemoryOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + virtual bool Next(void** data, int* size) { return inner_->Next(data, size); } + virtual void BackUp(int count) { inner_->BackUp(count); } + virtual int64 ByteCount() const { return inner_->ByteCount(); } + + private: + // Where to insert the string when it's done. + GeneratorContextImpl* directory_; + string filename_; + string insertion_point_; + + // The string we're building. + string data_; + + // StringOutputStream writing to data_. + scoped_ptr inner_; +}; + +// ------------------------------------------------------------------- + +CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( + const vector& parsed_files) + : parsed_files_(parsed_files), + had_error_(false) { +} + +CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { + STLDeleteValues(&files_); +} + +bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( + const string& prefix) { + if (had_error_) { + return false; + } + + if (!VerifyDirectoryExists(prefix)) { + return false; + } + + for (map::const_iterator iter = files_.begin(); + iter != files_.end(); ++iter) { + const string& relative_filename = iter->first; + const char* data = iter->second->data(); + int size = iter->second->size(); + + if (!TryCreateParentDirectory(prefix, relative_filename)) { + return false; + } + string filename = prefix + relative_filename; + + // Create the output file. + int file_descriptor; + do { + file_descriptor = + open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + } while (file_descriptor < 0 && errno == EINTR); + + if (file_descriptor < 0) { + int error = errno; + cerr << filename << ": " << strerror(error); + return false; + } + + // Write the file. + while (size > 0) { + int write_result; + do { + write_result = write(file_descriptor, data, size); + } while (write_result < 0 && errno == EINTR); + + if (write_result <= 0) { + // Write error. + + // FIXME(kenton): According to the man page, if write() returns zero, + // there was no error; write() simply did not write anything. It's + // unclear under what circumstances this might happen, but presumably + // errno won't be set in this case. I am confused as to how such an + // event should be handled. For now I'm treating it as an error, + // since retrying seems like it could lead to an infinite loop. I + // suspect this never actually happens anyway. + + if (write_result < 0) { + int error = errno; + cerr << filename << ": write: " << strerror(error); + } else { + cerr << filename << ": write() returned zero?" << endl; + } + return false; + } + + data += write_result; + size -= write_result; + } + + if (close(file_descriptor) != 0) { + int error = errno; + cerr << filename << ": close: " << strerror(error); + return false; + } + } + + return true; +} + +bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( + const string& filename) { + if (had_error_) { + return false; + } + + // Create the output file. + int file_descriptor; + do { + file_descriptor = + open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + } while (file_descriptor < 0 && errno == EINTR); + + if (file_descriptor < 0) { + int error = errno; + cerr << filename << ": " << strerror(error); + return false; + } + + // Create the ZipWriter + io::FileOutputStream stream(file_descriptor); + ZipWriter zip_writer(&stream); + + for (map::const_iterator iter = files_.begin(); + iter != files_.end(); ++iter) { + zip_writer.Write(iter->first, *iter->second); + } + + zip_writer.WriteDirectory(); + + if (stream.GetErrno() != 0) { + cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + } + + if (!stream.Close()) { + cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + } + + return true; +} + +void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { + string** map_slot = &files_["META-INF/MANIFEST.MF"]; + if (*map_slot == NULL) { + *map_slot = new string( + "Manifest-Version: 1.0\n" + "Created-By: 1.6.0 (protoc)\n" + "\n"); + } +} + +io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( + const string& filename) { + return new MemoryOutputStream(this, filename); +} + +io::ZeroCopyOutputStream* +CommandLineInterface::GeneratorContextImpl::OpenForInsert( + const string& filename, const string& insertion_point) { + return new MemoryOutputStream(this, filename, insertion_point); +} + +// ------------------------------------------------------------------- + +CommandLineInterface::MemoryOutputStream::MemoryOutputStream( + GeneratorContextImpl* directory, const string& filename) + : directory_(directory), + filename_(filename), + inner_(new io::StringOutputStream(&data_)) { +} + +CommandLineInterface::MemoryOutputStream::MemoryOutputStream( + GeneratorContextImpl* directory, const string& filename, + const string& insertion_point) + : directory_(directory), + filename_(filename), + insertion_point_(insertion_point), + inner_(new io::StringOutputStream(&data_)) { +} + +CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { + // Make sure all data has been written. + inner_.reset(); + + // Insert into the directory. + string** map_slot = &directory_->files_[filename_]; + + if (insertion_point_.empty()) { + // This was just a regular Open(). + if (*map_slot != NULL) { + cerr << filename_ << ": Tried to write the same file twice." << endl; + directory_->had_error_ = true; + return; + } + + *map_slot = new string; + (*map_slot)->swap(data_); + } else { + // This was an OpenForInsert(). + + // If the data doens't end with a clean line break, add one. + if (!data_.empty() && data_[data_.size() - 1] != '\n') { + data_.push_back('\n'); + } + + // Find the file we are going to insert into. + if (*map_slot == NULL) { + cerr << filename_ << ": Tried to insert into file that doesn't exist." + << endl; + directory_->had_error_ = true; + return; + } + string* target = *map_slot; + + // Find the insertion point. + string magic_string = strings::Substitute( + "@@protoc_insertion_point($0)", insertion_point_); + string::size_type pos = target->find(magic_string); + + if (pos == string::npos) { + cerr << filename_ << ": insertion point \"" << insertion_point_ + << "\" not found." << endl; + directory_->had_error_ = true; + return; + } + + // Seek backwards to the beginning of the line, which is where we will + // insert the data. Note that this has the effect of pushing the insertion + // point down, so the data is inserted before it. This is intentional + // because it means that multiple insertions at the same point will end + // up in the expected order in the final output. + pos = target->find_last_of('\n', pos); + if (pos == string::npos) { + // Insertion point is on the first line. + pos = 0; + } else { + // Advance to character after '\n'. + ++pos; + } + + // Extract indent. + string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos); + + if (indent_.empty()) { + // No indent. This makes things easier. + target->insert(pos, data_); + } else { + // Calculate how much space we need. + int indent_size = 0; + for (int i = 0; i < data_.size(); i++) { + if (data_[i] == '\n') indent_size += indent_.size(); + } + + // Make a hole for it. + target->insert(pos, data_.size() + indent_size, '\0'); + + // Now copy in the data. + string::size_type data_pos = 0; + char* target_ptr = string_as_array(target) + pos; + while (data_pos < data_.size()) { + // Copy indent. + memcpy(target_ptr, indent_.data(), indent_.size()); + target_ptr += indent_.size(); + + // Copy line from data_. + // We already guaranteed that data_ ends with a newline (above), so this + // search can't fail. + string::size_type line_length = + data_.find_first_of('\n', data_pos) + 1 - data_pos; + memcpy(target_ptr, data_.data() + data_pos, line_length); + target_ptr += line_length; + data_pos += line_length; + } + + GOOGLE_CHECK_EQ(target_ptr, + string_as_array(target) + pos + data_.size() + indent_size); + } + } +} + +// =================================================================== + +CommandLineInterface::CommandLineInterface() + : mode_(MODE_COMPILE), + error_format_(ERROR_FORMAT_GCC), + imports_in_descriptor_set_(false), + source_info_in_descriptor_set_(false), + disallow_services_(false), + inputs_are_proto_path_relative_(false) {} +CommandLineInterface::~CommandLineInterface() {} + +void CommandLineInterface::RegisterGenerator(const string& flag_name, + CodeGenerator* generator, + const string& help_text) { + GeneratorInfo info; + info.flag_name = flag_name; + info.generator = generator; + info.help_text = help_text; + generators_by_flag_name_[flag_name] = info; +} + +void CommandLineInterface::RegisterGenerator(const string& flag_name, + const string& option_flag_name, + CodeGenerator* generator, + const string& help_text) { + GeneratorInfo info; + info.flag_name = flag_name; + info.option_flag_name = option_flag_name; + info.generator = generator; + info.help_text = help_text; + generators_by_flag_name_[flag_name] = info; + generators_by_option_name_[option_flag_name] = info; +} + +void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { + plugin_prefix_ = exe_name_prefix; +} + +int CommandLineInterface::Run(int argc, const char* const argv[]) { + Clear(); + switch (ParseArguments(argc, argv)) { + case PARSE_ARGUMENT_DONE_AND_EXIT: + return 0; + case PARSE_ARGUMENT_FAIL: + return 1; + case PARSE_ARGUMENT_DONE_AND_CONTINUE: + break; + } + + // Set up the source tree. + DiskSourceTree source_tree; + for (int i = 0; i < proto_path_.size(); i++) { + source_tree.MapPath(proto_path_[i].first, proto_path_[i].second); + } + + // Map input files to virtual paths if necessary. + if (!inputs_are_proto_path_relative_) { + if (!MakeInputsBeProtoPathRelative(&source_tree)) { + return 1; + } + } + + // Allocate the Importer. + ErrorPrinter error_collector(error_format_, &source_tree); + Importer importer(&source_tree, &error_collector); + + vector parsed_files; + + // Parse each file. + for (int i = 0; i < input_files_.size(); i++) { + // Import the file. + const FileDescriptor* parsed_file = importer.Import(input_files_[i]); + if (parsed_file == NULL) return 1; + parsed_files.push_back(parsed_file); + + // Enforce --disallow_services. + if (disallow_services_ && parsed_file->service_count() > 0) { + cerr << parsed_file->name() << ": This file contains services, but " + "--disallow_services was used." << endl; + return 1; + } + } + + // We construct a separate GeneratorContext for each output location. Note + // that two code generators may output to the same location, in which case + // they should share a single GeneratorContext so that OpenForInsert() works. + typedef hash_map GeneratorContextMap; + GeneratorContextMap output_directories; + + // Generate output. + if (mode_ == MODE_COMPILE) { + for (int i = 0; i < output_directives_.size(); i++) { + string output_location = output_directives_[i].output_location; + if (!HasSuffixString(output_location, ".zip") && + !HasSuffixString(output_location, ".jar")) { + AddTrailingSlash(&output_location); + } + GeneratorContextImpl** map_slot = &output_directories[output_location]; + + if (*map_slot == NULL) { + // First time we've seen this output location. + *map_slot = new GeneratorContextImpl(parsed_files); + } + + if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { + STLDeleteValues(&output_directories); + return 1; + } + } + } + + // Write all output to disk. + for (GeneratorContextMap::iterator iter = output_directories.begin(); + iter != output_directories.end(); ++iter) { + const string& location = iter->first; + GeneratorContextImpl* directory = iter->second; + if (HasSuffixString(location, "/")) { + if (!directory->WriteAllToDisk(location)) { + STLDeleteValues(&output_directories); + return 1; + } + } else { + if (HasSuffixString(location, ".jar")) { + directory->AddJarManifest(); + } + + if (!directory->WriteAllToZip(location)) { + STLDeleteValues(&output_directories); + return 1; + } + } + } + + STLDeleteValues(&output_directories); + + if (!descriptor_set_name_.empty()) { + if (!WriteDescriptorSet(parsed_files)) { + return 1; + } + } + + if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) { + if (codec_type_.empty()) { + // HACK: Define an EmptyMessage type to use for decoding. + DescriptorPool pool; + FileDescriptorProto file; + file.set_name("empty_message.proto"); + file.add_message_type()->set_name("EmptyMessage"); + GOOGLE_CHECK(pool.BuildFile(file) != NULL); + codec_type_ = "EmptyMessage"; + if (!EncodeOrDecode(&pool)) { + return 1; + } + } else { + if (!EncodeOrDecode(importer.pool())) { + return 1; + } + } + } + + return 0; +} + +void CommandLineInterface::Clear() { + // Clear all members that are set by Run(). Note that we must not clear + // members which are set by other methods before Run() is called. + executable_name_.clear(); + proto_path_.clear(); + input_files_.clear(); + output_directives_.clear(); + codec_type_.clear(); + descriptor_set_name_.clear(); + + mode_ = MODE_COMPILE; + imports_in_descriptor_set_ = false; + source_info_in_descriptor_set_ = false; + disallow_services_ = false; +} + +bool CommandLineInterface::MakeInputsBeProtoPathRelative( + DiskSourceTree* source_tree) { + for (int i = 0; i < input_files_.size(); i++) { + string virtual_file, shadowing_disk_file; + switch (source_tree->DiskFileToVirtualFile( + input_files_[i], &virtual_file, &shadowing_disk_file)) { + case DiskSourceTree::SUCCESS: + input_files_[i] = virtual_file; + break; + case DiskSourceTree::SHADOWED: + cerr << input_files_[i] << ": Input is shadowed in the --proto_path " + "by \"" << shadowing_disk_file << "\". Either use the latter " + "file as your input or reorder the --proto_path so that the " + "former file's location comes first." << endl; + return false; + case DiskSourceTree::CANNOT_OPEN: + cerr << input_files_[i] << ": " << strerror(errno) << endl; + return false; + case DiskSourceTree::NO_MAPPING: + // First check if the file exists at all. + if (access(input_files_[i].c_str(), F_OK) < 0) { + // File does not even exist. + cerr << input_files_[i] << ": " << strerror(ENOENT) << endl; + } else { + cerr << input_files_[i] << ": File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think)." << endl; + } + return false; + } + } + + return true; +} + +CommandLineInterface::ParseArgumentStatus +CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { + executable_name_ = argv[0]; + + // Iterate through all arguments and parse them. + for (int i = 1; i < argc; i++) { + string name, value; + + if (ParseArgument(argv[i], &name, &value)) { + // Returned true => Use the next argument as the flag value. + if (i + 1 == argc || argv[i+1][0] == '-') { + cerr << "Missing value for flag: " << name << endl; + if (name == "--decode") { + cerr << "To decode an unknown message, use --decode_raw." << endl; + } + return PARSE_ARGUMENT_FAIL; + } else { + ++i; + value = argv[i]; + } + } + + ParseArgumentStatus status = InterpretArgument(name, value); + if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) + return status; + } + + // If no --proto_path was given, use the current working directory. + if (proto_path_.empty()) { + // Don't use make_pair as the old/default standard library on Solaris + // doesn't support it without explicit template parameters, which are + // incompatible with C++0x's make_pair. + proto_path_.push_back(pair("", ".")); + } + + // Check some errror cases. + bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); + if (decoding_raw && !input_files_.empty()) { + cerr << "When using --decode_raw, no input files should be given." << endl; + return PARSE_ARGUMENT_FAIL; + } else if (!decoding_raw && input_files_.empty()) { + cerr << "Missing input file." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (mode_ == MODE_COMPILE && output_directives_.empty() && + descriptor_set_name_.empty()) { + cerr << "Missing output directives." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { + cerr << "--include_imports only makes sense when combined with " + "--descriptor_set_out." << endl; + } + if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { + cerr << "--include_source_info only makes sense when combined with " + "--descriptor_set_out." << endl; + } + + return PARSE_ARGUMENT_DONE_AND_CONTINUE; +} + +bool CommandLineInterface::ParseArgument(const char* arg, + string* name, string* value) { + bool parsed_value = false; + + if (arg[0] != '-') { + // Not a flag. + name->clear(); + parsed_value = true; + *value = arg; + } else if (arg[1] == '-') { + // Two dashes: Multi-character name, with '=' separating name and + // value. + const char* equals_pos = strchr(arg, '='); + if (equals_pos != NULL) { + *name = string(arg, equals_pos - arg); + *value = equals_pos + 1; + parsed_value = true; + } else { + *name = arg; + } + } else { + // One dash: One-character name, all subsequent characters are the + // value. + if (arg[1] == '\0') { + // arg is just "-". We treat this as an input file, except that at + // present this will just lead to a "file not found" error. + name->clear(); + *value = arg; + parsed_value = true; + } else { + *name = string(arg, 2); + *value = arg + 2; + parsed_value = !value->empty(); + } + } + + // Need to return true iff the next arg should be used as the value for this + // one, false otherwise. + + if (parsed_value) { + // We already parsed a value for this flag. + return false; + } + + if (*name == "-h" || *name == "--help" || + *name == "--disallow_services" || + *name == "--include_imports" || + *name == "--include_source_info" || + *name == "--version" || + *name == "--decode_raw") { + // HACK: These are the only flags that don't take a value. + // They probably should not be hard-coded like this but for now it's + // not worth doing better. + return false; + } + + // Next argument is the flag value. + return true; +} + +CommandLineInterface::ParseArgumentStatus +CommandLineInterface::InterpretArgument(const string& name, + const string& value) { + if (name.empty()) { + // Not a flag. Just a filename. + if (value.empty()) { + cerr << "You seem to have passed an empty string as one of the " + "arguments to " << executable_name_ << ". This is actually " + "sort of hard to do. Congrats. Unfortunately it is not valid " + "input so the program is going to die now." << endl; + return PARSE_ARGUMENT_FAIL; + } + + input_files_.push_back(value); + + } else if (name == "-I" || name == "--proto_path") { + // Java's -classpath (and some other languages) delimits path components + // with colons. Let's accept that syntax too just to make things more + // intuitive. + vector parts; + SplitStringUsing(value, kPathSeparator, &parts); + + for (int i = 0; i < parts.size(); i++) { + string virtual_path; + string disk_path; + + string::size_type equals_pos = parts[i].find_first_of('='); + if (equals_pos == string::npos) { + virtual_path = ""; + disk_path = parts[i]; + } else { + virtual_path = parts[i].substr(0, equals_pos); + disk_path = parts[i].substr(equals_pos + 1); + } + + if (disk_path.empty()) { + cerr << "--proto_path passed empty directory name. (Use \".\" for " + "current directory.)" << endl; + return PARSE_ARGUMENT_FAIL; + } + + // Make sure disk path exists, warn otherwise. + if (access(disk_path.c_str(), F_OK) < 0) { + cerr << disk_path << ": warning: directory does not exist." << endl; + } + + // Don't use make_pair as the old/default standard library on Solaris + // doesn't support it without explicit template parameters, which are + // incompatible with C++0x's make_pair. + proto_path_.push_back(pair(virtual_path, disk_path)); + } + + } else if (name == "-o" || name == "--descriptor_set_out") { + if (!descriptor_set_name_.empty()) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (value.empty()) { + cerr << name << " requires a non-empty value." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use --encode or --decode and generate descriptors at the " + "same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + descriptor_set_name_ = value; + + } else if (name == "--include_imports") { + if (imports_in_descriptor_set_) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + imports_in_descriptor_set_ = true; + + } else if (name == "--include_source_info") { + if (source_info_in_descriptor_set_) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + source_info_in_descriptor_set_ = true; + + } else if (name == "-h" || name == "--help") { + PrintHelpText(); + return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. + + } else if (name == "--version") { + if (!version_info_.empty()) { + cout << version_info_ << endl; + } + cout << "libprotoc " + << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) + << endl; + return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. + + } else if (name == "--disallow_services") { + disallow_services_ = true; + + } else if (name == "--encode" || name == "--decode" || + name == "--decode_raw") { + if (mode_ != MODE_COMPILE) { + cerr << "Only one of --encode and --decode can be specified." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!output_directives_.empty() || !descriptor_set_name_.empty()) { + cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + + mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; + + if (value.empty() && name != "--decode_raw") { + cerr << "Type name for " << name << " cannot be blank." << endl; + if (name == "--decode") { + cerr << "To decode an unknown message, use --decode_raw." << endl; + } + return PARSE_ARGUMENT_FAIL; + } else if (!value.empty() && name == "--decode_raw") { + cerr << "--decode_raw does not take a parameter." << endl; + return PARSE_ARGUMENT_FAIL; + } + + codec_type_ = value; + + } else if (name == "--error_format") { + if (value == "gcc") { + error_format_ = ERROR_FORMAT_GCC; + } else if (value == "msvs") { + error_format_ = ERROR_FORMAT_MSVS; + } else { + cerr << "Unknown error format: " << value << endl; + return PARSE_ARGUMENT_FAIL; + } + + } else if (name == "--plugin") { + if (plugin_prefix_.empty()) { + cerr << "This compiler does not support plugins." << endl; + return PARSE_ARGUMENT_FAIL; + } + + string plugin_name; + string path; + + string::size_type equals_pos = value.find_first_of('='); + if (equals_pos == string::npos) { + // Use the basename of the file. + string::size_type slash_pos = value.find_last_of('/'); + if (slash_pos == string::npos) { + plugin_name = value; + } else { + plugin_name = value.substr(slash_pos + 1); + } + path = value; + } else { + plugin_name = value.substr(0, equals_pos); + path = value.substr(equals_pos + 1); + } + + plugins_[plugin_name] = path; + + } else { + // Some other flag. Look it up in the generators list. + const GeneratorInfo* generator_info = + FindOrNull(generators_by_flag_name_, name); + if (generator_info == NULL && + (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { + // Check if it's a generator option flag. + generator_info = FindOrNull(generators_by_option_name_, name); + if (generator_info == NULL) { + cerr << "Unknown flag: " << name << endl; + return PARSE_ARGUMENT_FAIL; + } else { + string* parameters = &generator_parameters_[generator_info->flag_name]; + if (!parameters->empty()) { + parameters->append(","); + } + parameters->append(value); + } + } else { + // It's an output flag. Add it to the output directives. + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use --encode or --decode and generate code at the " + "same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + + OutputDirective directive; + directive.name = name; + if (generator_info == NULL) { + directive.generator = NULL; + } else { + directive.generator = generator_info->generator; + } + + // Split value at ':' to separate the generator parameter from the + // filename. However, avoid doing this if the colon is part of a valid + // Windows-style absolute path. + string::size_type colon_pos = value.find_first_of(':'); + if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { + directive.output_location = value; + } else { + directive.parameter = value.substr(0, colon_pos); + directive.output_location = value.substr(colon_pos + 1); + } + + output_directives_.push_back(directive); + } + } + + return PARSE_ARGUMENT_DONE_AND_CONTINUE; +} + +void CommandLineInterface::PrintHelpText() { + // Sorry for indentation here; line wrapping would be uglier. + cerr << +"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n" +"Parse PROTO_FILES and generate output based on the options given:\n" +" -IPATH, --proto_path=PATH Specify the directory in which to search for\n" +" imports. May be specified multiple times;\n" +" directories will be searched in order. If not\n" +" given, the current working directory is used.\n" +" --version Show version info and exit.\n" +" -h, --help Show this text and exit.\n" +" --encode=MESSAGE_TYPE Read a text-format message of the given type\n" +" from standard input and write it in binary\n" +" to standard output. The message type must\n" +" be defined in PROTO_FILES or their imports.\n" +" --decode=MESSAGE_TYPE Read a binary message of the given type from\n" +" standard input and write it in text format\n" +" to standard output. The message type must\n" +" be defined in PROTO_FILES or their imports.\n" +" --decode_raw Read an arbitrary protocol message from\n" +" standard input and write the raw tag/value\n" +" pairs in text format to standard output. No\n" +" PROTO_FILES should be given when using this\n" +" flag.\n" +" -oFILE, Writes a FileDescriptorSet (a protocol buffer,\n" +" --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n" +" the input files to FILE.\n" +" --include_imports When using --descriptor_set_out, also include\n" +" all dependencies of the input files in the\n" +" set, so that the set is self-contained.\n" +" --include_source_info When using --descriptor_set_out, do not strip\n" +" SourceCodeInfo from the FileDescriptorProto.\n" +" This results in vastly larger descriptors that\n" +" include information about the original\n" +" location of each decl in the source file as\n" +" well as surrounding comments.\n" +" --error_format=FORMAT Set the format in which to print errors.\n" +" FORMAT may be 'gcc' (the default) or 'msvs'\n" +" (Microsoft Visual Studio format)." << endl; + if (!plugin_prefix_.empty()) { + cerr << +" --plugin=EXECUTABLE Specifies a plugin executable to use.\n" +" Normally, protoc searches the PATH for\n" +" plugins, but you may specify additional\n" +" executables not in the path using this flag.\n" +" Additionally, EXECUTABLE may be of the form\n" +" NAME=PATH, in which case the given plugin name\n" +" is mapped to the given executable even if\n" +" the executable's own name differs." << endl; + } + + for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); + iter != generators_by_flag_name_.end(); ++iter) { + // FIXME(kenton): If the text is long enough it will wrap, which is ugly, + // but fixing this nicely (e.g. splitting on spaces) is probably more + // trouble than it's worth. + cerr << " " << iter->first << "=OUT_DIR " + << string(19 - iter->first.size(), ' ') // Spaces for alignment. + << iter->second.help_text << endl; + } +} + +bool CommandLineInterface::GenerateOutput( + const vector& parsed_files, + const OutputDirective& output_directive, + GeneratorContext* generator_context) { + // Call the generator. + string error; + if (output_directive.generator == NULL) { + // This is a plugin. + GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && + HasSuffixString(output_directive.name, "_out")) + << "Bad name for plugin generator: " << output_directive.name; + + // Strip the "--" and "_out" and add the plugin prefix. + string plugin_name = plugin_prefix_ + "gen-" + + output_directive.name.substr(2, output_directive.name.size() - 6); + + if (!GeneratePluginOutput(parsed_files, plugin_name, + output_directive.parameter, + generator_context, &error)) { + cerr << output_directive.name << ": " << error << endl; + return false; + } + } else { + // Regular generator. + string parameters = output_directive.parameter; + if (!generator_parameters_[output_directive.name].empty()) { + if (!parameters.empty()) { + parameters.append(","); + } + parameters.append(generator_parameters_[output_directive.name]); + } + for (int i = 0; i < parsed_files.size(); i++) { + if (!output_directive.generator->Generate(parsed_files[i], parameters, + generator_context, &error)) { + // Generator returned an error. + cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " + << error << endl; + return false; + } + } + } + + return true; +} + +bool CommandLineInterface::GeneratePluginOutput( + const vector& parsed_files, + const string& plugin_name, + const string& parameter, + GeneratorContext* generator_context, + string* error) { + CodeGeneratorRequest request; + CodeGeneratorResponse response; + + // Build the request. + if (!parameter.empty()) { + request.set_parameter(parameter); + } + + set already_seen; + for (int i = 0; i < parsed_files.size(); i++) { + request.add_file_to_generate(parsed_files[i]->name()); + GetTransitiveDependencies(parsed_files[i], + true, // Include source code info. + &already_seen, request.mutable_proto_file()); + } + + // Invoke the plugin. + Subprocess subprocess; + + if (plugins_.count(plugin_name) > 0) { + subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME); + } else { + subprocess.Start(plugin_name, Subprocess::SEARCH_PATH); + } + + string communicate_error; + if (!subprocess.Communicate(request, &response, &communicate_error)) { + *error = strings::Substitute("$0: $1", plugin_name, communicate_error); + return false; + } + + // Write the files. We do this even if there was a generator error in order + // to match the behavior of a compiled-in generator. + scoped_ptr current_output; + for (int i = 0; i < response.file_size(); i++) { + const CodeGeneratorResponse::File& output_file = response.file(i); + + if (!output_file.insertion_point().empty()) { + // Open a file for insert. + // We reset current_output to NULL first so that the old file is closed + // before the new one is opened. + current_output.reset(); + current_output.reset(generator_context->OpenForInsert( + output_file.name(), output_file.insertion_point())); + } else if (!output_file.name().empty()) { + // Starting a new file. Open it. + // We reset current_output to NULL first so that the old file is closed + // before the new one is opened. + current_output.reset(); + current_output.reset(generator_context->Open(output_file.name())); + } else if (current_output == NULL) { + *error = strings::Substitute( + "$0: First file chunk returned by plugin did not specify a file name.", + plugin_name); + return false; + } + + // Use CodedOutputStream for convenience; otherwise we'd need to provide + // our own buffer-copying loop. + io::CodedOutputStream writer(current_output.get()); + writer.WriteString(output_file.content()); + } + + // Check for errors. + if (!response.error().empty()) { + // Generator returned an error. + *error = response.error(); + return false; + } + + return true; +} + +bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { + // Look up the type. + const Descriptor* type = pool->FindMessageTypeByName(codec_type_); + if (type == NULL) { + cerr << "Type not defined: " << codec_type_ << endl; + return false; + } + + DynamicMessageFactory dynamic_factory(pool); + scoped_ptr message(dynamic_factory.GetPrototype(type)->New()); + + if (mode_ == MODE_ENCODE) { + SetFdToTextMode(STDIN_FILENO); + SetFdToBinaryMode(STDOUT_FILENO); + } else { + SetFdToBinaryMode(STDIN_FILENO); + SetFdToTextMode(STDOUT_FILENO); + } + + io::FileInputStream in(STDIN_FILENO); + io::FileOutputStream out(STDOUT_FILENO); + + if (mode_ == MODE_ENCODE) { + // Input is text. + ErrorPrinter error_collector(error_format_); + TextFormat::Parser parser; + parser.RecordErrorsTo(&error_collector); + parser.AllowPartialMessage(true); + + if (!parser.Parse(&in, message.get())) { + cerr << "Failed to parse input." << endl; + return false; + } + } else { + // Input is binary. + if (!message->ParsePartialFromZeroCopyStream(&in)) { + cerr << "Failed to parse input." << endl; + return false; + } + } + + if (!message->IsInitialized()) { + cerr << "warning: Input message is missing required fields: " + << message->InitializationErrorString() << endl; + } + + if (mode_ == MODE_ENCODE) { + // Output is binary. + if (!message->SerializePartialToZeroCopyStream(&out)) { + cerr << "output: I/O error." << endl; + return false; + } + } else { + // Output is text. + if (!TextFormat::Print(*message, &out)) { + cerr << "output: I/O error." << endl; + return false; + } + } + + return true; +} + +bool CommandLineInterface::WriteDescriptorSet( + const vector parsed_files) { + FileDescriptorSet file_set; + + if (imports_in_descriptor_set_) { + set already_seen; + for (int i = 0; i < parsed_files.size(); i++) { + GetTransitiveDependencies(parsed_files[i], + source_info_in_descriptor_set_, + &already_seen, file_set.mutable_file()); + } + } else { + for (int i = 0; i < parsed_files.size(); i++) { + FileDescriptorProto* file_proto = file_set.add_file(); + parsed_files[i]->CopyTo(file_proto); + if (source_info_in_descriptor_set_) { + parsed_files[i]->CopySourceCodeInfoTo(file_proto); + } + } + } + + int fd; + do { + fd = open(descriptor_set_name_.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + } while (fd < 0 && errno == EINTR); + + if (fd < 0) { + perror(descriptor_set_name_.c_str()); + return false; + } + + io::FileOutputStream out(fd); + if (!file_set.SerializeToZeroCopyStream(&out)) { + cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + out.Close(); + return false; + } + if (!out.Close()) { + cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + return false; + } + + return true; +} + +void CommandLineInterface::GetTransitiveDependencies( + const FileDescriptor* file, bool include_source_code_info, + set* already_seen, + RepeatedPtrField* output) { + if (!already_seen->insert(file).second) { + // Already saw this file. Skip. + return; + } + + // Add all dependencies. + for (int i = 0; i < file->dependency_count(); i++) { + GetTransitiveDependencies(file->dependency(i), include_source_code_info, + already_seen, output); + } + + // Add this file. + FileDescriptorProto* new_descriptor = output->Add(); + file->CopyTo(new_descriptor); + if (include_source_code_info) { + file->CopySourceCodeInfoTo(new_descriptor); + } +} + + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.h new file mode 100644 index 000000000..86ea9bde2 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface.h @@ -0,0 +1,353 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Implements the Protocol Compiler front-end such that it may be reused by +// custom compilers written to support other languages. + +#ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ +#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +class FileDescriptor; // descriptor.h +class DescriptorPool; // descriptor.h +class FileDescriptorProto; // descriptor.pb.h +template class RepeatedPtrField; // repeated_field.h + +namespace compiler { + +class CodeGenerator; // code_generator.h +class GeneratorContext; // code_generator.h +class DiskSourceTree; // importer.h + +// This class implements the command-line interface to the protocol compiler. +// It is designed to make it very easy to create a custom protocol compiler +// supporting the languages of your choice. For example, if you wanted to +// create a custom protocol compiler binary which includes both the regular +// C++ support plus support for your own custom output "Foo", you would +// write a class "FooGenerator" which implements the CodeGenerator interface, +// then write a main() procedure like this: +// +// int main(int argc, char* argv[]) { +// google::protobuf::compiler::CommandLineInterface cli; +// +// // Support generation of C++ source and headers. +// google::protobuf::compiler::cpp::CppGenerator cpp_generator; +// cli.RegisterGenerator("--cpp_out", &cpp_generator, +// "Generate C++ source and header."); +// +// // Support generation of Foo code. +// FooGenerator foo_generator; +// cli.RegisterGenerator("--foo_out", &foo_generator, +// "Generate Foo file."); +// +// return cli.Run(argc, argv); +// } +// +// The compiler is invoked with syntax like: +// protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto +// +// For a full description of the command-line syntax, invoke it with --help. +class LIBPROTOC_EXPORT CommandLineInterface { + public: + CommandLineInterface(); + ~CommandLineInterface(); + + // Register a code generator for a language. + // + // Parameters: + // * flag_name: The command-line flag used to specify an output file of + // this type. The name must start with a '-'. If the name is longer + // than one letter, it must start with two '-'s. + // * generator: The CodeGenerator which will be called to generate files + // of this type. + // * help_text: Text describing this flag in the --help output. + // + // Some generators accept extra parameters. You can specify this parameter + // on the command-line by placing it before the output directory, separated + // by a colon: + // protoc --foo_out=enable_bar:outdir + // The text before the colon is passed to CodeGenerator::Generate() as the + // "parameter". + void RegisterGenerator(const string& flag_name, + CodeGenerator* generator, + const string& help_text); + + // Register a code generator for a language. + // Besides flag_name you can specify another option_flag_name that could be + // used to pass extra parameters to the registered code generator. + // Suppose you have registered a generator by calling: + // command_line_interface.RegisterGenerator("--foo_out", "--foo_opt", ...) + // Then you could invoke the compiler with a command like: + // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz + // This will pass "enable_bar,enable_baz" as the parameter to the generator. + void RegisterGenerator(const string& flag_name, + const string& option_flag_name, + CodeGenerator* generator, + const string& help_text); + + // Enables "plugins". In this mode, if a command-line flag ends with "_out" + // but does not match any registered generator, the compiler will attempt to + // find a "plugin" to implement the generator. Plugins are just executables. + // They should live somewhere in the PATH. + // + // The compiler determines the executable name to search for by concatenating + // exe_name_prefix with the unrecognized flag name, removing "_out". So, for + // example, if exe_name_prefix is "protoc-" and you pass the flag --foo_out, + // the compiler will try to run the program "protoc-foo". + // + // The plugin program should implement the following usage: + // plugin [--out=OUTDIR] [--parameter=PARAMETER] PROTO_FILES < DESCRIPTORS + // --out indicates the output directory (as passed to the --foo_out + // parameter); if omitted, the current directory should be used. --parameter + // gives the generator parameter, if any was provided. The PROTO_FILES list + // the .proto files which were given on the compiler command-line; these are + // the files for which the plugin is expected to generate output code. + // Finally, DESCRIPTORS is an encoded FileDescriptorSet (as defined in + // descriptor.proto). This is piped to the plugin's stdin. The set will + // include descriptors for all the files listed in PROTO_FILES as well as + // all files that they import. The plugin MUST NOT attempt to read the + // PROTO_FILES directly -- it must use the FileDescriptorSet. + // + // The plugin should generate whatever files are necessary, as code generators + // normally do. It should write the names of all files it generates to + // stdout. The names should be relative to the output directory, NOT absolute + // names or relative to the current directory. If any errors occur, error + // messages should be written to stderr. If an error is fatal, the plugin + // should exit with a non-zero exit code. + void AllowPlugins(const string& exe_name_prefix); + + // Run the Protocol Compiler with the given command-line parameters. + // Returns the error code which should be returned by main(). + // + // It may not be safe to call Run() in a multi-threaded environment because + // it calls strerror(). I'm not sure why you'd want to do this anyway. + int Run(int argc, const char* const argv[]); + + // Call SetInputsAreCwdRelative(true) if the input files given on the command + // line should be interpreted relative to the proto import path specified + // using --proto_path or -I flags. Otherwise, input file names will be + // interpreted relative to the current working directory (or as absolute + // paths if they start with '/'), though they must still reside inside + // a directory given by --proto_path or the compiler will fail. The latter + // mode is generally more intuitive and easier to use, especially e.g. when + // defining implicit rules in Makefiles. + void SetInputsAreProtoPathRelative(bool enable) { + inputs_are_proto_path_relative_ = enable; + } + + // Provides some text which will be printed when the --version flag is + // used. The version of libprotoc will also be printed on the next line + // after this text. + void SetVersionInfo(const string& text) { + version_info_ = text; + } + + + private: + // ----------------------------------------------------------------- + + class ErrorPrinter; + class GeneratorContextImpl; + class MemoryOutputStream; + + // Clear state from previous Run(). + void Clear(); + + // Remaps each file in input_files_ so that it is relative to one of the + // directories in proto_path_. Returns false if an error occurred. This + // is only used if inputs_are_proto_path_relative_ is false. + bool MakeInputsBeProtoPathRelative( + DiskSourceTree* source_tree); + + // Return status for ParseArguments() and InterpretArgument(). + enum ParseArgumentStatus { + PARSE_ARGUMENT_DONE_AND_CONTINUE, + PARSE_ARGUMENT_DONE_AND_EXIT, + PARSE_ARGUMENT_FAIL + }; + + // Parse all command-line arguments. + ParseArgumentStatus ParseArguments(int argc, const char* const argv[]); + + // Parses a command-line argument into a name/value pair. Returns + // true if the next argument in the argv should be used as the value, + // false otherwise. + // + // Exmaples: + // "-Isrc/protos" -> + // name = "-I", value = "src/protos" + // "--cpp_out=src/foo.pb2.cc" -> + // name = "--cpp_out", value = "src/foo.pb2.cc" + // "foo.proto" -> + // name = "", value = "foo.proto" + bool ParseArgument(const char* arg, string* name, string* value); + + // Interprets arguments parsed with ParseArgument. + ParseArgumentStatus InterpretArgument(const string& name, + const string& value); + + // Print the --help text to stderr. + void PrintHelpText(); + + // Generate the given output file from the given input. + struct OutputDirective; // see below + bool GenerateOutput(const vector& parsed_files, + const OutputDirective& output_directive, + GeneratorContext* generator_context); + bool GeneratePluginOutput(const vector& parsed_files, + const string& plugin_name, + const string& parameter, + GeneratorContext* generator_context, + string* error); + + // Implements --encode and --decode. + bool EncodeOrDecode(const DescriptorPool* pool); + + // Implements the --descriptor_set_out option. + bool WriteDescriptorSet(const vector parsed_files); + + // Get all transitive dependencies of the given file (including the file + // itself), adding them to the given list of FileDescriptorProtos. The + // protos will be ordered such that every file is listed before any file that + // depends on it, so that you can call DescriptorPool::BuildFile() on them + // in order. Any files in *already_seen will not be added, and each file + // added will be inserted into *already_seen. If include_source_code_info is + // true then include the source code information in the FileDescriptorProtos. + static void GetTransitiveDependencies( + const FileDescriptor* file, + bool include_source_code_info, + set* already_seen, + RepeatedPtrField* output); + + // ----------------------------------------------------------------- + + // The name of the executable as invoked (i.e. argv[0]). + string executable_name_; + + // Version info set with SetVersionInfo(). + string version_info_; + + // Registered generators. + struct GeneratorInfo { + string flag_name; + string option_flag_name; + CodeGenerator* generator; + string help_text; + }; + typedef map GeneratorMap; + GeneratorMap generators_by_flag_name_; + GeneratorMap generators_by_option_name_; + // A map from generator names to the parameters specified using the option + // flag. For example, if the user invokes the compiler with: + // protoc --foo_out=outputdir --foo_opt=enable_bar ... + // Then there will be an entry ("--foo_out", "enable_bar") in this map. + map generator_parameters_; + + // See AllowPlugins(). If this is empty, plugins aren't allowed. + string plugin_prefix_; + + // Maps specific plugin names to files. When executing a plugin, this map + // is searched first to find the plugin executable. If not found here, the + // PATH (or other OS-specific search strategy) is searched. + map plugins_; + + // Stuff parsed from command line. + enum Mode { + MODE_COMPILE, // Normal mode: parse .proto files and compile them. + MODE_ENCODE, // --encode: read text from stdin, write binary to stdout. + MODE_DECODE // --decode: read binary from stdin, write text to stdout. + }; + + Mode mode_; + + enum ErrorFormat { + ERROR_FORMAT_GCC, // GCC error output format (default). + ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). + }; + + ErrorFormat error_format_; + + vector > proto_path_; // Search path for proto files. + vector input_files_; // Names of the input proto files. + + // output_directives_ lists all the files we are supposed to output and what + // generator to use for each. + struct OutputDirective { + string name; // E.g. "--foo_out" + CodeGenerator* generator; // NULL for plugins + string parameter; + string output_location; + }; + vector output_directives_; + + // When using --encode or --decode, this names the type we are encoding or + // decoding. (Empty string indicates --decode_raw.) + string codec_type_; + + // If --descriptor_set_out was given, this is the filename to which the + // FileDescriptorSet should be written. Otherwise, empty. + string descriptor_set_name_; + + // True if --include_imports was given, meaning that we should + // write all transitive dependencies to the DescriptorSet. Otherwise, only + // the .proto files listed on the command-line are added. + bool imports_in_descriptor_set_; + + // True if --include_source_info was given, meaning that we should not strip + // SourceCodeInfo from the DescriptorSet. + bool source_info_in_descriptor_set_; + + // Was the --disallow_services flag used? + bool disallow_services_; + + // See SetInputsAreProtoPathRelative(). + bool inputs_are_proto_path_relative_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface); +}; + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc new file mode 100644 index 000000000..165599231 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -0,0 +1,1560 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#ifdef _MSC_VER +#include +#else +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +#if defined(_WIN32) +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#ifndef F_OK +#define F_OK 00 // not defined by MSVC for whatever reason +#endif +#endif + +namespace { + +class CommandLineInterfaceTest : public testing::Test { + protected: + virtual void SetUp(); + virtual void TearDown(); + + // Runs the CommandLineInterface with the given command line. The + // command is automatically split on spaces, and the string "$tmpdir" + // is replaced with TestTempDir(). + void Run(const string& command); + + // ----------------------------------------------------------------- + // Methods to set up the test (called before Run()). + + class NullCodeGenerator; + + // Normally plugins are allowed for all tests. Call this to explicitly + // disable them. + void DisallowPlugins() { disallow_plugins_ = true; } + + // Create a temp file within temp_directory_ with the given name. + // The containing directory is also created if necessary. + void CreateTempFile(const string& name, const string& contents); + + // Create a subdirectory within temp_directory_. + void CreateTempDir(const string& name); + + void SetInputsAreProtoPathRelative(bool enable) { + cli_.SetInputsAreProtoPathRelative(enable); + } + + // ----------------------------------------------------------------- + // Methods to check the test results (called after Run()). + + // Checks that no text was written to stderr during Run(), and Run() + // returned 0. + void ExpectNoErrors(); + + // Checks that Run() returned non-zero and the stderr output is exactly + // the text given. expected_test may contain references to "$tmpdir", + // which will be replaced by the temporary directory path. + void ExpectErrorText(const string& expected_text); + + // Checks that Run() returned non-zero and the stderr contains the given + // substring. + void ExpectErrorSubstring(const string& expected_substring); + + // Like ExpectErrorSubstring, but checks that Run() returned zero. + void ExpectErrorSubstringWithZeroReturnCode( + const string& expected_substring); + + // Returns true if ExpectErrorSubstring(expected_substring) would pass, but + // does not fail otherwise. + bool HasAlternateErrorSubstring(const string& expected_substring); + + // Checks that MockCodeGenerator::Generate() was called in the given + // context (or the generator in test_plugin.cc, which produces the same + // output). That is, this tests if the generator with the given name + // was called with the given parameter and proto file and produced the + // given output file. This is checked by reading the output file and + // checking that it contains the content that MockCodeGenerator would + // generate given these inputs. message_name is the name of the first + // message that appeared in the proto file; this is just to make extra + // sure that the correct file was parsed. + void ExpectGenerated(const string& generator_name, + const string& parameter, + const string& proto_name, + const string& message_name); + void ExpectGenerated(const string& generator_name, + const string& parameter, + const string& proto_name, + const string& message_name, + const string& output_directory); + void ExpectGeneratedWithMultipleInputs(const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name); + void ExpectGeneratedWithInsertions(const string& generator_name, + const string& parameter, + const string& insertions, + const string& proto_name, + const string& message_name); + + void ExpectNullCodeGeneratorCalled(const string& parameter); + + void ReadDescriptorSet(const string& filename, + FileDescriptorSet* descriptor_set); + + private: + // The object we are testing. + CommandLineInterface cli_; + + // Was DisallowPlugins() called? + bool disallow_plugins_; + + // We create a directory within TestTempDir() in order to add extra + // protection against accidentally deleting user files (since we recursively + // delete this directory during the test). This is the full path of that + // directory. + string temp_directory_; + + // The result of Run(). + int return_code_; + + // The captured stderr output. + string error_text_; + + // Pointers which need to be deleted later. + vector mock_generators_to_delete_; + + NullCodeGenerator* null_generator_; +}; + +class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { + public: + NullCodeGenerator() : called_(false) {} + ~NullCodeGenerator() {} + + mutable bool called_; + mutable string parameter_; + + // implements CodeGenerator ---------------------------------------- + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + called_ = true; + parameter_ = parameter; + return true; + } +}; + +// =================================================================== + +void CommandLineInterfaceTest::SetUp() { + // Most of these tests were written before this option was added, so we + // run with the option on (which used to be the only way) except in certain + // tests where we turn it off. + cli_.SetInputsAreProtoPathRelative(true); + + temp_directory_ = TestTempDir() + "/proto2_cli_test_temp"; + + // If the temp directory already exists, it must be left over from a + // previous run. Delete it. + if (File::Exists(temp_directory_)) { + File::DeleteRecursively(temp_directory_, NULL, NULL); + } + + // Create the temp directory. + GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE)); + + // Register generators. + CodeGenerator* generator = new MockCodeGenerator("test_generator"); + mock_generators_to_delete_.push_back(generator); + cli_.RegisterGenerator("--test_out", "--test_opt", generator, "Test output."); + cli_.RegisterGenerator("-t", generator, "Test output."); + + generator = new MockCodeGenerator("alt_generator"); + mock_generators_to_delete_.push_back(generator); + cli_.RegisterGenerator("--alt_out", generator, "Alt output."); + + generator = null_generator_ = new NullCodeGenerator(); + mock_generators_to_delete_.push_back(generator); + cli_.RegisterGenerator("--null_out", generator, "Null output."); + + disallow_plugins_ = false; +} + +void CommandLineInterfaceTest::TearDown() { + // Delete the temp directory. + File::DeleteRecursively(temp_directory_, NULL, NULL); + + // Delete all the MockCodeGenerators. + for (int i = 0; i < mock_generators_to_delete_.size(); i++) { + delete mock_generators_to_delete_[i]; + } + mock_generators_to_delete_.clear(); +} + +void CommandLineInterfaceTest::Run(const string& command) { + vector args; + SplitStringUsing(command, " ", &args); + + if (!disallow_plugins_) { + cli_.AllowPlugins("prefix-"); + const char* possible_paths[] = { + // When building with shared libraries, libtool hides the real executable + // in .libs and puts a fake wrapper in the current directory. + // Unfortunately, due to an apparent bug on Cygwin/MinGW, if one program + // wrapped in this way (e.g. protobuf-tests.exe) tries to execute another + // program wrapped in this way (e.g. test_plugin.exe), the latter fails + // with error code 127 and no explanation message. Presumably the problem + // is that the wrapper for protobuf-tests.exe set some environment + // variables that confuse the wrapper for test_plugin.exe. Luckily, it + // turns out that if we simply invoke the wrapped test_plugin.exe + // directly, it works -- I guess the environment variables set by the + // protobuf-tests.exe wrapper happen to be correct for it too. So we do + // that. + ".libs/test_plugin.exe", // Win32 w/autotool (Cygwin / MinGW) + "test_plugin.exe", // Other Win32 (MSVC) + "test_plugin", // Unix + }; + + string plugin_path; + + for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) { + if (access(possible_paths[i], F_OK) == 0) { + plugin_path = possible_paths[i]; + break; + } + } + + if (plugin_path.empty()) { + GOOGLE_LOG(ERROR) + << "Plugin executable not found. Plugin tests are likely to fail."; + } else { + args.push_back("--plugin=prefix-gen-plug=" + plugin_path); + } + } + + scoped_array argv(new const char*[args.size()]); + + for (int i = 0; i < args.size(); i++) { + args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); + argv[i] = args[i].c_str(); + } + + CaptureTestStderr(); + + return_code_ = cli_.Run(args.size(), argv.get()); + + error_text_ = GetCapturedTestStderr(); +} + +// ------------------------------------------------------------------- + +void CommandLineInterfaceTest::CreateTempFile( + const string& name, + const string& contents) { + // Create parent directory, if necessary. + string::size_type slash_pos = name.find_last_of('/'); + if (slash_pos != string::npos) { + string dir = name.substr(0, slash_pos); + File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777); + } + + // Write file. + string full_name = temp_directory_ + "/" + name; + File::WriteStringToFileOrDie(contents, full_name); +} + +void CommandLineInterfaceTest::CreateTempDir(const string& name) { + File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777); +} + +// ------------------------------------------------------------------- + +void CommandLineInterfaceTest::ExpectNoErrors() { + EXPECT_EQ(0, return_code_); + EXPECT_EQ("", error_text_); +} + +void CommandLineInterfaceTest::ExpectErrorText(const string& expected_text) { + EXPECT_NE(0, return_code_); + EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true), + error_text_); +} + +void CommandLineInterfaceTest::ExpectErrorSubstring( + const string& expected_substring) { + EXPECT_NE(0, return_code_); + EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); +} + +void CommandLineInterfaceTest::ExpectErrorSubstringWithZeroReturnCode( + const string& expected_substring) { + EXPECT_EQ(0, return_code_); + EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_); +} + +bool CommandLineInterfaceTest::HasAlternateErrorSubstring( + const string& expected_substring) { + EXPECT_NE(0, return_code_); + return error_text_.find(expected_substring) != string::npos; +} + +void CommandLineInterfaceTest::ExpectGenerated( + const string& generator_name, + const string& parameter, + const string& proto_name, + const string& message_name) { + MockCodeGenerator::ExpectGenerated( + generator_name, parameter, "", proto_name, message_name, proto_name, + temp_directory_); +} + +void CommandLineInterfaceTest::ExpectGenerated( + const string& generator_name, + const string& parameter, + const string& proto_name, + const string& message_name, + const string& output_directory) { + MockCodeGenerator::ExpectGenerated( + generator_name, parameter, "", proto_name, message_name, proto_name, + temp_directory_ + "/" + output_directory); +} + +void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( + const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name) { + MockCodeGenerator::ExpectGenerated( + generator_name, "", "", proto_name, message_name, + all_proto_names, + temp_directory_); +} + +void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( + const string& generator_name, + const string& parameter, + const string& insertions, + const string& proto_name, + const string& message_name) { + MockCodeGenerator::ExpectGenerated( + generator_name, parameter, insertions, proto_name, message_name, + proto_name, temp_directory_); +} + +void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( + const string& parameter) { + EXPECT_TRUE(null_generator_->called_); + EXPECT_EQ(parameter, null_generator_->parameter_); +} + +void CommandLineInterfaceTest::ReadDescriptorSet( + const string& filename, FileDescriptorSet* descriptor_set) { + string path = temp_directory_ + "/" + filename; + string file_contents; + if (!File::ReadFileToString(path, &file_contents)) { + FAIL() << "File not found: " << path; + } + if (!descriptor_set->ParseFromString(file_contents)) { + FAIL() << "Could not parse file contents: " << path; + } +} + +// =================================================================== + +TEST_F(CommandLineInterfaceTest, BasicOutput) { + // Test that the common case works. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, BasicPlugin) { + // Test that basic plugins work. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_plugin", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) { + // Invoke a generator and a plugin at the same time. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); + ExpectGenerated("test_plugin", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, MultipleInputs) { + // Test parsing multiple input files. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto bar.proto"); + + ExpectNoErrors(); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); +} + +TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { + // Test parsing multiple input files with an import of a separate file. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"baz.proto\";\n" + "message Bar {\n" + " optional Baz a = 1;\n" + "}\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "message Baz {}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto bar.proto"); + + ExpectNoErrors(); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); +} + +TEST_F(CommandLineInterfaceTest, CreateDirectory) { + // Test that when we output to a sub-directory, it is created. + + CreateTempFile("bar/baz/foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempDir("out"); + CreateTempDir("plugout"); + + Run("protocol_compiler --test_out=$tmpdir/out --plug_out=$tmpdir/plugout " + "--proto_path=$tmpdir bar/baz/foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "bar/baz/foo.proto", "Foo", "out"); + ExpectGenerated("test_plugin", "", "bar/baz/foo.proto", "Foo", "plugout"); +} + +TEST_F(CommandLineInterfaceTest, GeneratorParameters) { + // Test that generator parameters are correctly parsed from the command line. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=TestParameter:$tmpdir " + "--plug_out=TestPluginParameter:$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "TestParameter", "foo.proto", "Foo"); + ExpectGenerated("test_plugin", "TestPluginParameter", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, ExtraGeneratorParameters) { + // Test that generator parameters specified with the option flag are + // correctly passed to the code generator. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + // Create the "a" and "b" sub-directories. + CreateTempDir("a"); + CreateTempDir("b"); + + Run("protocol_compiler " + "--test_opt=foo1 " + "--test_out=bar:$tmpdir/a " + "--test_opt=foo2 " + "--test_out=baz:$tmpdir/b " + "--test_opt=foo3 " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated( + "test_generator", "bar,foo1,foo2,foo3", "foo.proto", "Foo", "a"); + ExpectGenerated( + "test_generator", "baz,foo1,foo2,foo3", "foo.proto", "Foo", "b"); +} + +TEST_F(CommandLineInterfaceTest, Insert) { + // Test running a generator that inserts code into another's output. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler " + "--test_out=TestParameter:$tmpdir " + "--plug_out=TestPluginParameter:$tmpdir " + "--test_out=insert=test_generator,test_plugin:$tmpdir " + "--plug_out=insert=test_generator,test_plugin:$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGeneratedWithInsertions( + "test_generator", "TestParameter", "test_generator,test_plugin", + "foo.proto", "Foo"); + ExpectGeneratedWithInsertions( + "test_plugin", "TestPluginParameter", "test_generator,test_plugin", + "foo.proto", "Foo"); +} + +#if defined(_WIN32) + +TEST_F(CommandLineInterfaceTest, WindowsOutputPath) { + // Test that the output path can be a Windows-style path. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n"); + + Run("protocol_compiler --null_out=C:\\ " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectNullCodeGeneratorCalled(""); +} + +TEST_F(CommandLineInterfaceTest, WindowsOutputPathAndParameter) { + // Test that we can have a windows-style output path and a parameter. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n"); + + Run("protocol_compiler --null_out=bar:C:\\ " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectNullCodeGeneratorCalled("bar"); +} + +TEST_F(CommandLineInterfaceTest, TrailingBackslash) { + // Test that the directories can end in backslashes. Some users claim this + // doesn't work on their system. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir\\ " + "--proto_path=$tmpdir\\ foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +#endif // defined(_WIN32) || defined(__CYGWIN__) + +TEST_F(CommandLineInterfaceTest, PathLookup) { + // Test that specifying multiple directories in the proto search path works. + + CreateTempFile("b/bar.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + CreateTempFile("a/foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar a = 1;\n" + "}\n"); + CreateTempFile("b/foo.proto", "this should not be parsed\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/a --proto_path=$tmpdir/b foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) { + // Same as PathLookup, but we provide the proto_path in a single flag. + + CreateTempFile("b/bar.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + CreateTempFile("a/foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar a = 1;\n" + "}\n"); + CreateTempFile("b/foo.proto", "this should not be parsed\n"); + +#undef PATH_SEPARATOR +#if defined(_WIN32) +#define PATH_SEPARATOR ";" +#else +#define PATH_SEPARATOR ":" +#endif + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/a"PATH_SEPARATOR"$tmpdir/b foo.proto"); + +#undef PATH_SEPARATOR + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, NonRootMapping) { + // Test setting up a search path mapping a directory to a non-root location. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=bar=$tmpdir bar/foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "bar/foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, MultipleGenerators) { + // Test that we can have multiple generators and use both in one invocation, + // each with a different output directory. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + // Create the "a" and "b" sub-directories. + CreateTempDir("a"); + CreateTempDir("b"); + + Run("protocol_compiler " + "--test_out=$tmpdir/a " + "--alt_out=$tmpdir/b " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo", "a"); + ExpectGenerated("alt_generator", "", "foo.proto", "Foo", "b"); +} + +TEST_F(CommandLineInterfaceTest, DisallowServicesNoServices) { + // Test that --disallow_services doesn't cause a problem when there are no + // services. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --disallow_services --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, DisallowServicesHasService) { + // Test that --disallow_services produces an error when there are services. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n" + "service Bar {}\n"); + + Run("protocol_compiler --disallow_services --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring("foo.proto: This file contains services"); +} + +TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { + // Test that services work fine as long as --disallow_services is not used. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n" + "service Bar {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) { + // Test that we can accept working-directory-relative input files. + + SetInputsAreProtoPathRelative(false); + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir $tmpdir/foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + ASSERT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); + // Descriptor set should not have source code info. + EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); +} + +TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--include_source_info --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + ASSERT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); + // Source code info included. + EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); +} + +TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--include_imports --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + ASSERT_EQ(2, descriptor_set.file_size()); + if (descriptor_set.file(0).name() == "bar.proto") { + std::swap(descriptor_set.mutable_file()->mutable_data()[0], + descriptor_set.mutable_file()->mutable_data()[1]); + } + EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); + EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); + // Descriptor set should not have source code info. + EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); + EXPECT_FALSE(descriptor_set.file(1).has_source_code_info()); +} + +TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set " + "--include_imports --include_source_info --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + FileDescriptorSet descriptor_set; + ReadDescriptorSet("descriptor_set", &descriptor_set); + if (HasFatalFailure()) return; + ASSERT_EQ(2, descriptor_set.file_size()); + if (descriptor_set.file(0).name() == "bar.proto") { + std::swap(descriptor_set.mutable_file()->mutable_data()[0], + descriptor_set.mutable_file()->mutable_data()[1]); + } + EXPECT_EQ("foo.proto", descriptor_set.file(0).name()); + EXPECT_EQ("bar.proto", descriptor_set.file(1).name()); + // Source code info included. + EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); + EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); +} + +// ------------------------------------------------------------------- + +TEST_F(CommandLineInterfaceTest, ParseErrors) { + // Test that parse errors are reported. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "badsyntax\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorText( + "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); +} + +TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) { + // Test that parse errors are reported from multiple files. + + // We set up files such that foo.proto actually depends on bar.proto in + // two ways: Directly and through baz.proto. bar.proto's errors should + // only be reported once. + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "badsyntax\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n"); + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "import \"baz.proto\";\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorText( + "bar.proto:2:1: Expected top-level statement (e.g. \"message\").\n" + "baz.proto: Import \"bar.proto\" was not found or had errors.\n" + "foo.proto: Import \"bar.proto\" was not found or had errors.\n" + "foo.proto: Import \"baz.proto\" was not found or had errors.\n"); +} + +TEST_F(CommandLineInterfaceTest, InputNotFoundError) { + // Test what happens if the input file is not found. + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorText( + "foo.proto: File not found.\n"); +} + +TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) { + // Test what happens when a working-directory-relative input file is not + // found. + + SetInputsAreProtoPathRelative(false); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir $tmpdir/foo.proto"); + + ExpectErrorText( + "$tmpdir/foo.proto: No such file or directory\n"); +} + +TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotMappedError) { + // Test what happens when a working-directory-relative input file is not + // mapped to a virtual path. + + SetInputsAreProtoPathRelative(false); + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + // Create a directory called "bar" so that we can point --proto_path at it. + CreateTempFile("bar/dummy", ""); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); + + ExpectErrorText( + "$tmpdir/foo.proto: File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think).\n"); +} + +TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundAndNotMappedError) { + // Check what happens if the input file is not found *and* is not mapped + // in the proto_path. + + SetInputsAreProtoPathRelative(false); + + // Create a directory called "bar" so that we can point --proto_path at it. + CreateTempFile("bar/dummy", ""); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/bar $tmpdir/foo.proto"); + + ExpectErrorText( + "$tmpdir/foo.proto: No such file or directory\n"); +} + +TEST_F(CommandLineInterfaceTest, CwdRelativeInputShadowedError) { + // Test what happens when a working-directory-relative input file is shadowed + // by another file in the virtual path. + + SetInputsAreProtoPathRelative(false); + + CreateTempFile("foo/foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar/foo.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/foo --proto_path=$tmpdir/bar " + "$tmpdir/bar/foo.proto"); + + ExpectErrorText( + "$tmpdir/bar/foo.proto: Input is shadowed in the --proto_path " + "by \"$tmpdir/foo/foo.proto\". Either use the latter " + "file as your input or reorder the --proto_path so that the " + "former file's location comes first.\n"); +} + +TEST_F(CommandLineInterfaceTest, ProtoPathNotFoundError) { + // Test what happens if the input file is not found. + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir/foo foo.proto"); + + ExpectErrorText( + "$tmpdir/foo: warning: directory does not exist.\n" + "foo.proto: File not found.\n"); +} + +TEST_F(CommandLineInterfaceTest, MissingInputError) { + // Test that we get an error if no inputs are given. + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir"); + + ExpectErrorText("Missing input file.\n"); +} + +TEST_F(CommandLineInterfaceTest, MissingOutputError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --proto_path=$tmpdir foo.proto"); + + ExpectErrorText("Missing output directives.\n"); +} + +TEST_F(CommandLineInterfaceTest, OutputWriteError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + string output_file = + MockCodeGenerator::GetOutputFileName("test_generator", "foo.proto"); + + // Create a directory blocking our output location. + CreateTempDir(output_file); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + // MockCodeGenerator no longer detects an error because we actually write to + // an in-memory location first, then dump to disk at the end. This is no + // big deal. + // ExpectErrorSubstring("MockCodeGenerator detected write error."); + +#if defined(_WIN32) && !defined(__CYGWIN__) + // Windows with MSVCRT.dll produces EPERM instead of EISDIR. + if (HasAlternateErrorSubstring(output_file + ": Permission denied")) { + return; + } +#endif + + ExpectErrorSubstring(output_file + ": Is a directory"); +} + +TEST_F(CommandLineInterfaceTest, PluginOutputWriteError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + string output_file = + MockCodeGenerator::GetOutputFileName("test_plugin", "foo.proto"); + + // Create a directory blocking our output location. + CreateTempDir(output_file); + + Run("protocol_compiler --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + +#if defined(_WIN32) && !defined(__CYGWIN__) + // Windows with MSVCRT.dll produces EPERM instead of EISDIR. + if (HasAlternateErrorSubstring(output_file + ": Permission denied")) { + return; + } +#endif + + ExpectErrorSubstring(output_file + ": Is a directory"); +} + +TEST_F(CommandLineInterfaceTest, OutputDirectoryNotFoundError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir/nosuchdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring("nosuchdir/: No such file or directory"); +} + +TEST_F(CommandLineInterfaceTest, PluginOutputDirectoryNotFoundError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --plug_out=$tmpdir/nosuchdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring("nosuchdir/: No such file or directory"); +} + +TEST_F(CommandLineInterfaceTest, OutputDirectoryIsFileError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out=$tmpdir/foo.proto " + "--proto_path=$tmpdir foo.proto"); + +#if defined(_WIN32) && !defined(__CYGWIN__) + // Windows with MSVCRT.dll produces EINVAL instead of ENOTDIR. + if (HasAlternateErrorSubstring("foo.proto/: Invalid argument")) { + return; + } +#endif + + ExpectErrorSubstring("foo.proto/: Not a directory"); +} + +TEST_F(CommandLineInterfaceTest, GeneratorError) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Error {}\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "--test_out: foo.proto: Saw message type MockCodeGenerator_Error."); +} + +TEST_F(CommandLineInterfaceTest, GeneratorPluginError) { + // Test a generator plugin that returns an error. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Error {}\n"); + + Run("protocol_compiler --plug_out=TestParameter:$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "--plug_out: foo.proto: Saw message type MockCodeGenerator_Error."); +} + +TEST_F(CommandLineInterfaceTest, GeneratorPluginFail) { + // Test a generator plugin that exits with an error code. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Exit {}\n"); + + Run("protocol_compiler --plug_out=TestParameter:$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring("Saw message type MockCodeGenerator_Exit."); + ExpectErrorSubstring( + "--plug_out: prefix-gen-plug: Plugin failed with status code 123."); +} + +TEST_F(CommandLineInterfaceTest, GeneratorPluginCrash) { + // Test a generator plugin that crashes. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_Abort {}\n"); + + Run("protocol_compiler --plug_out=TestParameter:$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring("Saw message type MockCodeGenerator_Abort."); + +#ifdef _WIN32 + // Windows doesn't have signals. It looks like abort()ing causes the process + // to exit with status code 3, but let's not depend on the exact number here. + ExpectErrorSubstring( + "--plug_out: prefix-gen-plug: Plugin failed with status code"); +#else + // Don't depend on the exact signal number. + ExpectErrorSubstring( + "--plug_out: prefix-gen-plug: Plugin killed by signal"); +#endif +} + +TEST_F(CommandLineInterfaceTest, PluginReceivesSourceCodeInfo) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message MockCodeGenerator_HasSourceCodeInfo {}\n"); + + Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto"); + + ExpectErrorSubstring( + "Saw message type MockCodeGenerator_HasSourceCodeInfo: 1."); +} + +TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) { + // Test what happens if the plugin isn't found. + + CreateTempFile("error.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --badplug_out=TestParameter:$tmpdir " + "--plugin=prefix-gen-badplug=no_such_file " + "--proto_path=$tmpdir error.proto"); + +#ifdef _WIN32 + ExpectErrorSubstring("--badplug_out: prefix-gen-badplug: " + + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); +#else + // Error written to stdout by child process after exec() fails. + ExpectErrorSubstring( + "no_such_file: program not found or is not executable"); + + // Error written by parent process when child fails. + ExpectErrorSubstring( + "--badplug_out: prefix-gen-badplug: Plugin failed with status code 1."); +#endif +} + +TEST_F(CommandLineInterfaceTest, GeneratorPluginNotAllowed) { + // Test what happens if plugins aren't allowed. + + CreateTempFile("error.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + DisallowPlugins(); + Run("protocol_compiler --plug_out=TestParameter:$tmpdir " + "--proto_path=$tmpdir error.proto"); + + ExpectErrorSubstring("Unknown flag: --plug_out"); +} + +TEST_F(CommandLineInterfaceTest, HelpText) { + Run("test_exec_name --help"); + + ExpectErrorSubstringWithZeroReturnCode("Usage: test_exec_name "); + ExpectErrorSubstringWithZeroReturnCode("--test_out=OUT_DIR"); + ExpectErrorSubstringWithZeroReturnCode("Test output."); + ExpectErrorSubstringWithZeroReturnCode("--alt_out=OUT_DIR"); + ExpectErrorSubstringWithZeroReturnCode("Alt output."); +} + +TEST_F(CommandLineInterfaceTest, GccFormatErrors) { + // Test --error_format=gcc (which is the default, but we want to verify + // that it can be set explicitly). + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "badsyntax\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir --error_format=gcc foo.proto"); + + ExpectErrorText( + "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n"); +} + +TEST_F(CommandLineInterfaceTest, MsvsFormatErrors) { + // Test --error_format=msvs + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "badsyntax\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir --error_format=msvs foo.proto"); + + ExpectErrorText( + "$tmpdir/foo.proto(2) : error in column=1: Expected top-level statement " + "(e.g. \"message\").\n"); +} + +TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) { + // Test --error_format=msvs + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "badsyntax\n"); + + Run("protocol_compiler --test_out=$tmpdir " + "--proto_path=$tmpdir --error_format=invalid foo.proto"); + + ExpectErrorText( + "Unknown error format: invalid\n"); +} + +// ------------------------------------------------------------------- +// Flag parsing tests + +TEST_F(CommandLineInterfaceTest, ParseSingleCharacterFlag) { + // Test that a single-character flag works. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler -t$tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, ParseSpaceDelimitedValue) { + // Test that separating the flag value with a space works. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler --test_out $tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, ParseSingleCharacterSpaceDelimitedValue) { + // Test that separating the flag value with a space works for + // single-character flags. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + Run("protocol_compiler -t $tmpdir " + "--proto_path=$tmpdir foo.proto"); + + ExpectNoErrors(); + ExpectGenerated("test_generator", "", "foo.proto", "Foo"); +} + +TEST_F(CommandLineInterfaceTest, MissingValueError) { + // Test that we get an error if a flag is missing its value. + + Run("protocol_compiler --test_out --proto_path=$tmpdir foo.proto"); + + ExpectErrorText("Missing value for flag: --test_out\n"); +} + +TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { + // Test that we get an error if the last argument is a flag requiring a + // value. + + Run("protocol_compiler --test_out"); + + ExpectErrorText("Missing value for flag: --test_out\n"); +} + +// =================================================================== + +// Test for --encode and --decode. Note that it would be easier to do this +// test as a shell script, but we'd like to be able to run the test on +// platforms that don't have a Bourne-compatible shell available (especially +// Windows/MSVC). +class EncodeDecodeTest : public testing::Test { + protected: + virtual void SetUp() { + duped_stdin_ = dup(STDIN_FILENO); + } + + virtual void TearDown() { + dup2(duped_stdin_, STDIN_FILENO); + close(duped_stdin_); + } + + void RedirectStdinFromText(const string& input) { + string filename = TestTempDir() + "/test_stdin"; + File::WriteStringToFileOrDie(input, filename); + GOOGLE_CHECK(RedirectStdinFromFile(filename)); + } + + bool RedirectStdinFromFile(const string& filename) { + int fd = open(filename.c_str(), O_RDONLY); + if (fd < 0) return false; + dup2(fd, STDIN_FILENO); + close(fd); + return true; + } + + // Remove '\r' characters from text. + string StripCR(const string& text) { + string result; + + for (int i = 0; i < text.size(); i++) { + if (text[i] != '\r') { + result.push_back(text[i]); + } + } + + return result; + } + + enum Type { TEXT, BINARY }; + enum ReturnCode { SUCCESS, ERROR }; + + bool Run(const string& command) { + vector args; + args.push_back("protoc"); + SplitStringUsing(command, " ", &args); + args.push_back("--proto_path=" + TestSourceDir()); + + scoped_array argv(new const char*[args.size()]); + for (int i = 0; i < args.size(); i++) { + argv[i] = args[i].c_str(); + } + + CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + CaptureTestStdout(); + CaptureTestStderr(); + + int result = cli.Run(args.size(), argv.get()); + + captured_stdout_ = GetCapturedTestStdout(); + captured_stderr_ = GetCapturedTestStderr(); + + return result == 0; + } + + void ExpectStdoutMatchesBinaryFile(const string& filename) { + string expected_output; + ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + + // Don't use EXPECT_EQ because we don't want to print raw binary data to + // stdout on failure. + EXPECT_TRUE(captured_stdout_ == expected_output); + } + + void ExpectStdoutMatchesTextFile(const string& filename) { + string expected_output; + ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + + ExpectStdoutMatchesText(expected_output); + } + + void ExpectStdoutMatchesText(const string& expected_text) { + EXPECT_EQ(StripCR(expected_text), StripCR(captured_stdout_)); + } + + void ExpectStderrMatchesText(const string& expected_text) { + EXPECT_EQ(StripCR(expected_text), StripCR(captured_stderr_)); + } + + private: + int duped_stdin_; + string captured_stdout_; + string captured_stderr_; +}; + +TEST_F(EncodeDecodeTest, Encode) { + RedirectStdinFromFile(TestSourceDir() + + "/google/protobuf/testdata/text_format_unittest_data.txt"); + EXPECT_TRUE(Run("google/protobuf/unittest.proto " + "--encode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesBinaryFile(TestSourceDir() + + "/google/protobuf/testdata/golden_message"); + ExpectStderrMatchesText(""); +} + +TEST_F(EncodeDecodeTest, Decode) { + RedirectStdinFromFile(TestSourceDir() + + "/google/protobuf/testdata/golden_message"); + EXPECT_TRUE(Run("google/protobuf/unittest.proto " + "--decode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesTextFile(TestSourceDir() + + "/google/protobuf/testdata/text_format_unittest_data.txt"); + ExpectStderrMatchesText(""); +} + +TEST_F(EncodeDecodeTest, Partial) { + RedirectStdinFromText(""); + EXPECT_TRUE(Run("google/protobuf/unittest.proto " + "--encode=protobuf_unittest.TestRequired")); + ExpectStdoutMatchesText(""); + ExpectStderrMatchesText( + "warning: Input message is missing required fields: a, b, c\n"); +} + +TEST_F(EncodeDecodeTest, DecodeRaw) { + protobuf_unittest::TestAllTypes message; + message.set_optional_int32(123); + message.set_optional_string("foo"); + string data; + message.SerializeToString(&data); + + RedirectStdinFromText(data); + EXPECT_TRUE(Run("--decode_raw")); + ExpectStdoutMatchesText("1: 123\n" + "14: \"foo\"\n"); + ExpectStderrMatchesText(""); +} + +TEST_F(EncodeDecodeTest, UnknownType) { + EXPECT_FALSE(Run("google/protobuf/unittest.proto " + "--encode=NoSuchType")); + ExpectStdoutMatchesText(""); + ExpectStderrMatchesText("Type not defined: NoSuchType\n"); +} + +TEST_F(EncodeDecodeTest, ProtoParseError) { + EXPECT_FALSE(Run("google/protobuf/no_such_file.proto " + "--encode=NoSuchType")); + ExpectStdoutMatchesText(""); + ExpectStderrMatchesText( + "google/protobuf/no_such_file.proto: File not found.\n"); +} + +} // anonymous namespace + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc new file mode 100644 index 000000000..b7c1766bf --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -0,0 +1,158 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 test insures that google/protobuf/descriptor.pb.{h,cc} match exactly +// what would be generated by the protocol compiler. These files are not +// generated automatically at build time because they are compiled into the +// protocol compiler itself. So, if they were auto-generated, you'd have a +// chicken-and-egg problem. +// +// If this test fails, run the script +// "generate_descriptor_proto.sh" and add +// descriptor.pb.{h,cc} to your changelist. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +class MockErrorCollector : public MultiFileErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, int line, int column, + const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", + filename, line, column, message); + } +}; + +class MockGeneratorContext : public GeneratorContext { + public: + MockGeneratorContext() {} + ~MockGeneratorContext() { + STLDeleteValues(&files_); + } + + void ExpectFileMatches(const string& virtual_filename, + const string& physical_filename) { + string* expected_contents = FindPtrOrNull(files_, virtual_filename); + ASSERT_TRUE(expected_contents != NULL) + << "Generator failed to generate file: " << virtual_filename; + + string actual_contents; + File::ReadFileToStringOrDie( + TestSourceDir() + "/" + physical_filename, + &actual_contents); + EXPECT_TRUE(actual_contents == *expected_contents) + << physical_filename << " needs to be regenerated. Please run " + "generate_descriptor_proto.sh and add this file " + "to your CL."; + } + + // implements GeneratorContext -------------------------------------- + + virtual io::ZeroCopyOutputStream* Open(const string& filename) { + string** map_slot = &files_[filename]; + if (*map_slot != NULL) delete *map_slot; + *map_slot = new string; + + return new io::StringOutputStream(*map_slot); + } + + private: + map files_; +}; + +TEST(BootstrapTest, GeneratedDescriptorMatches) { + MockErrorCollector error_collector; + DiskSourceTree source_tree; + source_tree.MapPath("", TestSourceDir()); + Importer importer(&source_tree, &error_collector); + const FileDescriptor* proto_file = + importer.Import("google/protobuf/descriptor.proto"); + const FileDescriptor* plugin_proto_file = + importer.Import("google/protobuf/compiler/plugin.proto"); + EXPECT_EQ("", error_collector.text_); + ASSERT_TRUE(proto_file != NULL); + ASSERT_TRUE(plugin_proto_file != NULL); + + CppGenerator generator; + MockGeneratorContext context; + string error; + string parameter; + parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; + ASSERT_TRUE(generator.Generate(proto_file, parameter, + &context, &error)); + parameter = "dllexport_decl=LIBPROTOC_EXPORT"; + ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, + &context, &error)); + + context.ExpectFileMatches("google/protobuf/descriptor.pb.h", + "google/protobuf/descriptor.pb.h"); + context.ExpectFileMatches("google/protobuf/descriptor.pb.cc", + "google/protobuf/descriptor.pb.cc"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", + "google/protobuf/compiler/plugin.pb.h"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", + "google/protobuf/compiler/plugin.pb.cc"); +} + +} // namespace + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc new file mode 100644 index 000000000..67c12d7ab --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -0,0 +1,258 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options) { +} + +EnumGenerator::~EnumGenerator() {} + +void EnumGenerator::GenerateDefinition(io::Printer* printer) { + map vars; + vars["classname"] = classname_; + vars["short_name"] = descriptor_->name(); + + printer->Print(vars, "enum $classname$ {\n"); + printer->Indent(); + + const EnumValueDescriptor* min_value = descriptor_->value(0); + const EnumValueDescriptor* max_value = descriptor_->value(0); + + for (int i = 0; i < descriptor_->value_count(); i++) { + vars["name"] = descriptor_->value(i)->name(); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + vars["prefix"] = (descriptor_->containing_type() == NULL) ? + "" : classname_ + "_"; + + if (i > 0) printer->Print(",\n"); + printer->Print(vars, "$prefix$$name$ = $number$"); + + if (descriptor_->value(i)->number() < min_value->number()) { + min_value = descriptor_->value(i); + } + if (descriptor_->value(i)->number() > max_value->number()) { + max_value = descriptor_->value(i); + } + } + + printer->Outdent(); + printer->Print("\n};\n"); + + vars["min_name"] = min_value->name(); + vars["max_name"] = max_value->name(); + + if (options_.dllexport_decl.empty()) { + vars["dllexport"] = ""; + } else { + vars["dllexport"] = options_.dllexport_decl + " "; + } + + printer->Print(vars, + "$dllexport$bool $classname$_IsValid(int value);\n" + "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" + "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" + "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n" + "\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); + // The _Name and _Parse methods + printer->Print(vars, + "inline const ::std::string& $classname$_Name($classname$ value) {\n" + " return ::google::protobuf::internal::NameOfEnum(\n" + " $classname$_descriptor(), value);\n" + "}\n"); + printer->Print(vars, + "inline bool $classname$_Parse(\n" + " const ::std::string& name, $classname$* value) {\n" + " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" + " $classname$_descriptor(), name, value);\n" + "}\n"); + } +} + +void EnumGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "template <>\n" + "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" + " return $classname$_descriptor();\n" + "}\n", + "classname", ClassName(descriptor_, true)); + } +} + +void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { + map vars; + vars["nested_name"] = descriptor_->name(); + vars["classname"] = classname_; + printer->Print(vars, "typedef $classname$ $nested_name$;\n"); + + for (int j = 0; j < descriptor_->value_count(); j++) { + vars["tag"] = descriptor_->value(j)->name(); + printer->Print(vars, + "static const $nested_name$ $tag$ = $classname$_$tag$;\n"); + } + + printer->Print(vars, + "static inline bool $nested_name$_IsValid(int value) {\n" + " return $classname$_IsValid(value);\n" + "}\n" + "static const $nested_name$ $nested_name$_MIN =\n" + " $classname$_$nested_name$_MIN;\n" + "static const $nested_name$ $nested_name$_MAX =\n" + " $classname$_$nested_name$_MAX;\n" + "static const int $nested_name$_ARRAYSIZE =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "static inline const ::google::protobuf::EnumDescriptor*\n" + "$nested_name$_descriptor() {\n" + " return $classname$_descriptor();\n" + "}\n"); + printer->Print(vars, + "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" + " return $classname$_Name(value);\n" + "}\n"); + printer->Print(vars, + "static inline bool $nested_name$_Parse(const ::std::string& name,\n" + " $nested_name$* value) {\n" + " return $classname$_Parse(name, value);\n" + "}\n"); + } +} + +void EnumGenerator::GenerateDescriptorInitializer( + io::Printer* printer, int index) { + map vars; + vars["classname"] = classname_; + vars["index"] = SimpleItoa(index); + + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "$classname$_descriptor_ = file->enum_type($index$);\n"); + } else { + vars["parent"] = ClassName(descriptor_->containing_type(), false); + printer->Print(vars, + "$classname$_descriptor_ = $parent$_descriptor_->enum_type($index$);\n"); + } +} + +void EnumGenerator::GenerateMethods(io::Printer* printer) { + map vars; + vars["classname"] = classname_; + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n"); + } + + printer->Print(vars, + "bool $classname$_IsValid(int value) {\n" + " switch(value) {\n"); + + // Multiple values may have the same number. Make sure we only cover + // each number once by first constructing a set containing all valid + // numbers, then printing a case statement for each element. + + set numbers; + for (int j = 0; j < descriptor_->value_count(); j++) { + const EnumValueDescriptor* value = descriptor_->value(j); + numbers.insert(value->number()); + } + + for (set::iterator iter = numbers.begin(); + iter != numbers.end(); ++iter) { + printer->Print( + " case $number$:\n", + "number", SimpleItoa(*iter)); + } + + printer->Print(vars, + " return true;\n" + " default:\n" + " return false;\n" + " }\n" + "}\n" + "\n"); + + if (descriptor_->containing_type() != NULL) { + // We need to "define" the static constants which were declared in the + // header, to give the linker a place to put them. Or at least the C++ + // standard says we have to. MSVC actually insists tha we do _not_ define + // them again in the .cc file. + printer->Print("#ifndef _MSC_VER\n"); + + vars["parent"] = ClassName(descriptor_->containing_type(), false); + vars["nested_name"] = descriptor_->name(); + for (int i = 0; i < descriptor_->value_count(); i++) { + vars["value"] = descriptor_->value(i)->name(); + printer->Print(vars, + "const $classname$ $parent$::$value$;\n"); + } + printer->Print(vars, + "const $classname$ $parent$::$nested_name$_MIN;\n" + "const $classname$ $parent$::$nested_name$_MAX;\n" + "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + + printer->Print("#endif // _MSC_VER\n"); + } +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h new file mode 100644 index 000000000..2e85a0bd3 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_ENUM_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ + +#include +#include +#include + + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +class EnumGenerator { + public: + // See generator.cc for the meaning of dllexport_decl. + explicit EnumGenerator(const EnumDescriptor* descriptor, + const Options& options); + ~EnumGenerator(); + + // Header stuff. + + // Generate header code defining the enum. This code should be placed + // within the enum's package namespace, but NOT within any class, even for + // nested enums. + void GenerateDefinition(io::Printer* printer); + + // Generate specialization of GetEnumDescriptor(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + + // For enums nested within a message, generate code to import all the enum's + // symbols (e.g. the enum type name, all its values, etc.) into the class's + // namespace. This should be placed inside the class definition in the + // header. + void GenerateSymbolImports(io::Printer* printer); + + // Source file stuff. + + // Generate code that initializes the global variable storing the enum's + // descriptor. + void GenerateDescriptorInitializer(io::Printer* printer, int index); + + // Generate non-inline methods related to the enum, such as IsValidValue(). + // Goes in the .cc file. + void GenerateMethods(io::Printer* printer); + + private: + const EnumDescriptor* descriptor_; + string classname_; + Options options_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc new file mode 100644 index 000000000..6e1620d4d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -0,0 +1,366 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +void SetEnumVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); + const EnumValueDescriptor* default_value = descriptor->default_value_enum(); + (*variables)["type"] = ClassName(descriptor->enum_type(), true); + (*variables)["default"] = SimpleItoa(default_value->number()); +} + +} // namespace + +// =================================================================== + +EnumFieldGenerator:: +EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetEnumVariables(descriptor, &variables_, options); +} + +EnumFieldGenerator::~EnumFieldGenerator() {} + +void EnumFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, "int $name$_;\n"); +} + +void EnumFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); +} + +void EnumFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " return static_cast< $type$ >($name$_);\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " assert($type$_IsValid(value));\n" + " set_has_$name$();\n" + " $name$_ = value;\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void EnumFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "set_$name$(from.$name$());\n"); +} + +void EnumFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); +} + +void EnumFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void EnumFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "int value;\n" + "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n" + "if ($type$_IsValid(value)) {\n" + " set_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print(variables_, + "}\n"); +} + +void EnumFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(), output);\n"); +} + +void EnumFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + printer->Print(variables_, + "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(), target);\n"); +} + +void EnumFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n"); +} + +// =================================================================== + +RepeatedEnumFieldGenerator:: +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetEnumVariables(descriptor, &variables_, options); +} + +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} + +void RepeatedEnumFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::RepeatedField $name$_;\n"); + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { + printer->Print(variables_, + "mutable int _$name$_cached_byte_size_;\n"); + } +} + +void RepeatedEnumFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedField& $name$() const$deprecation$;\n" + "inline ::google::protobuf::RepeatedField* mutable_$name$()$deprecation$;\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$(int index) const {\n" + " return static_cast< $type$ >($name$_.Get(index));\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n" + " assert($type$_IsValid(value));\n" + " $name$_.Set(index, value);\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n" + " assert($type$_IsValid(value));\n" + " $name$_.Add(value);\n" + "}\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedField&\n" + "$classname$::$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline ::google::protobuf::RepeatedField*\n" + "$classname$::mutable_$name$() {\n" + " return &$name$_;\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Clear();\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Not needed for repeated fields. +} + +void RepeatedEnumFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + // Don't use ReadRepeatedPrimitive here so that the enum can be validated. + printer->Print(variables_, + "int value;\n" + "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n" + "if ($type$_IsValid(value)) {\n" + " add_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print("}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { + if (!descriptor_->options().packed()) { + // We use a non-inlined implementation in this case, since this path will + // rarely be executed. + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n" + " input,\n" + " &$type$_IsValid,\n" + " this->mutable_$name$())));\n"); + } else { + printer->Print(variables_, + "::google::protobuf::uint32 length;\n" + "DO_(input->ReadVarint32(&length));\n" + "::google::protobuf::io::CodedInputStream::Limit limit = " + "input->PushLimit(length);\n" + "while (input->BytesUntilLimit() > 0) {\n" + " int value;\n" + " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n" + " if ($type$_IsValid(value)) {\n" + " add_$name$(static_cast< $type$ >(value));\n" + " }\n" + "}\n" + "input->PopLimit(limit);\n"); + } +} + +void RepeatedEnumFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + if (descriptor_->options().packed()) { + // Write the tag and the size. + printer->Print(variables_, + "if (this->$name$_size() > 0) {\n" + " ::google::protobuf::internal::WireFormatLite::WriteTag(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " output);\n" + " output->WriteVarint32(_$name$_cached_byte_size_);\n" + "}\n"); + } + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" + " this->$name$(i), output);\n"); + } else { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(i), output);\n"); + } + printer->Print("}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + if (descriptor_->options().packed()) { + // Write the tag and the size. + printer->Print(variables_, + "if (this->$name$_size() > 0) {\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" + " _$name$_cached_byte_size_, target);\n" + "}\n"); + } + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" + " this->$name$(i), target);\n"); + } else { + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(i), target);\n"); + } + printer->Print("}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int data_size = 0;\n"); + printer->Indent(); + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n" + " this->$name$(i));\n" + "}\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" + "}\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + "_$name$_cached_byte_size_ = data_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "total_size += data_size;\n"); + } else { + printer->Print(variables_, + "total_size += $tag_size$ * this->$name$_size() + data_size;\n"); + } + printer->Outdent(); + printer->Print("}\n"); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h new file mode 100644 index 000000000..65770083b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -0,0 +1,105 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +class EnumFieldGenerator : public FieldGenerator { + public: + explicit EnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~EnumFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); +}; + +class RepeatedEnumFieldGenerator : public FieldGenerator { + public: + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~RepeatedEnumFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc new file mode 100644 index 000000000..ef56b5e54 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -0,0 +1,210 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +// Returns the fully-qualified class name of the message that this field +// extends. This function is used in the Google-internal code to handle some +// legacy cases. +string ExtendeeClassName(const FieldDescriptor* descriptor) { + const Descriptor* extendee = descriptor->containing_type(); + return ClassName(extendee, true); +} + +} // anonymous namespace + +ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + options_(options) { + // Construct type_traits_. + if (descriptor_->is_repeated()) { + type_traits_ = "Repeated"; + } + + switch (descriptor_->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + type_traits_.append("EnumTypeTraits< "); + type_traits_.append(ClassName(descriptor_->enum_type(), true)); + type_traits_.append(", "); + type_traits_.append(ClassName(descriptor_->enum_type(), true)); + type_traits_.append("_IsValid>"); + break; + case FieldDescriptor::CPPTYPE_STRING: + type_traits_.append("StringTypeTraits"); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + type_traits_.append("MessageTypeTraits< "); + type_traits_.append(ClassName(descriptor_->message_type(), true)); + type_traits_.append(" >"); + break; + default: + type_traits_.append("PrimitiveTypeTraits< "); + type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type())); + type_traits_.append(" >"); + break; + } +} + +ExtensionGenerator::~ExtensionGenerator() {} + +void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { + map vars; + vars["extendee" ] = ExtendeeClassName(descriptor_); + vars["number" ] = SimpleItoa(descriptor_->number()); + vars["type_traits" ] = type_traits_; + vars["name" ] = descriptor_->name(); + vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); + vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; + vars["constant_name"] = FieldConstantName(descriptor_); + + // If this is a class member, it needs to be declared "static". Otherwise, + // it needs to be "extern". In the latter case, it also needs the DLL + // export/import specifier. + if (descriptor_->extension_scope() == NULL) { + vars["qualifier"] = "extern"; + if (!options_.dllexport_decl.empty()) { + vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"]; + } + } else { + vars["qualifier"] = "static"; + } + + printer->Print(vars, + "static const int $constant_name$ = $number$;\n" + "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" + " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" + " $name$;\n" + ); + +} + +void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { + // If this is a class member, it needs to be declared in its class scope. + string scope = (descriptor_->extension_scope() == NULL) ? "" : + ClassName(descriptor_->extension_scope(), false) + "::"; + string name = scope + descriptor_->name(); + + map vars; + vars["extendee" ] = ExtendeeClassName(descriptor_); + vars["type_traits" ] = type_traits_; + vars["name" ] = name; + vars["constant_name"] = FieldConstantName(descriptor_); + vars["default" ] = DefaultValue(descriptor_); + vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); + vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; + vars["scope" ] = scope; + + if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + // We need to declare a global string which will contain the default value. + // We cannot declare it at class scope because that would require exposing + // it in the header which would be annoying for other reasons. So we + // replace :: with _ in the name and declare it as a global. + string global_name = StringReplace(name, "::", "_", true); + vars["global_name"] = global_name; + printer->Print(vars, + "const ::std::string $global_name$_default($default$);\n"); + + // Update the default to refer to the string global. + vars["default"] = global_name + "_default"; + } + + // Likewise, class members need to declare the field constant variable. + if (descriptor_->extension_scope() != NULL) { + printer->Print(vars, + "#ifndef _MSC_VER\n" + "const int $scope$$constant_name$;\n" + "#endif\n"); + } + + printer->Print(vars, + "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" + " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" + " $name$($constant_name$, $default$);\n"); +} + +void ExtensionGenerator::GenerateRegistration(io::Printer* printer) { + map vars; + vars["extendee" ] = ExtendeeClassName(descriptor_); + vars["number" ] = SimpleItoa(descriptor_->number()); + vars["field_type" ] = SimpleItoa(static_cast(descriptor_->type())); + vars["is_repeated"] = descriptor_->is_repeated() ? "true" : "false"; + vars["is_packed" ] = (descriptor_->is_repeated() && + descriptor_->options().packed()) + ? "true" : "false"; + + switch (descriptor_->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + printer->Print(vars, + "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n" + " &$extendee$::default_instance(),\n" + " $number$, $field_type$, $is_repeated$, $is_packed$,\n"); + printer->Print( + " &$type$_IsValid);\n", + "type", ClassName(descriptor_->enum_type(), true)); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + printer->Print(vars, + "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n" + " &$extendee$::default_instance(),\n" + " $number$, $field_type$, $is_repeated$, $is_packed$,\n"); + printer->Print( + " &$type$::default_instance());\n", + "type", ClassName(descriptor_->message_type(), true)); + break; + default: + printer->Print(vars, + "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n" + " &$extendee$::default_instance(),\n" + " $number$, $field_type$, $is_repeated$, $is_packed$);\n"); + break; + } +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h new file mode 100644 index 000000000..50ad035ba --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -0,0 +1,86 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_EXTENSION_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + class FieldDescriptor; // descriptor.h + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +// Generates code for an extension, which may be within the scope of some +// message or may be at file scope. This is much simpler than FieldGenerator +// since extensions are just simple identifiers with interesting types. +class ExtensionGenerator { + public: + // See generator.cc for the meaning of dllexport_decl. + explicit ExtensionGenerator(const FieldDescriptor* desycriptor, + const Options& options); + ~ExtensionGenerator(); + + // Header stuff. + void GenerateDeclaration(io::Printer* printer); + + // Source file stuff. + void GenerateDefinition(io::Printer* printer); + + // Generate code to register the extension. + void GenerateRegistration(io::Printer* printer); + + private: + const FieldDescriptor* descriptor_; + string type_traits_; + Options options_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc new file mode 100644 index 000000000..0786176ba --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -0,0 +1,142 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +using internal::WireFormat; + +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options) { + (*variables)["name"] = FieldName(descriptor); + (*variables)["index"] = SimpleItoa(descriptor->index()); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["classname"] = ClassName(FieldScope(descriptor), false); + (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); + + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["deprecation"] = descriptor->options().deprecated() + ? " PROTOBUF_DEPRECATED" : ""; + + (*variables)["cppget"] = "Get"; +} + +FieldGenerator::~FieldGenerator() {} + +void FieldGenerator:: +GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { + // Reaching here indicates a bug. Cases are: + // - This FieldGenerator should support packing, but this method should be + // overridden. + // - This FieldGenerator doesn't support packing, and this method should + // never have been called. + GOOGLE_LOG(FATAL) << "GenerateMergeFromCodedStreamWithPacking() " + << "called on field generator that does not support packing."; + +} + +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + field_generators_(new scoped_ptr[descriptor->field_count()]) { + // Construct all the FieldGenerators. + for (int i = 0; i < descriptor->field_count(); i++) { + field_generators_[i].reset(MakeGenerator(descriptor->field(i), options)); + } +} + +FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, + const Options& options) { + if (field->is_repeated()) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + return new RepeatedMessageFieldGenerator(field, options); + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // RepeatedStringFieldGenerator handles unknown ctypes. + case FieldOptions::STRING: + return new RepeatedStringFieldGenerator(field, options); + } + case FieldDescriptor::CPPTYPE_ENUM: + return new RepeatedEnumFieldGenerator(field, options); + default: + return new RepeatedPrimitiveFieldGenerator(field, options); + } + } else { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + return new MessageFieldGenerator(field, options); + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // StringFieldGenerator handles unknown ctypes. + case FieldOptions::STRING: + return new StringFieldGenerator(field, options); + } + case FieldDescriptor::CPPTYPE_ENUM: + return new EnumFieldGenerator(field, options); + default: + return new PrimitiveFieldGenerator(field, options); + } + } +} + +FieldGeneratorMap::~FieldGeneratorMap() {} + +const FieldGenerator& FieldGeneratorMap::get( + const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h new file mode 100644 index 000000000..f7d99b154 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_field.h @@ -0,0 +1,177 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ + +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +// Helper function: set variables in the map that are the same for all +// field code generators. +// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', +// 'deprecation']. +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options); + +class FieldGenerator { + public: + FieldGenerator() {} + virtual ~FieldGenerator(); + + // Generate lines of code declaring members fields of the message class + // needed to represent this field. These are placed inside the message + // class. + virtual void GeneratePrivateMembers(io::Printer* printer) const = 0; + + // Generate prototypes for all of the accessor functions related to this + // field. These are placed inside the class definition. + virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; + + // Generate inline definitions of accessor functions for this field. + // These are placed inside the header after all class definitions. + virtual void GenerateInlineAccessorDefinitions( + io::Printer* printer) const = 0; + + // Generate definitions of accessors that aren't inlined. These are + // placed somewhere in the .cc file. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const {} + + // Generate lines of code (statements, not declarations) which clear the + // field. This is used to define the clear_$name$() method as well as + // the Clear() method for the whole message. + virtual void GenerateClearingCode(io::Printer* printer) const = 0; + + // Generate lines of code (statements, not declarations) which merges the + // contents of the field from the current message to the target message, + // which is stored in the generated code variable "from". + // This is used to fill in the MergeFrom method for the whole message. + // Details of this usage can be found in message.cc under the + // GenerateMergeFrom method. + virtual void GenerateMergingCode(io::Printer* printer) const = 0; + + // Generate lines of code (statements, not declarations) which swaps + // this field and the corresponding field of another message, which + // is stored in the generated code variable "other". This is used to + // define the Swap method. Details of usage can be found in + // message.cc under the GenerateSwap method. + virtual void GenerateSwappingCode(io::Printer* printer) const = 0; + + // Generate initialization code for private members declared by + // GeneratePrivateMembers(). These go into the message class's SharedCtor() + // method, invoked by each of the generated constructors. + virtual void GenerateConstructorCode(io::Printer* printer) const = 0; + + // Generate any code that needs to go in the class's SharedDtor() method, + // invoked by the destructor. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateDestructorCode(io::Printer* printer) const {} + + // Generate code that allocates the fields's default instance. + virtual void GenerateDefaultInstanceAllocator(io::Printer* printer) const {} + + // Generate code that should be run when ShutdownProtobufLibrary() is called, + // to delete all dynamically-allocated objects. + virtual void GenerateShutdownCode(io::Printer* printer) const {} + + // Generate lines to decode this field, which will be placed inside the + // message's MergeFromCodedStream() method. + virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0; + + // Generate lines to decode this field from a packed value, which will be + // placed inside the message's MergeFromCodedStream() method. + virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) + const; + + // Generate lines to serialize this field, which are placed within the + // message's SerializeWithCachedSizes() method. + virtual void GenerateSerializeWithCachedSizes(io::Printer* printer) const = 0; + + // Generate lines to serialize this field directly to the array "target", + // which are placed within the message's SerializeWithCachedSizesToArray() + // method. This must also advance "target" past the written bytes. + virtual void GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const = 0; + + // Generate lines to compute the serialized size of this field, which + // are placed in the message's ByteSize() method. + virtual void GenerateByteSize(io::Printer* printer) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); +}; + +// Convenience class which constructs FieldGenerators for a Descriptor. +class FieldGeneratorMap { + public: + explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options); + ~FieldGeneratorMap(); + + const FieldGenerator& get(const FieldDescriptor* field) const; + + private: + const Descriptor* descriptor_; + scoped_array > field_generators_; + + static FieldGenerator* MakeGenerator(const FieldDescriptor* field, + const Options& options); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); +}; + + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc new file mode 100644 index 000000000..cfe96c8a7 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -0,0 +1,652 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// =================================================================== + +FileGenerator::FileGenerator(const FileDescriptor* file, + const Options& options) + : file_(file), + message_generators_( + new scoped_ptr[file->message_type_count()]), + enum_generators_( + new scoped_ptr[file->enum_type_count()]), + service_generators_( + new scoped_ptr[file->service_count()]), + extension_generators_( + new scoped_ptr[file->extension_count()]), + options_(options) { + + for (int i = 0; i < file->message_type_count(); i++) { + message_generators_[i].reset( + new MessageGenerator(file->message_type(i), options)); + } + + for (int i = 0; i < file->enum_type_count(); i++) { + enum_generators_[i].reset( + new EnumGenerator(file->enum_type(i), options)); + } + + for (int i = 0; i < file->service_count(); i++) { + service_generators_[i].reset( + new ServiceGenerator(file->service(i), options)); + } + + for (int i = 0; i < file->extension_count(); i++) { + extension_generators_[i].reset( + new ExtensionGenerator(file->extension(i), options)); + } + + SplitStringUsing(file_->package(), ".", &package_parts_); +} + +FileGenerator::~FileGenerator() {} + +void FileGenerator::GenerateHeader(io::Printer* printer) { + string filename_identifier = FilenameIdentifier(file_->name()); + + // Generate top of header. + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n" + "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" + "#define PROTOBUF_$filename_identifier$__INCLUDED\n" + "\n" + "#include \n" + "\n", + "filename", file_->name(), + "filename_identifier", filename_identifier); + + + printer->Print( + "#include \n" + "\n"); + + // Verify the protobuf library header version is compatible with the protoc + // version before going any further. + printer->Print( + "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" + "#error This file was generated by a newer version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please update\n" + "#error your headers.\n" + "#endif\n" + "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" + "#error This file was generated by an older version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please\n" + "#error regenerate this file with a newer version of protoc.\n" + "#endif\n" + "\n", + "min_header_version", + SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), + "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); + + // OK, it's now safe to #include other files. + printer->Print( + "#include \n"); + if (file_->message_type_count() > 0) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } + } + printer->Print( + "#include \n" + "#include \n"); + + if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { + printer->Print( + "#include \n"); + } + + if (HasGenericServices(file_)) { + printer->Print( + "#include \n"); + } + + if (HasUnknownFields(file_) && file_->message_type_count() > 0) { + printer->Print( + "#include \n"); + } + + + for (int i = 0; i < file_->dependency_count(); i++) { + printer->Print( + "#include \"$dependency$.pb.h\"\n", + "dependency", StripProto(file_->dependency(i)->name())); + } + + + printer->Print( + "// @@protoc_insertion_point(includes)\n"); + + + // Open namespace. + GenerateNamespaceOpeners(printer); + + // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile + // functions, so that we can declare them to be friends of each class. + printer->Print( + "\n" + "// Internal implementation detail -- do not call these.\n" + "void $dllexport_decl$ $adddescriptorsname$();\n", + "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), + "dllexport_decl", options_.dllexport_decl); + + printer->Print( + // Note that we don't put dllexport_decl on these because they are only + // called by the .pb.cc file in which they are defined. + "void $assigndescriptorsname$();\n" + "void $shutdownfilename$();\n" + "\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()), + "shutdownfilename", GlobalShutdownFileName(file_->name())); + + // Generate forward declarations of classes. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateForwardDeclaration(printer); + } + + printer->Print("\n"); + + // Generate enum definitions. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateEnumDefinitions(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } + + printer->Print(kThickSeparator); + printer->Print("\n"); + + // Generate class definitions. + for (int i = 0; i < file_->message_type_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + message_generators_[i]->GenerateClassDefinition(printer); + } + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + + if (HasGenericServices(file_)) { + // Generate service definitions. + for (int i = 0; i < file_->service_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + service_generators_[i]->GenerateDeclarations(printer); + } + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + } + + // Declare extension identifiers. + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateDeclaration(printer); + } + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + + // Generate class inline methods. + for (int i = 0; i < file_->message_type_count(); i++) { + if (i > 0) { + printer->Print(kThinSeparator); + printer->Print("\n"); + } + message_generators_[i]->GenerateInlineMethods(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); + + // Close up namespace. + GenerateNamespaceClosers(printer); + + // Emit GetEnumDescriptor specializations into google::protobuf namespace: + if (HasDescriptorMethods(file_)) { + // The SWIG conditional is to avoid a null-pointer dereference + // (bug 1984964) in swig-1.3.21 resulting from the following syntax: + // namespace X { void Y(); } + // which appears in GetEnumDescriptor() specializations. + printer->Print( + "\n" + "#ifndef SWIG\n" + "namespace google {\nnamespace protobuf {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + printer->Print( + "\n" + "} // namespace google\n} // namespace protobuf\n" + "#endif // SWIG\n"); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); + + printer->Print( + "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", + "filename_identifier", filename_identifier); +} + +void FileGenerator::GenerateSource(io::Printer* printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n" + + // The generated code calls accessors that might be deprecated. We don't + // want the compiler to warn in generated code. + "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" + "#include \"$basename$.pb.h\"\n" + "\n" + "#include \n" // for swap() + "\n" + "#include \n" + "#include \n" + "#include \n" + "#include \n", + "filename", file_->name(), + "basename", StripProto(file_->name())); + + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n" + "#include \n" + "#include \n" + "#include \n"); + } + + printer->Print( + "// @@protoc_insertion_point(includes)\n"); + + GenerateNamespaceOpeners(printer); + + if (HasDescriptorMethods(file_)) { + printer->Print( + "\n" + "namespace {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorDeclarations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + printer->Print( + "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", + "name", ClassName(file_->enum_type(i), false)); + } + + if (HasGenericServices(file_)) { + for (int i = 0; i < file_->service_count(); i++) { + printer->Print( + "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", + "name", file_->service(i)->name()); + } + } + + printer->Print( + "\n" + "} // namespace\n" + "\n"); + } + + // Define our externally-visible BuildDescriptors() function. (For the lite + // library, all this does is initialize default instances.) + GenerateBuildDescriptors(printer); + + // Generate enums. + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateMethods(printer); + } + + // Generate classes. + for (int i = 0; i < file_->message_type_count(); i++) { + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + message_generators_[i]->GenerateClassMethods(printer); + } + + if (HasGenericServices(file_)) { + // Generate services. + for (int i = 0; i < file_->service_count(); i++) { + if (i == 0) printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + service_generators_[i]->GenerateImplementation(printer); + } + } + + // Define extensions. + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateDefinition(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); + + GenerateNamespaceClosers(printer); + + printer->Print( + "\n" + "// @@protoc_insertion_point(global_scope)\n"); +} + +void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { + // AddDescriptors() is a file-level procedure which adds the encoded + // FileDescriptorProto for this .proto file to the global DescriptorPool for + // generated files (DescriptorPool::generated_pool()). It either runs at + // static initialization time (by default) or when default_instance() is + // called for the first time (in LITE_RUNTIME mode with + // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also + // constructs default instances and registers extensions. + // + // Its sibling, AssignDescriptors(), actually pulls the compiled + // FileDescriptor from the DescriptorPool and uses it to populate all of + // the global variables which store pointers to the descriptor objects. + // It also constructs the reflection objects. It is called the first time + // anyone calls descriptor() or GetReflection() on one of the types defined + // in the file. + + // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() + // and we only use AddDescriptors() to allocate default instances. + if (HasDescriptorMethods(file_)) { + printer->Print( + "\n" + "void $assigndescriptorsname$() {\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + printer->Indent(); + + // Make sure the file has found its way into the pool. If a descriptor + // is requested *during* static init then AddDescriptors() may not have + // been called yet, so we call it manually. Note that it's fine if + // AddDescriptors() is called multiple times. + printer->Print( + "$adddescriptorsname$();\n", + "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + + // Get the file's descriptor from the pool. + printer->Print( + "const ::google::protobuf::FileDescriptor* file =\n" + " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" + " \"$filename$\");\n" + // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" + // being unused when compiling an empty .proto file. + "GOOGLE_CHECK(file != NULL);\n", + "filename", file_->name()); + + // Go through all the stuff defined in this file and generated code to + // assign the global descriptor pointers based on the file descriptor. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + if (HasGenericServices(file_)) { + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + // --------------------------------------------------------------- + + // protobuf_AssignDescriptorsOnce(): The first time it is called, calls + // AssignDescriptors(). All later times, waits for the first call to + // complete and then returns. + printer->Print( + "namespace {\n" + "\n" + "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" + "inline void protobuf_AssignDescriptorsOnce() {\n" + " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" + " &$assigndescriptorsname$);\n" + "}\n" + "\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + + // protobuf_RegisterTypes(): Calls + // MessageFactory::InternalRegisterGeneratedType() for each message type. + printer->Print( + "void protobuf_RegisterTypes(const ::std::string&) {\n" + " protobuf_AssignDescriptorsOnce();\n"); + printer->Indent(); + + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateTypeRegistrations(printer); + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "} // namespace\n"); + } + + // ----------------------------------------------------------------- + + // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown. + printer->Print( + "\n" + "void $shutdownfilename$() {\n", + "shutdownfilename", GlobalShutdownFileName(file_->name())); + printer->Indent(); + + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateShutdownCode(printer); + } + + printer->Outdent(); + printer->Print( + "}\n\n"); + + // ----------------------------------------------------------------- + + // Now generate the AddDescriptors() function. + PrintHandlingOptionalStaticInitializers( + file_, printer, + // With static initializers. + // Note that we don't need any special synchronization in the following code + // because it is called at static init time before any threads exist. + "void $adddescriptorsname$() {\n" + " static bool already_here = false;\n" + " if (already_here) return;\n" + " already_here = true;\n" + " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" + "\n", + // Without. + "void $adddescriptorsname$_impl() {\n" + " GOOGLE_PROTOBUF_VERIFY_VERSION;\n" + "\n", + // Vars. + "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + + printer->Indent(); + + // Call the AddDescriptors() methods for all of our dependencies, to make + // sure they get added first. + for (int i = 0; i < file_->dependency_count(); i++) { + const FileDescriptor* dependency = file_->dependency(i); + // Print the namespace prefix for the dependency. + vector dependency_package_parts; + SplitStringUsing(dependency->package(), ".", &dependency_package_parts); + printer->Print("::"); + for (int j = 0; j < dependency_package_parts.size(); j++) { + printer->Print("$name$::", + "name", dependency_package_parts[j]); + } + // Call its AddDescriptors function. + printer->Print( + "$name$();\n", + "name", GlobalAddDescriptorsName(dependency->name())); + } + + if (HasDescriptorMethods(file_)) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", + EscapeTrigraphs( + CEscape(file_data.substr(i, kBytesPerLine)))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); + + // Call MessageFactory::InternalRegisterGeneratedFile(). + printer->Print( + "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" + " \"$filename$\", &protobuf_RegisterTypes);\n", + "filename", file_->name()); + } + + // Allocate and initialize default instances. This can't be done lazily + // since default instances are returned by simple accessors and are used with + // extensions. Speaking of which, we also register extensions at this time. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDefaultInstanceAllocator(printer); + } + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateRegistration(printer); + } + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDefaultInstanceInitializer(printer); + } + + printer->Print( + "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n", + "shutdownfilename", GlobalShutdownFileName(file_->name())); + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + PrintHandlingOptionalStaticInitializers( + file_, printer, + // With static initializers. + "// Force AddDescriptors() to be called at static initialization time.\n" + "struct StaticDescriptorInitializer_$filename$ {\n" + " StaticDescriptorInitializer_$filename$() {\n" + " $adddescriptorsname$();\n" + " }\n" + "} static_descriptor_initializer_$filename$_;\n", + // Without. + "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" + "void $adddescriptorsname$() {\n" + " ::google::protobuf::::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" + " &$adddescriptorsname$_impl);\n" + "}\n", + // Vars. + "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), + "filename", FilenameIdentifier(file_->name())); +} + +void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) { + if (package_parts_.size() > 0) printer->Print("\n"); + + for (int i = 0; i < package_parts_.size(); i++) { + printer->Print("namespace $part$ {\n", + "part", package_parts_[i]); + } +} + +void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) { + if (package_parts_.size() > 0) printer->Print("\n"); + + for (int i = package_parts_.size() - 1; i >= 0; i--) { + printer->Print("} // namespace $part$\n", + "part", package_parts_[i]); + } +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h new file mode 100644 index 000000000..2deefaa86 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_file.h @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_FILE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + class FileDescriptor; // descriptor.h + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +class EnumGenerator; // enum.h +class MessageGenerator; // message.h +class ServiceGenerator; // service.h +class ExtensionGenerator; // extension.h + +class FileGenerator { + public: + // See generator.cc for the meaning of dllexport_decl. + explicit FileGenerator(const FileDescriptor* file, + const Options& options); + ~FileGenerator(); + + void GenerateHeader(io::Printer* printer); + void GenerateSource(io::Printer* printer); + + private: + // Generate the BuildDescriptors() procedure, which builds all descriptors + // for types defined in the file. + void GenerateBuildDescriptors(io::Printer* printer); + + void GenerateNamespaceOpeners(io::Printer* printer); + void GenerateNamespaceClosers(io::Printer* printer); + + const FileDescriptor* file_; + + scoped_array > message_generators_; + scoped_array > enum_generators_; + scoped_array > service_generators_; + scoped_array > extension_generators_; + + // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. + vector package_parts_; + + const Options options_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc new file mode 100644 index 000000000..1813510b6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +CppGenerator::CppGenerator() {} +CppGenerator::~CppGenerator() {} + +bool CppGenerator::Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const { + vector > options; + ParseGeneratorParameter(parameter, &options); + + // ----------------------------------------------------------------- + // parse generator options + + // TODO(kenton): If we ever have more options, we may want to create a + // class that encapsulates them which we can pass down to all the + // generator classes. Currently we pass dllexport_decl down to all of + // them via the constructors, but we don't want to have to add another + // constructor parameter for every option. + + // If the dllexport_decl option is passed to the compiler, we need to write + // it in front of every symbol that should be exported if this .proto is + // compiled into a Windows DLL. E.g., if the user invokes the protocol + // compiler as: + // protoc --cpp_out=dllexport_decl=FOO_EXPORT:outdir foo.proto + // then we'll define classes like this: + // class FOO_EXPORT Foo { + // ... + // } + // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or + // __declspec(dllimport) depending on what is being compiled. + Options file_options; + + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "dllexport_decl") { + file_options.dllexport_decl = options[i].second; + } else if (options[i].first == "safe_boundary_check") { + file_options.safe_boundary_check = true; + } else { + *error = "Unknown generator option: " + options[i].first; + return false; + } + } + + // ----------------------------------------------------------------- + + + string basename = StripProto(file->name()); + basename.append(".pb"); + + FileGenerator file_generator(file, file_options); + + // Generate header. + { + scoped_ptr output( + generator_context->Open(basename + ".h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateHeader(&printer); + } + + // Generate cc file. + { + scoped_ptr output( + generator_context->Open(basename + ".cc")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateSource(&printer); + } + + return true; +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.h new file mode 100644 index 000000000..a90e84d7b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Generates C++ code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// CodeGenerator implementation which generates a C++ source file and +// header. If you create your own protocol compiler binary and you want +// it to support C++ output, you can do so by registering an instance of this +// CodeGenerator with the CommandLineInterface in your main() function. +class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { + public: + CppGenerator(); + ~CppGenerator(); + + // implements CodeGenerator ---------------------------------------- + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc new file mode 100644 index 000000000..28911ab00 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -0,0 +1,438 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +string DotsToUnderscores(const string& name) { + return StringReplace(name, ".", "_", true); +} + +string DotsToColons(const string& name) { + return StringReplace(name, ".", "::", true); +} + +const char* const kKeywordList[] = { + "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case", + "catch", "char", "class", "compl", "const", "const_cast", "continue", + "default", "delete", "do", "double", "dynamic_cast", "else", "enum", + "explicit", "extern", "false", "float", "for", "friend", "goto", "if", + "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq", + "operator", "or", "or_eq", "private", "protected", "public", "register", + "reinterpret_cast", "return", "short", "signed", "sizeof", "static", + "static_cast", "struct", "switch", "template", "this", "throw", "true", "try", + "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", + "void", "volatile", "wchar_t", "while", "xor", "xor_eq" +}; + +hash_set MakeKeywordsMap() { + hash_set result; + for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) { + result.insert(kKeywordList[i]); + } + return result; +} + +hash_set kKeywords = MakeKeywordsMap(); + +string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { + string result; + // Note: I distrust ctype.h due to locales. + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + if (cap_next_letter) { + result += input[i] + ('A' - 'a'); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if ('A' <= input[i] && input[i] <= 'Z') { + // Capital letters are left as-is. + result += input[i]; + cap_next_letter = false; + } else if ('0' <= input[i] && input[i] <= '9') { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + } + } + return result; +} + +// Returns whether the provided descriptor has an extension. This includes its +// nested types. +bool HasExtension(const Descriptor* descriptor) { + if (descriptor->extension_count() > 0) { + return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasExtension(descriptor->nested_type(i))) { + return true; + } + } + return false; +} + +} // namespace + +const char kThickSeparator[] = + "// ===================================================================\n"; +const char kThinSeparator[] = + "// -------------------------------------------------------------------\n"; + +string ClassName(const Descriptor* descriptor, bool qualified) { + + // Find "outer", the descriptor of the top-level message in which + // "descriptor" is embedded. + const Descriptor* outer = descriptor; + while (outer->containing_type() != NULL) outer = outer->containing_type(); + + const string& outer_name = outer->full_name(); + string inner_name = descriptor->full_name().substr(outer_name.size()); + + if (qualified) { + return "::" + DotsToColons(outer_name) + DotsToUnderscores(inner_name); + } else { + return outer->name() + DotsToUnderscores(inner_name); + } +} + +string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) { + if (enum_descriptor->containing_type() == NULL) { + if (qualified) { + return "::" + DotsToColons(enum_descriptor->full_name()); + } else { + return enum_descriptor->name(); + } + } else { + string result = ClassName(enum_descriptor->containing_type(), qualified); + result += '_'; + result += enum_descriptor->name(); + return result; + } +} + + +string SuperClassName(const Descriptor* descriptor) { + return HasDescriptorMethods(descriptor->file()) ? + "::google::protobuf::Message" : "::google::protobuf::MessageLite"; +} + +string FieldName(const FieldDescriptor* field) { + string result = field->name(); + LowerString(&result); + if (kKeywords.count(result) > 0) { + result.append("_"); + } + return result; +} + +string FieldConstantName(const FieldDescriptor *field) { + string field_name = UnderscoresToCamelCase(field->name(), true); + string result = "k" + field_name + "FieldNumber"; + + if (!field->is_extension() && + field->containing_type()->FindFieldByCamelcaseName( + field->camelcase_name()) != field) { + // This field's camelcase name is not unique. As a hack, add the field + // number to the constant name. This makes the constant rather useless, + // but what can we do? + result += "_" + SimpleItoa(field->number()); + } + + return result; +} + +string FieldMessageTypeName(const FieldDescriptor* field) { + // Note: The Google-internal version of Protocol Buffers uses this function + // as a hook point for hacks to support legacy code. + return ClassName(field->message_type(), true); +} + +string StripProto(const string& filename) { + if (HasSuffixString(filename, ".protodevel")) { + return StripSuffixString(filename, ".protodevel"); + } else { + return StripSuffixString(filename, ".proto"); + } +} + +const char* PrimitiveTypeName(FieldDescriptor::CppType type) { + switch (type) { + case FieldDescriptor::CPPTYPE_INT32 : return "::google::protobuf::int32"; + case FieldDescriptor::CPPTYPE_INT64 : return "::google::protobuf::int64"; + case FieldDescriptor::CPPTYPE_UINT32 : return "::google::protobuf::uint32"; + case FieldDescriptor::CPPTYPE_UINT64 : return "::google::protobuf::uint64"; + case FieldDescriptor::CPPTYPE_DOUBLE : return "double"; + case FieldDescriptor::CPPTYPE_FLOAT : return "float"; + case FieldDescriptor::CPPTYPE_BOOL : return "bool"; + case FieldDescriptor::CPPTYPE_ENUM : return "int"; + case FieldDescriptor::CPPTYPE_STRING : return "::std::string"; + case FieldDescriptor::CPPTYPE_MESSAGE: return NULL; + + // No default because we want the compiler to complain if any new + // CppTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return "Int32"; + case FieldDescriptor::TYPE_INT64 : return "Int64"; + case FieldDescriptor::TYPE_UINT32 : return "UInt32"; + case FieldDescriptor::TYPE_UINT64 : return "UInt64"; + case FieldDescriptor::TYPE_SINT32 : return "SInt32"; + case FieldDescriptor::TYPE_SINT64 : return "SInt64"; + case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; + case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; + case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT : return "Float"; + case FieldDescriptor::TYPE_DOUBLE : return "Double"; + + case FieldDescriptor::TYPE_BOOL : return "Bool"; + case FieldDescriptor::TYPE_ENUM : return "Enum"; + + case FieldDescriptor::TYPE_STRING : return "String"; + case FieldDescriptor::TYPE_BYTES : return "Bytes"; + case FieldDescriptor::TYPE_GROUP : return "Group"; + case FieldDescriptor::TYPE_MESSAGE : return "Message"; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + +string DefaultValue(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + // gcc rejects the decimal form of kint32min and kint64min. + if (field->default_value_int32() == kint32min) { + // Make sure we are in a 2's complement system. + GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error); + return "-0x80000000"; + } + return SimpleItoa(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + return SimpleItoa(field->default_value_uint32()) + "u"; + case FieldDescriptor::CPPTYPE_INT64: + // See the comments for CPPTYPE_INT32. + if (field->default_value_int64() == kint64min) { + // Make sure we are in a 2's complement system. + GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000), + kint64min_value_error); + return "GOOGLE_LONGLONG(-0x8000000000000000)"; + } + return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")"; + case FieldDescriptor::CPPTYPE_UINT64: + return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value = field->default_value_double(); + if (value == numeric_limits::infinity()) { + return "::google::protobuf::internal::Infinity()"; + } else if (value == -numeric_limits::infinity()) { + return "-::google::protobuf::internal::Infinity()"; + } else if (value != value) { + return "::google::protobuf::internal::NaN()"; + } else { + return SimpleDtoa(value); + } + } + case FieldDescriptor::CPPTYPE_FLOAT: + { + float value = field->default_value_float(); + if (value == numeric_limits::infinity()) { + return "static_cast(::google::protobuf::internal::Infinity())"; + } else if (value == -numeric_limits::infinity()) { + return "static_cast(-::google::protobuf::internal::Infinity())"; + } else if (value != value) { + return "static_cast(::google::protobuf::internal::NaN())"; + } else { + string float_value = SimpleFtoa(value); + // If floating point value contains a period (.) or an exponent + // (either E or e), then append suffix 'f' to make it a float + // literal. + if (float_value.find_first_of(".eE") != string::npos) { + float_value.push_back('f'); + } + return float_value; + } + } + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_ENUM: + // Lazy: Generate a static_cast because we don't have a helper function + // that constructs the full name of an enum value. + return strings::Substitute( + "static_cast< $0 >($1)", + ClassName(field->enum_type(), true), + field->default_value_enum()->number()); + case FieldDescriptor::CPPTYPE_STRING: + return "\"" + EscapeTrigraphs( + CEscape(field->default_value_string())) + + "\""; + case FieldDescriptor::CPPTYPE_MESSAGE: + return FieldMessageTypeName(field) + "::default_instance()"; + } + // Can't actually get here; make compiler happy. (We could add a default + // case above but then we wouldn't get the nice compiler warning when a + // new type is added.) + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + +// Convert a file name into a valid identifier. +string FilenameIdentifier(const string& filename) { + string result; + for (int i = 0; i < filename.size(); i++) { + if (ascii_isalnum(filename[i])) { + result.push_back(filename[i]); + } else { + // Not alphanumeric. To avoid any possibility of name conflicts we + // use the hex code for the character. + result.push_back('_'); + char buffer[kFastToBufferSize]; + result.append(FastHexToBuffer(static_cast(filename[i]), buffer)); + } + } + return result; +} + +// Return the name of the AddDescriptors() function for a given file. +string GlobalAddDescriptorsName(const string& filename) { + return "protobuf_AddDesc_" + FilenameIdentifier(filename); +} + +// Return the name of the AssignDescriptors() function for a given file. +string GlobalAssignDescriptorsName(const string& filename) { + return "protobuf_AssignDesc_" + FilenameIdentifier(filename); +} + +// Return the name of the ShutdownFile() function for a given file. +string GlobalShutdownFileName(const string& filename) { + return "protobuf_ShutdownFile_" + FilenameIdentifier(filename); +} + +// Escape C++ trigraphs by escaping question marks to \? +string EscapeTrigraphs(const string& to_escape) { + return StringReplace(to_escape, "?", "\\?", true); +} + +bool StaticInitializersForced(const FileDescriptor* file) { + if (HasDescriptorMethods(file) || file->extension_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasExtension(file->message_type(i))) { + return true; + } + } + return false; +} + +void PrintHandlingOptionalStaticInitializers( + const FileDescriptor* file, io::Printer* printer, + const char* with_static_init, const char* without_static_init, + const char* var1, const string& val1, + const char* var2, const string& val2) { + map vars; + if (var1) { + vars[var1] = val1; + } + if (var2) { + vars[var2] = val2; + } + PrintHandlingOptionalStaticInitializers( + vars, file, printer, with_static_init, without_static_init); +} + +void PrintHandlingOptionalStaticInitializers( + const map& vars, const FileDescriptor* file, + io::Printer* printer, const char* with_static_init, + const char* without_static_init) { + if (StaticInitializersForced(file)) { + printer->Print(vars, with_static_init); + } else { + printer->Print(vars, (string( + "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") + + without_static_init + + "#else\n" + + with_static_init + + "#endif\n").c_str()); + } +} + + +static bool HasEnumDefinitions(const Descriptor* message_type) { + if (message_type->enum_type_count() > 0) return true; + for (int i = 0; i < message_type->nested_type_count(); ++i) { + if (HasEnumDefinitions(message_type->nested_type(i))) return true; + } + return false; +} + +bool HasEnumDefinitions(const FileDescriptor* file) { + if (file->enum_type_count() > 0) return true; + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasEnumDefinitions(file->message_type(i))) return true; + } + return false; +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h new file mode 100644 index 000000000..526e19cc7 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -0,0 +1,186 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace io { +class Printer; +} + +namespace compiler { +namespace cpp { + +// Commonly-used separator comments. Thick is a line of '=', thin is a line +// of '-'. +extern const char kThickSeparator[]; +extern const char kThinSeparator[]; + +// Returns the non-nested type name for the given type. If "qualified" is +// true, prefix the type with the full namespace. For example, if you had: +// package foo.bar; +// message Baz { message Qux {} } +// Then the qualified ClassName for Qux would be: +// ::foo::bar::Baz_Qux +// While the non-qualified version would be: +// Baz_Qux +string ClassName(const Descriptor* descriptor, bool qualified); +string ClassName(const EnumDescriptor* enum_descriptor, bool qualified); + +string SuperClassName(const Descriptor* descriptor); + +// Get the (unqualified) name that should be used for this field in C++ code. +// The name is coerced to lower-case to emulate proto1 behavior. People +// should be using lowercase-with-underscores style for proto field names +// anyway, so normally this just returns field->name(). +string FieldName(const FieldDescriptor* field); + +// Get the unqualified name that should be used for a field's field +// number constant. +string FieldConstantName(const FieldDescriptor *field); + +// Returns the scope where the field was defined (for extensions, this is +// different from the message type to which the field applies). +inline const Descriptor* FieldScope(const FieldDescriptor* field) { + return field->is_extension() ? + field->extension_scope() : field->containing_type(); +} + +// Returns the fully-qualified type name field->message_type(). Usually this +// is just ClassName(field->message_type(), true); +string FieldMessageTypeName(const FieldDescriptor* field); + +// Strips ".proto" or ".protodevel" from the end of a filename. +string StripProto(const string& filename); + +// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.). +// Note: non-built-in type names will be qualified, meaning they will start +// with a ::. If you are using the type as a template parameter, you will +// need to insure there is a space between the < and the ::, because the +// ridiculous C++ standard defines "<:" to be a synonym for "[". +const char* PrimitiveTypeName(FieldDescriptor::CppType type); + +// Get the declared type name in CamelCase format, as is used e.g. for the +// methods of WireFormat. For example, TYPE_INT32 becomes "Int32". +const char* DeclaredTypeMethodName(FieldDescriptor::Type type); + +// Get code that evaluates to the field's default value. +string DefaultValue(const FieldDescriptor* field); + +// Convert a file name into a valid identifier. +string FilenameIdentifier(const string& filename); + +// Return the name of the AddDescriptors() function for a given file. +string GlobalAddDescriptorsName(const string& filename); + +// Return the name of the AssignDescriptors() function for a given file. +string GlobalAssignDescriptorsName(const string& filename); + +// Return the name of the ShutdownFile() function for a given file. +string GlobalShutdownFileName(const string& filename); + +// Escape C++ trigraphs by escaping question marks to \? +string EscapeTrigraphs(const string& to_escape); + +// Do message classes in this file keep track of unknown fields? +inline bool HasUnknownFields(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + + +// Does this file have any enum type definitions? +bool HasEnumDefinitions(const FileDescriptor* file); + +// Does this file have generated parsing, serialization, and other +// standard methods for which reflection-based fallback implementations exist? +inline bool HasGeneratedMethods(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::CODE_SIZE; +} + +// Do message classes in this file have descriptor and reflection methods? +inline bool HasDescriptorMethods(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should we generate generic services for this file? +inline bool HasGenericServices(const FileDescriptor* file) { + return file->service_count() > 0 && + file->options().optimize_for() != FileOptions::LITE_RUNTIME && + file->options().cc_generic_services(); +} + +// Should string fields in this file verify that their contents are UTF-8? +inline bool HasUtf8Verification(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should we generate a separate, super-optimized code path for serializing to +// flat arrays? We don't do this in Lite mode because we'd rather reduce code +// size. +inline bool HasFastArraySerialization(const FileDescriptor* file) { + return file->options().optimize_for() == FileOptions::SPEED; +} + +// Returns whether we have to generate code with static initializers. +bool StaticInitializersForced(const FileDescriptor* file); + +// Prints 'with_static_init' if static initializers have to be used for the +// provided file. Otherwise emits both 'with_static_init' and +// 'without_static_init' using #ifdef. +void PrintHandlingOptionalStaticInitializers( + const FileDescriptor* file, io::Printer* printer, + const char* with_static_init, const char* without_static_init, + const char* var1 = NULL, const string& val1 = "", + const char* var2 = NULL, const string& val2 = ""); + +void PrintHandlingOptionalStaticInitializers( + const map& vars, const FileDescriptor* file, + io::Printer* printer, const char* with_static_init, + const char* without_static_init); + + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc new file mode 100644 index 000000000..1ea4f13d1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -0,0 +1,2020 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { + // Print the field's proto-syntax definition as a comment. We don't want to + // print group bodies so we cut off after the first line. + string def = field->DebugString(); + printer->Print("// $def$\n", + "def", def.substr(0, def.find_first_of('\n'))); +} + +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +const char* kWireTypeNames[] = { + "VARINT", + "FIXED64", + "LENGTH_DELIMITED", + "START_GROUP", + "END_GROUP", + "FIXED32", +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Functor for sorting extension ranges by their "start" field number. +struct ExtensionRangeSorter { + bool operator()(const Descriptor::ExtensionRange* left, + const Descriptor::ExtensionRange* right) const { + return left->start < right->start; + } +}; + +// Returns true if the "required" restriction check should be ignored for the +// given field. +inline static bool ShouldIgnoreRequiredFieldCheck( + const FieldDescriptor* field) { + return false; +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its IsInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +static bool HasRequiredFields( + const Descriptor* type, + hash_set* already_seen) { + if (already_seen->count(type) > 0) { + // Since the first occurrence of a required field causes the whole + // function to return true, we can assume that if the type is already + // in the cache it didn't have any required fields. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field)) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + + return false; +} + +static bool HasRequiredFields(const Descriptor* type) { + hash_set already_seen; + return HasRequiredFields(type, &already_seen); +} + +// This returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field) { + if (field == NULL) return 0; + if (field->is_repeated()) return 8; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return 1; + + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + return 4; + + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return 8; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; // Make compiler happy. +} + +// FieldGroup is just a helper for OptimizePadding below. It holds a vector of +// fields that are grouped together because they have compatible alignment, and +// a preferred location in the final field ordering. +class FieldGroup { + public: + FieldGroup() + : preferred_location_(0) {} + + // A group with a single field. + FieldGroup(float preferred_location, const FieldDescriptor* field) + : preferred_location_(preferred_location), + fields_(1, field) {} + + // Append the fields in 'other' to this group. + void Append(const FieldGroup& other) { + if (other.fields_.empty()) { + return; + } + // Preferred location is the average among all the fields, so we weight by + // the number of fields on each FieldGroup object. + preferred_location_ = + (preferred_location_ * fields_.size() + + (other.preferred_location_ * other.fields_.size())) / + (fields_.size() + other.fields_.size()); + fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); + } + + void SetPreferredLocation(float location) { preferred_location_ = location; } + const vector& fields() const { return fields_; } + + // FieldGroup objects sort by their preferred location. + bool operator<(const FieldGroup& other) const { + return preferred_location_ < other.preferred_location_; + } + + private: + // "preferred_location_" is an estimate of where this group should go in the + // final list of fields. We compute this by taking the average index of each + // field in this group in the original ordering of fields. This is very + // approximate, but should put this group close to where its member fields + // originally went. + float preferred_location_; + vector fields_; + // We rely on the default copy constructor and operator= so this type can be + // used in a vector. +}; + +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, the alignment padding is minimized. We try to do this while keeping +// each field as close as possible to its original position so that we don't +// reduce cache locality much for function that access each field in order. +void OptimizePadding(vector* fields) { + // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. + vector aligned_to_1, aligned_to_4, aligned_to_8; + for (int i = 0; i < fields->size(); ++i) { + switch (EstimateAlignmentSize((*fields)[i])) { + case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; + case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; + case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; + default: + GOOGLE_LOG(FATAL) << "Unknown alignment size."; + } + } + + // Now group fields aligned to 1 byte into sets of 4, and treat those like a + // single field aligned to 4 bytes. + for (int i = 0; i < aligned_to_1.size(); i += 4) { + FieldGroup field_group; + for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { + field_group.Append(aligned_to_1[j]); + } + aligned_to_4.push_back(field_group); + } + // Sort by preferred location to keep fields as close to their original + // location as possible. + sort(aligned_to_4.begin(), aligned_to_4.end()); + + // Now group fields aligned to 4 bytes (or the 4-field groups created above) + // into pairs, and treat those like a single field aligned to 8 bytes. + for (int i = 0; i < aligned_to_4.size(); i += 2) { + FieldGroup field_group; + for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { + field_group.Append(aligned_to_4[j]); + } + if (i == aligned_to_4.size() - 1) { + // Move incomplete 4-byte block to the end. + field_group.SetPreferredLocation(fields->size() + 1); + } + aligned_to_8.push_back(field_group); + } + // Sort by preferred location to keep fields as close to their original + // location as possible. + sort(aligned_to_8.begin(), aligned_to_8.end()); + + // Now pull out all the FieldDescriptors in order. + fields->clear(); + for (int i = 0; i < aligned_to_8.size(); ++i) { + fields->insert(fields->end(), + aligned_to_8[i].fields().begin(), + aligned_to_8[i].fields().end()); + } +} + +} + +// =================================================================== + +MessageGenerator::MessageGenerator(const Descriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + field_generators_(descriptor, options), + nested_generators_(new scoped_ptr[ + descriptor->nested_type_count()]), + enum_generators_(new scoped_ptr[ + descriptor->enum_type_count()]), + extension_generators_(new scoped_ptr[ + descriptor->extension_count()]) { + + for (int i = 0; i < descriptor->nested_type_count(); i++) { + nested_generators_[i].reset( + new MessageGenerator(descriptor->nested_type(i), options)); + } + + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enum_generators_[i].reset( + new EnumGenerator(descriptor->enum_type(i), options)); + } + + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset( + new ExtensionGenerator(descriptor->extension(i), options)); + } +} + +MessageGenerator::~MessageGenerator() {} + +void MessageGenerator:: +GenerateForwardDeclaration(io::Printer* printer) { + printer->Print("class $classname$;\n", + "classname", classname_); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateForwardDeclaration(printer); + } +} + +void MessageGenerator:: +GenerateEnumDefinitions(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateEnumDefinitions(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } +} + +void MessageGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } +} + +void MessageGenerator:: +GenerateFieldAccessorDeclarations(io::Printer* printer) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map vars; + SetCommonFieldVariables(field, &vars, options_); + vars["constant_name"] = FieldConstantName(field); + + if (field->is_repeated()) { + printer->Print(vars, "inline int $name$_size() const$deprecation$;\n"); + } else { + printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n"); + } + + printer->Print(vars, "inline void clear_$name$()$deprecation$;\n"); + printer->Print(vars, "static const int $constant_name$ = $number$;\n"); + + // Generate type-specific accessor declarations. + field_generators_.get(field).GenerateAccessorDeclarations(printer); + + printer->Print("\n"); + } + + if (descriptor_->extension_range_count() > 0) { + // Generate accessors for extensions. We just call a macro located in + // extension_set.h since the accessors about 80 lines of static code. + printer->Print( + "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", + "classname", classname_); + } +} + +void MessageGenerator:: +GenerateFieldAccessorDefinitions(io::Printer* printer) { + printer->Print("// $classname$\n\n", "classname", classname_); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map vars; + SetCommonFieldVariables(field, &vars, options_); + + // Generate has_$name$() or $name$_size(). + if (field->is_repeated()) { + printer->Print(vars, + "inline int $classname$::$name$_size() const {\n" + " return $name$_.size();\n" + "}\n"); + } else { + // Singular field. + char buffer[kFastToBufferSize]; + vars["has_array_index"] = SimpleItoa(field->index() / 32); + vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); + printer->Print(vars, + "inline bool $classname$::has_$name$() const {\n" + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n" + "inline void $classname$::clear_has_$name$() {\n" + " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" + "}\n" + ); + } + + // Generate clear_$name$() + printer->Print(vars, + "inline void $classname$::clear_$name$() {\n"); + + printer->Indent(); + field_generators_.get(field).GenerateClearingCode(printer); + printer->Outdent(); + + if (!field->is_repeated()) { + printer->Print(vars, + " clear_has_$name$();\n"); + } + + printer->Print("}\n"); + + // Generate type-specific accessors. + field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); + + printer->Print("\n"); + } +} + +void MessageGenerator:: +GenerateClassDefinition(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateClassDefinition(printer); + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + map vars; + vars["classname"] = classname_; + vars["field_count"] = SimpleItoa(descriptor_->field_count()); + if (options_.dllexport_decl.empty()) { + vars["dllexport"] = ""; + } else { + vars["dllexport"] = options_.dllexport_decl + " "; + } + vars["superclass"] = SuperClassName(descriptor_); + + printer->Print(vars, + "class $dllexport$$classname$ : public $superclass$ {\n" + " public:\n"); + printer->Indent(); + + printer->Print(vars, + "$classname$();\n" + "virtual ~$classname$();\n" + "\n" + "$classname$(const $classname$& from);\n" + "\n" + "inline $classname$& operator=(const $classname$& from) {\n" + " CopyFrom(from);\n" + " return *this;\n" + "}\n" + "\n"); + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" + " return _unknown_fields_;\n" + "}\n" + "\n" + "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n" + " return &_unknown_fields_;\n" + "}\n" + "\n"); + } + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print(vars, + "static const ::google::protobuf::Descriptor* descriptor();\n"); + } + + printer->Print(vars, + "static const $classname$& default_instance();\n" + "\n"); + + if (!StaticInitializersForced(descriptor_->file())) { + printer->Print(vars, + "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" + "// Returns the internal default instance pointer. This function can\n" + "// return NULL thus should not be used by the user. This is intended\n" + "// for Protobuf internal code. Please use default_instance() declared\n" + "// above instead.\n" + "static inline const $classname$* internal_default_instance() {\n" + " return default_instance_;\n" + "}\n" + "#endif\n" + "\n"); + } + + + printer->Print(vars, + "void Swap($classname$* other);\n" + "\n" + "// implements Message ----------------------------------------------\n" + "\n" + "$classname$* New() const;\n"); + + if (HasGeneratedMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "void CopyFrom(const ::google::protobuf::Message& from);\n" + "void MergeFrom(const ::google::protobuf::Message& from);\n"); + } else { + printer->Print(vars, + "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n"); + } + + printer->Print(vars, + "void CopyFrom(const $classname$& from);\n" + "void MergeFrom(const $classname$& from);\n" + "void Clear();\n" + "bool IsInitialized() const;\n" + "\n" + "int ByteSize() const;\n" + "bool MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input);\n" + "void SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + if (HasFastArraySerialization(descriptor_->file())) { + printer->Print( + "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); + } + } + + printer->Print(vars, + "int GetCachedSize() const { return _cached_size_; }\n" + "private:\n" + "void SharedCtor();\n" + "void SharedDtor();\n" + "void SetCachedSize(int size) const;\n" + "public:\n" + "\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata GetMetadata() const;\n" + "\n"); + } else { + printer->Print( + "::std::string GetTypeName() const;\n" + "\n"); + } + + printer->Print( + "// nested types ----------------------------------------------------\n" + "\n"); + + // Import all nested message classes into this class's scope with typedefs. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + const Descriptor* nested_type = descriptor_->nested_type(i); + printer->Print("typedef $nested_full_name$ $nested_name$;\n", + "nested_name", nested_type->name(), + "nested_full_name", ClassName(nested_type, false)); + } + + if (descriptor_->nested_type_count() > 0) { + printer->Print("\n"); + } + + // Import all nested enums and their values into this class's scope with + // typedefs and constants. + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateSymbolImports(printer); + printer->Print("\n"); + } + + printer->Print( + "// accessors -------------------------------------------------------\n" + "\n"); + + // Generate accessor methods for all fields. + GenerateFieldAccessorDeclarations(printer); + + // Declare extension identifiers. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateDeclaration(printer); + } + + + printer->Print( + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + // Generate private members. + printer->Outdent(); + printer->Print(" private:\n"); + printer->Indent(); + + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->is_repeated()) { + printer->Print( + "inline void set_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + printer->Print( + "inline void clear_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + } + } + printer->Print("\n"); + + // To minimize padding, data members are divided into three sections: + // (1) members assumed to align to 8 bytes + // (2) members corresponding to message fields, re-ordered to optimize + // alignment. + // (3) members assumed to align to 4 bytes. + + // Members assumed to align to 8 bytes: + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "::google::protobuf::internal::ExtensionSet _extensions_;\n" + "\n"); + } + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" + "\n"); + } + + // Field members: + + vector fields; + for (int i = 0; i < descriptor_->field_count(); i++) { + fields.push_back(descriptor_->field(i)); + } + OptimizePadding(&fields); + for (int i = 0; i < fields.size(); ++i) { + field_generators_.get(fields[i]).GeneratePrivateMembers(printer); + } + + // Members assumed to align to 4 bytes: + + // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. + printer->Print( + "\n" + "mutable int _cached_size_;\n"); + + // Generate _has_bits_. + if (descriptor_->field_count() > 0) { + printer->Print(vars, + "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n" + "\n"); + } else { + // Zero-size arrays aren't technically allowed, and MSVC in particular + // doesn't like them. We still need to declare these arrays to make + // other code compile. Since this is an uncommon case, we'll just declare + // them with size 1 and waste some space. Oh well. + printer->Print( + "::google::protobuf::uint32 _has_bits_[1];\n" + "\n"); + } + + // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as + // friends so that they can access private static variables like + // default_instance_ and reflection_. + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + "friend void $dllexport_decl$ $adddescriptorsname$();\n", + // Without. + "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", + // Vars. + "dllexport_decl", options_.dllexport_decl, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + + printer->Print( + "friend void $assigndescriptorsname$();\n" + "friend void $shutdownfilename$();\n" + "\n", + "assigndescriptorsname", + GlobalAssignDescriptorsName(descriptor_->file()->name()), + "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); + + printer->Print( + "void InitAsDefaultInstance();\n" + "static $classname$* default_instance_;\n", + "classname", classname_); + + printer->Outdent(); + printer->Print(vars, "};"); +} + +void MessageGenerator:: +GenerateInlineMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateInlineMethods(printer); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + GenerateFieldAccessorDefinitions(printer); +} + +void MessageGenerator:: +GenerateDescriptorDeclarations(io::Printer* printer) { + printer->Print( + "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n" + "const ::google::protobuf::internal::GeneratedMessageReflection*\n" + " $name$_reflection_ = NULL;\n", + "name", classname_); + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDescriptorDeclarations(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + printer->Print( + "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", + "name", ClassName(descriptor_->enum_type(i), false)); + } +} + +void MessageGenerator:: +GenerateDescriptorInitializer(io::Printer* printer, int index) { + // TODO(kenton): Passing the index to this method is redundant; just use + // descriptor_->index() instead. + map vars; + vars["classname"] = classname_; + vars["index"] = SimpleItoa(index); + + // Obtain the descriptor from the parent's descriptor. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "$classname$_descriptor_ = file->message_type($index$);\n"); + } else { + vars["parent"] = ClassName(descriptor_->containing_type(), false); + printer->Print(vars, + "$classname$_descriptor_ = " + "$parent$_descriptor_->nested_type($index$);\n"); + } + + // Generate the offsets. + GenerateOffsets(printer); + + // Construct the reflection object. + printer->Print(vars, + "$classname$_reflection_ =\n" + " new ::google::protobuf::internal::GeneratedMessageReflection(\n" + " $classname$_descriptor_,\n" + " $classname$::default_instance_,\n" + " $classname$_offsets_,\n" + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n" + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _unknown_fields_),\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _extensions_),\n"); + } else { + // No extensions. + printer->Print(vars, + " -1,\n"); + } + printer->Print( + " ::google::protobuf::DescriptorPool::generated_pool(),\n"); + printer->Print(vars, + " ::google::protobuf::MessageFactory::generated_factory(),\n"); + printer->Print(vars, + " sizeof($classname$));\n"); + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorInitializer(printer, i); + } +} + +void MessageGenerator:: +GenerateTypeRegistrations(io::Printer* printer) { + // Register this message type with the message factory. + printer->Print( + "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" + " $classname$_descriptor_, &$classname$::default_instance());\n", + "classname", classname_); + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateTypeRegistrations(printer); + } +} + +void MessageGenerator:: +GenerateDefaultInstanceAllocator(io::Printer* printer) { + // Construct the default instances of all fields, as they will be used + // when creating the default instance of the entire message. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateDefaultInstanceAllocator(printer); + } + + // Construct the default instance. We can't call InitAsDefaultInstance() yet + // because we need to make sure all default instances that this one might + // depend on are constructed first. + printer->Print( + "$classname$::default_instance_ = new $classname$();\n", + "classname", classname_); + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); + } + +} + +void MessageGenerator:: +GenerateDefaultInstanceInitializer(io::Printer* printer) { + printer->Print( + "$classname$::default_instance_->InitAsDefaultInstance();\n", + "classname", classname_); + + // Register extensions. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateRegistration(printer); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDefaultInstanceInitializer(printer); + } +} + +void MessageGenerator:: +GenerateShutdownCode(io::Printer* printer) { + printer->Print( + "delete $classname$::default_instance_;\n", + "classname", classname_); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "delete $classname$_reflection_;\n", + "classname", classname_); + } + + // Handle default instances of fields. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateShutdownCode(printer); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateShutdownCode(printer); + } +} + +void MessageGenerator:: +GenerateClassMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateMethods(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateClassMethods(printer); + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + // Generate non-inline field definitions. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateNonInlineAccessorDefinitions(printer); + } + + // Generate field number constants. + printer->Print("#ifndef _MSC_VER\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = descriptor_->field(i); + printer->Print( + "const int $classname$::$constant_name$;\n", + "classname", ClassName(FieldScope(field), false), + "constant_name", FieldConstantName(field)); + } + printer->Print( + "#endif // !_MSC_VER\n" + "\n"); + + // Define extension identifiers. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateDefinition(printer); + } + + GenerateStructors(printer); + printer->Print("\n"); + + if (HasGeneratedMethods(descriptor_->file())) { + GenerateClear(printer); + printer->Print("\n"); + + GenerateMergeFromCodedStream(printer); + printer->Print("\n"); + + GenerateSerializeWithCachedSizes(printer); + printer->Print("\n"); + + if (HasFastArraySerialization(descriptor_->file())) { + GenerateSerializeWithCachedSizesToArray(printer); + printer->Print("\n"); + } + + GenerateByteSize(printer); + printer->Print("\n"); + + GenerateMergeFrom(printer); + printer->Print("\n"); + + GenerateCopyFrom(printer); + printer->Print("\n"); + + GenerateIsInitialized(printer); + printer->Print("\n"); + } + + GenerateSwap(printer); + printer->Print("\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" + " protobuf_AssignDescriptorsOnce();\n" + " ::google::protobuf::Metadata metadata;\n" + " metadata.descriptor = $classname$_descriptor_;\n" + " metadata.reflection = $classname$_reflection_;\n" + " return metadata;\n" + "}\n" + "\n", + "classname", classname_); + } else { + printer->Print( + "::std::string $classname$::GetTypeName() const {\n" + " return \"$type_name$\";\n" + "}\n" + "\n", + "classname", classname_, + "type_name", descriptor_->full_name()); + } + +} + +void MessageGenerator:: +GenerateOffsets(io::Printer* printer) { + printer->Print( + "static const int $classname$_offsets_[$field_count$] = {\n", + "classname", classname_, + "field_count", SimpleItoa(max(1, descriptor_->field_count()))); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + printer->Print( + "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } + + printer->Outdent(); + printer->Print("};\n"); +} + +void MessageGenerator:: +GenerateSharedConstructorCode(io::Printer* printer) { + printer->Print( + "void $classname$::SharedCtor() {\n", + "classname", classname_); + printer->Indent(); + + printer->Print( + "_cached_size_ = 0;\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); + } + + printer->Print( + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + + printer->Outdent(); + printer->Print("}\n\n"); +} + +void MessageGenerator:: +GenerateSharedDestructorCode(io::Printer* printer) { + printer->Print( + "void $classname$::SharedDtor() {\n", + "classname", classname_); + printer->Indent(); + // Write the destructors for each field. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateDestructorCode(printer); + } + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + "if (this != default_instance_) {\n", + // Without. + "if (this != &default_instance()) {\n"); + + // We need to delete all embedded messages. + // TODO(kenton): If we make unset messages point at default instances + // instead of NULL, then it would make sense to move this code into + // MessageFieldGenerator::GenerateDestructorCode(). + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print(" delete $name$_;\n", + "name", FieldName(field)); + } + } + + printer->Outdent(); + printer->Print( + " }\n" + "}\n" + "\n"); +} + +void MessageGenerator:: +GenerateStructors(io::Printer* printer) { + string superclass = SuperClassName(descriptor_); + + // Generate the default constructor. + printer->Print( + "$classname$::$classname$()\n" + " : $superclass$() {\n" + " SharedCtor();\n" + "}\n", + "classname", classname_, + "superclass", superclass); + + printer->Print( + "\n" + "void $classname$::InitAsDefaultInstance() {\n", + "classname", classname_); + + // The default instance needs all of its embedded message pointers + // cross-linked to other default instances. We can't do this initialization + // in the constructor because some other default instances may not have been + // constructed yet at that time. + // TODO(kenton): Maybe all message fields (even for non-default messages) + // should be initialized to point at default instances rather than NULL? + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", + // Without. + " $name$_ = const_cast< $type$*>(\n" + " $type$::internal_default_instance());\n", + // Vars. + "name", FieldName(field), + "type", FieldMessageTypeName(field)); + } + } + printer->Print( + "}\n" + "\n"); + + // Generate the copy constructor. + printer->Print( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$() {\n" + " SharedCtor();\n" + " MergeFrom(from);\n" + "}\n" + "\n", + "classname", classname_, + "superclass", superclass); + + // Generate the shared constructor code. + GenerateSharedConstructorCode(printer); + + // Generate the destructor. + printer->Print( + "$classname$::~$classname$() {\n" + " SharedDtor();\n" + "}\n" + "\n", + "classname", classname_); + + // Generate the shared destructor code. + GenerateSharedDestructorCode(printer); + + // Generate SetCachedSize. + printer->Print( + "void $classname$::SetCachedSize(int size) const {\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + " _cached_size_ = size;\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "}\n", + "classname", classname_); + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n", + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + } + + printer->Print( + "const $classname$& $classname$::default_instance() {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " if (default_instance_ == NULL) $adddescriptorsname$();\n", + // Without. + " $adddescriptorsname$();\n", + // Vars. + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + + printer->Print( + " return *default_instance_;\n" + "}\n" + "\n" + "$classname$* $classname$::default_instance_ = NULL;\n" + "\n" + "$classname$* $classname$::New() const {\n" + " return new $classname$;\n" + "}\n", + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); +} + +void MessageGenerator:: +GenerateClear(io::Printer* printer) { + printer->Print("void $classname$::Clear() {\n", + "classname", classname_); + printer->Indent(); + + int last_index = -1; + + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.Clear();\n"); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated()) { + // We can use the fact that _has_bits_ is a giant bitfield to our + // advantage: We can check up to 32 bits at a time for equality to + // zero, and skip the whole range if so. This can improve the speed + // of Clear() for messages which contain a very large number of + // optional fields of which only a few are used at a time. Here, + // we've chosen to check 8 bits at a time rather than 32. + if (i / 8 != last_index / 8 || last_index < 0) { + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print( + "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); + printer->Indent(); + } + last_index = i; + + // It's faster to just overwrite primitive types, but we should + // only clear strings and messages if they were set. + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; + + if (should_check_bit) { + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + } + + field_generators_.get(field).GenerateClearingCode(printer); + + if (should_check_bit) { + printer->Outdent(); + printer->Print("}\n"); + } + } + } + + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + + // Repeated fields don't use _has_bits_ so we clear them in a separate + // pass. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + field_generators_.get(field).GenerateClearingCode(printer); + } + } + + printer->Print( + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->Clear();\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateSwap(io::Printer* printer) { + // Generate the Swap member function. + printer->Print("void $classname$::Swap($classname$* other) {\n", + "classname", classname_); + printer->Indent(); + printer->Print("if (other != this) {\n"); + printer->Indent(); + + if (HasGeneratedMethods(descriptor_->file())) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + field_generators_.get(field).GenerateSwappingCode(printer); + } + + for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { + printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", + "i", SimpleItoa(i)); + } + + if (HasUnknownFields(descriptor_->file())) { + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } + printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.Swap(&other->_extensions_);\n"); + } + } else { + printer->Print("GetReflection()->Swap(this, other);"); + } + + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateMergeFrom(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized MergeFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + " GOOGLE_CHECK_NE(&from, this);\n", + "classname", classname_); + printer->Indent(); + + // Cast the message to the proper type. If we find that the message is + // *not* of the proper type, we can still call Merge via the reflection + // system, as the GOOGLE_CHECK above ensured that we have the same descriptor + // for each message. + printer->Print( + "const $classname$* source =\n" + " ::google::protobuf::internal::dynamic_cast_if_available(\n" + " &from);\n" + "if (source == NULL) {\n" + " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + " MergeFrom(*source);\n" + "}\n", + "classname", classname_); + + printer->Outdent(); + printer->Print("}\n\n"); + } else { + // Generate CheckTypeAndMergeFrom(). + printer->Print( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::google::protobuf::MessageLite& from) {\n" + " MergeFrom(*::google::protobuf::down_cast(&from));\n" + "}\n" + "\n", + "classname", classname_); + } + + // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. + printer->Print( + "void $classname$::MergeFrom(const $classname$& from) {\n" + " GOOGLE_CHECK_NE(&from, this);\n", + "classname", classname_); + printer->Indent(); + + // Merge Repeated fields. These fields do not require a + // check as we can simply iterate over them. + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + field_generators_.get(field).GenerateMergingCode(printer); + } + } + + // Merge Optional and Required fields (after a _has_bit check). + int last_index = -1; + + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated()) { + // See above in GenerateClear for an explanation of this. + if (i / 8 != last_index / 8 || last_index < 0) { + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print( + "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); + printer->Indent(); + } + + last_index = i; + + printer->Print( + "if (from.has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + + field_generators_.get(field).GenerateMergingCode(printer); + + printer->Outdent(); + printer->Print("}\n"); + } + } + + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); + } + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateCopyFrom(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized CopyFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n", + "classname", classname_); + printer->Indent(); + + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); + + printer->Outdent(); + printer->Print("}\n\n"); + } + + // Generate the class-specific CopyFrom. + printer->Print( + "void $classname$::CopyFrom(const $classname$& from) {\n", + "classname", classname_); + printer->Indent(); + + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " return _extensions_.ParseMessageSet(input, default_instance_,\n" + " mutable_unknown_fields());\n", + // Without. + " return _extensions_.ParseMessageSet(input, &default_instance(),\n" + " mutable_unknown_fields());\n", + // Vars. + "classname", classname_); + + printer->Print( + "}\n"); + return; + } + + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n" + "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n" + " ::google::protobuf::uint32 tag;\n" + " while ((tag = input->ReadTag()) != 0) {\n", + "classname", classname_); + + printer->Indent(); + printer->Indent(); + + if (descriptor_->field_count() > 0) { + // We don't even want to print the switch() if we have no fields because + // MSVC dislikes switch() statements that contain only a default value. + + // Note: If we just switched on the tag rather than the field number, we + // could avoid the need for the if() to check the wire type at the beginning + // of each case. However, this is actually a bit slower in practice as it + // creates a jump table that is 8x larger and sparser, and meanwhile the + // if()s are highly predictable. + printer->Print( + "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); + + printer->Indent(); + + scoped_array ordered_fields( + SortFieldsByNumber(descriptor_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = ordered_fields[i]; + + PrintFieldComment(printer, field); + + printer->Print( + "case $number$: {\n", + "number", SimpleItoa(field->number())); + printer->Indent(); + const FieldGenerator& field_generator = field_generators_.get(field); + + // Emit code to parse the common, expected case. + printer->Print( + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n", + "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]); + + if (i > 0 || (field->is_repeated() && !field->options().packed())) { + printer->Print( + " parse_$name$:\n", + "name", field->name()); + } + + printer->Indent(); + if (field->options().packed()) { + field_generator.GenerateMergeFromCodedStreamWithPacking(printer); + } else { + field_generator.GenerateMergeFromCodedStream(printer); + } + printer->Outdent(); + + // Emit code to parse unexpectedly packed or unpacked values. + if (field->is_packable() && field->options().packed()) { + printer->Print( + "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" + " == ::google::protobuf::internal::WireFormatLite::\n" + " WIRETYPE_$wiretype$) {\n", + "wiretype", + kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]); + printer->Indent(); + field_generator.GenerateMergeFromCodedStream(printer); + printer->Outdent(); + } else if (field->is_packable() && !field->options().packed()) { + printer->Print( + "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" + " == ::google::protobuf::internal::WireFormatLite::\n" + " WIRETYPE_LENGTH_DELIMITED) {\n"); + printer->Indent(); + field_generator.GenerateMergeFromCodedStreamWithPacking(printer); + printer->Outdent(); + } + + printer->Print( + "} else {\n" + " goto handle_uninterpreted;\n" + "}\n"); + + // switch() is slow since it can't be predicted well. Insert some if()s + // here that attempt to predict the next tag. + if (field->is_repeated() && !field->options().packed()) { + // Expect repeats of this field. + printer->Print( + "if (input->ExpectTag($tag$)) goto parse_$name$;\n", + "tag", SimpleItoa(WireFormat::MakeTag(field)), + "name", field->name()); + } + + if (i + 1 < descriptor_->field_count()) { + // Expect the next field in order. + const FieldDescriptor* next_field = ordered_fields[i + 1]; + printer->Print( + "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n", + "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), + "next_name", next_field->name()); + } else { + // Expect EOF. + // TODO(kenton): Expect group end-tag? + printer->Print( + "if (input->ExpectAtEnd()) return true;\n"); + } + + printer->Print( + "break;\n"); + + printer->Outdent(); + printer->Print("}\n\n"); + } + + printer->Print( + "default: {\n" + "handle_uninterpreted:\n"); + printer->Indent(); + } + + // Is this an end-group tag? If so, this must be the end of the message. + printer->Print( + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" + " return true;\n" + "}\n"); + + // Handle extension ranges. + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if ("); + for (int i = 0; i < descriptor_->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range = + descriptor_->extension_range(i); + if (i > 0) printer->Print(" ||\n "); + + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast(0)); + + if (range->end > FieldDescriptor::kMaxNumber) { + printer->Print( + "($start$u <= tag)", + "start", SimpleItoa(start_tag)); + } else { + printer->Print( + "($start$u <= tag && tag < $end$u)", + "start", SimpleItoa(start_tag), + "end", SimpleItoa(end_tag)); + } + } + printer->Print(") {\n"); + if (HasUnknownFields(descriptor_->file())) { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " mutable_unknown_fields()));\n"); + } else { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance()));\n"); + } + printer->Print( + " continue;\n" + "}\n"); + } + + // We really don't recognize this tag. Skip it. + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" + " input, tag, mutable_unknown_fields()));\n"); + } else { + printer->Print( + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); + } + + if (descriptor_->field_count() > 0) { + printer->Print("break;\n"); + printer->Outdent(); + printer->Print("}\n"); // default: + printer->Outdent(); + printer->Print("}\n"); // switch + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // while + " return true;\n" + "#undef DO_\n" + "}\n"); +} + +void MessageGenerator::GenerateSerializeOneField( + io::Printer* printer, const FieldDescriptor* field, bool to_array) { + PrintFieldComment(printer, field); + + if (!field->is_repeated()) { + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + } + + if (to_array) { + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( + printer); + } else { + field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); + } + + if (!field->is_repeated()) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print("\n"); +} + +void MessageGenerator::GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range, + bool to_array) { + map vars; + vars["start"] = SimpleItoa(range->start); + vars["end"] = SimpleItoa(range->end); + printer->Print(vars, + "// Extension range [$start$, $end$)\n"); + if (to_array) { + printer->Print(vars, + "target = _extensions_.SerializeWithCachedSizesToArray(\n" + " $start$, $end$, target);\n\n"); + } else { + printer->Print(vars, + "_extensions_.SerializeWithCachedSizes(\n" + " $start$, $end$, output);\n\n"); + } +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n" + " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); + } + printer->Print( + "}\n"); + return; + } + + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n", + "classname", classname_); + printer->Indent(); + + GenerateSerializeWithCachedSizesBody(printer, false); + + printer->Outdent(); + printer->Print( + "}\n"); +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" + " ::google::protobuf::uint8* target) const {\n" + " target =\n" + " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); + } + printer->Print( + " return target;\n" + "}\n"); + return; + } + + printer->Print( + "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" + " ::google::protobuf::uint8* target) const {\n", + "classname", classname_); + printer->Indent(); + + GenerateSerializeWithCachedSizesBody(printer, true); + + printer->Outdent(); + printer->Print( + " return target;\n" + "}\n"); +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { + scoped_array ordered_fields( + SortFieldsByNumber(descriptor_)); + + vector sorted_extensions; + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); + + // Merge the fields and the extension ranges, both sorted by field number. + int i, j; + for (i = 0, j = 0; + i < descriptor_->field_count() || j < sorted_extensions.size(); + ) { + if (i == descriptor_->field_count()) { + GenerateSerializeOneExtensionRange(printer, + sorted_extensions[j++], + to_array); + } else if (j == sorted_extensions.size()) { + GenerateSerializeOneField(printer, ordered_fields[i++], to_array); + } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { + GenerateSerializeOneField(printer, ordered_fields[i++], to_array); + } else { + GenerateSerializeOneExtensionRange(printer, + sorted_extensions[j++], + to_array); + } + } + + if (HasUnknownFields(descriptor_->file())) { + printer->Print("if (!unknown_fields().empty()) {\n"); + printer->Indent(); + if (to_array) { + printer->Print( + "target = " + "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" + " unknown_fields(), target);\n"); + } else { + printer->Print( + "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" + " unknown_fields(), output);\n"); + } + printer->Outdent(); + + printer->Print( + "}\n"); + } +} + +void MessageGenerator:: +GenerateByteSize(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "int $classname$::ByteSize() const {\n" + " int total_size = _extensions_.MessageSetByteSize();\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); + } + printer->Print( + " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + " _cached_size_ = total_size;\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + " return total_size;\n" + "}\n"); + return; + } + + printer->Print( + "int $classname$::ByteSize() const {\n", + "classname", classname_); + printer->Indent(); + printer->Print( + "int total_size = 0;\n" + "\n"); + + int last_index = -1; + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated()) { + // See above in GenerateClear for an explanation of this. + // TODO(kenton): Share code? Unclear how to do so without + // over-engineering. + if ((i / 8) != (last_index / 8) || + last_index < 0) { + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print( + "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); + printer->Indent(); + } + last_index = i; + + PrintFieldComment(printer, field); + + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + + field_generators_.get(field).GenerateByteSize(printer); + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } + } + + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + + // Repeated fields don't use _has_bits_ so we count them in a separate + // pass. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + PrintFieldComment(printer, field); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print("\n"); + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "total_size += _extensions_.ByteSize();\n" + "\n"); + } + + if (HasUnknownFields(descriptor_->file())) { + printer->Print("if (!unknown_fields().empty()) {\n"); + printer->Indent(); + printer->Print( + "total_size +=\n" + " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" + " unknown_fields());\n"); + printer->Outdent(); + printer->Print("}\n"); + } + + // We update _cached_size_ even though this is a const method. In theory, + // this is not thread-compatible, because concurrent writes have undefined + // results. In practice, since any concurrent writes will be writing the + // exact same value, it works on all common processors. In a future version + // of C++, _cached_size_ should be made into an atomic. + printer->Print( + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + "_cached_size_ = total_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "return total_size;\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateIsInitialized(io::Printer* printer) { + printer->Print( + "bool $classname$::IsInitialized() const {\n", + "classname", classname_); + printer->Indent(); + + // Check that all required fields in this message are set. We can do this + // most efficiently by checking 32 "has bits" at a time. + int has_bits_array_size = (descriptor_->field_count() + 31) / 32; + for (int i = 0; i < has_bits_array_size; i++) { + uint32 mask = 0; + for (int bit = 0; bit < 32; bit++) { + int index = i * 32 + bit; + if (index >= descriptor_->field_count()) break; + const FieldDescriptor* field = descriptor_->field(index); + + if (field->is_required()) { + mask |= 1 << bit; + } + } + + if (mask != 0) { + char buffer[kFastToBufferSize]; + printer->Print( + "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", + "i", SimpleItoa(i), + "mask", FastHex32ToBuffer(mask, buffer)); + } + } + + // Now check that all embedded messages are initialized. + printer->Print("\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field) && + HasRequiredFields(field->message_type())) { + if (field->is_repeated()) { + printer->Print( + "for (int i = 0; i < $name$_size(); i++) {\n" + " if (!this->$name$(i).IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } else { + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$().IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "\n" + "if (!_extensions_.IsInitialized()) return false;"); + } + + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n"); +} + + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h new file mode 100644 index 000000000..a7e43d9c9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message.h @@ -0,0 +1,171 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +class EnumGenerator; // enum.h +class ExtensionGenerator; // extension.h + +class MessageGenerator { + public: + // See generator.cc for the meaning of dllexport_decl. + explicit MessageGenerator(const Descriptor* descriptor, + const Options& options); + ~MessageGenerator(); + + // Header stuff. + + // Generate foward declarations for this class and all its nested types. + void GenerateForwardDeclaration(io::Printer* printer); + + // Generate definitions of all nested enums (must come before class + // definitions because those classes use the enums definitions). + void GenerateEnumDefinitions(io::Printer* printer); + + // Generate specializations of GetEnumDescriptor(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + + // Generate definitions for this class and all its nested types. + void GenerateClassDefinition(io::Printer* printer); + + // Generate definitions of inline methods (placed at the end of the header + // file). + void GenerateInlineMethods(io::Printer* printer); + + // Source file stuff. + + // Generate code which declares all the global descriptor pointers which + // will be initialized by the methods below. + void GenerateDescriptorDeclarations(io::Printer* printer); + + // Generate code that initializes the global variable storing the message's + // descriptor. + void GenerateDescriptorInitializer(io::Printer* printer, int index); + + // Generate code that calls MessageFactory::InternalRegisterGeneratedMessage() + // for all types. + void GenerateTypeRegistrations(io::Printer* printer); + + // Generates code that allocates the message's default instance. + void GenerateDefaultInstanceAllocator(io::Printer* printer); + + // Generates code that initializes the message's default instance. This + // is separate from allocating because all default instances must be + // allocated before any can be initialized. + void GenerateDefaultInstanceInitializer(io::Printer* printer); + + // Generates code that should be run when ShutdownProtobufLibrary() is called, + // to delete all dynamically-allocated objects. + void GenerateShutdownCode(io::Printer* printer); + + // Generate all non-inline methods for this class. + void GenerateClassMethods(io::Printer* printer); + + private: + // Generate declarations and definitions of accessors for fields. + void GenerateFieldAccessorDeclarations(io::Printer* printer); + void GenerateFieldAccessorDefinitions(io::Printer* printer); + + // Generate the field offsets array. + void GenerateOffsets(io::Printer* printer); + + // Generate constructors and destructor. + void GenerateStructors(io::Printer* printer); + + // The compiler typically generates multiple copies of each constructor and + // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx + // Placing common code in a separate method reduces the generated code size. + // + // Generate the shared constructor code. + void GenerateSharedConstructorCode(io::Printer* printer); + // Generate the shared destructor code. + void GenerateSharedDestructorCode(io::Printer* printer); + + // Generate standard Message methods. + void GenerateClear(io::Printer* printer); + void GenerateMergeFromCodedStream(io::Printer* printer); + void GenerateSerializeWithCachedSizes(io::Printer* printer); + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); + void GenerateSerializeWithCachedSizesBody(io::Printer* printer, + bool to_array); + void GenerateByteSize(io::Printer* printer); + void GenerateMergeFrom(io::Printer* printer); + void GenerateCopyFrom(io::Printer* printer); + void GenerateSwap(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer); + + // Helpers for GenerateSerializeWithCachedSizes(). + void GenerateSerializeOneField(io::Printer* printer, + const FieldDescriptor* field, + bool unbounded); + void GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range, + bool unbounded); + + + const Descriptor* descriptor_; + string classname_; + Options options_; + FieldGeneratorMap field_generators_; + scoped_array > nested_generators_; + scoped_array > enum_generators_; + scoped_array > extension_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc new file mode 100644 index 000000000..447f975f8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -0,0 +1,298 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 compiler { +namespace cpp { + +namespace { + +void SetMessageVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); + (*variables)["type"] = FieldMessageTypeName(descriptor); + (*variables)["stream_writer"] = (*variables)["declared_type"] + + (HasFastArraySerialization(descriptor->message_type()->file()) ? + "MaybeToArray" : + ""); +} + +} // namespace + +// =================================================================== + +MessageFieldGenerator:: +MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetMessageVariables(descriptor, &variables_, options); +} + +MessageFieldGenerator::~MessageFieldGenerator() {} + +void MessageFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, "$type$* $name$_;\n"); +} + +void MessageFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $name$() const$deprecation$;\n" + "inline $type$* mutable_$name$()$deprecation$;\n" + "inline $type$* release_$name$()$deprecation$;\n" + "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); +} + +void MessageFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $classname$::$name$() const {\n"); + + PrintHandlingOptionalStaticInitializers( + variables_, descriptor_->file(), printer, + // With static initializers. + " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", + // Without. + " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); + + printer->Print(variables_, + "}\n" + "inline $type$* $classname$::mutable_$name$() {\n" + " set_has_$name$();\n" + " if ($name$_ == NULL) $name$_ = new $type$;\n" + " return $name$_;\n" + "}\n" + "inline $type$* $classname$::release_$name$() {\n" + " clear_has_$name$();\n" + " $type$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n" + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + " delete $name$_;\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " } else {\n" + " clear_has_$name$();\n" + " }\n" + "}\n"); +} + +void MessageFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($name$_ != NULL) $name$_->$type$::Clear();\n"); +} + +void MessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); +} + +void MessageFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); +} + +void MessageFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = NULL;\n"); +} + +void MessageFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + " input, mutable_$name$()));\n"); + } else { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, mutable_$name$()));\n"); + } +} + +void MessageFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" + " $number$, this->$name$(), output);\n"); +} + +void MessageFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + printer->Print(variables_, + "target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(), target);\n"); +} + +void MessageFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" + " this->$name$());\n"); +} + +// =================================================================== + +RepeatedMessageFieldGenerator:: +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetMessageVariables(descriptor, &variables_, options); +} + +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} + +void RepeatedMessageFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $name$(int index) const$deprecation$;\n" + "inline $type$* mutable_$name$(int index)$deprecation$;\n" + "inline $type$* add_$name$()$deprecation$;\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + " $name$() const$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + " mutable_$name$()$deprecation$;\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $classname$::$name$(int index) const {\n" + " return $name$_.$cppget$(index);\n" + "}\n" + "inline $type$* $classname$::mutable_$name$(int index) {\n" + " return $name$_.Mutable(index);\n" + "}\n" + "inline $type$* $classname$::add_$name$() {\n" + " return $name$_.Add();\n" + "}\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + "$classname$::$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + " return &$name$_;\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Clear();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Not needed for repeated fields. +} + +void RepeatedMessageFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + " input, add_$name$()));\n"); + } else { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, add_$name$()));\n"); + } +} + +void RepeatedMessageFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" + " $number$, this->$name$(i), output);\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(i), target);\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "total_size += $tag_size$ * this->$name$_size();\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " total_size +=\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" + " this->$name$(i));\n" + "}\n"); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h new file mode 100644 index 000000000..a5ed68a5c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -0,0 +1,104 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +class MessageFieldGenerator : public FieldGenerator { + public: + explicit MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~MessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); +}; + +class RepeatedMessageFieldGenerator : public FieldGenerator { + public: + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~RepeatedMessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h new file mode 100644 index 000000000..787706629 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_options.h @@ -0,0 +1,58 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: rennie@google.com (Jeffrey Rennie) + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ + +#include + +#include +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Generator options: +struct Options { + Options() : safe_boundary_check(false) { + } + string dllexport_decl; + bool safe_boundary_check; +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc new file mode 100644 index 000000000..5c4aa4fbc --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// TODO(kenton): Share code with the versions of this test in other languages? +// It seemed like parameterizing it would add more complexity than it is +// worth. + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { + +class TestGenerator : public CodeGenerator { + public: + TestGenerator() {} + ~TestGenerator() {} + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + TryInsert("test.pb.h", "includes", context); + TryInsert("test.pb.h", "namespace_scope", context); + TryInsert("test.pb.h", "global_scope", context); + TryInsert("test.pb.h", "class_scope:foo.Bar", context); + TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context); + + TryInsert("test.pb.cc", "includes", context); + TryInsert("test.pb.cc", "namespace_scope", context); + TryInsert("test.pb.cc", "global_scope", context); + return true; + } + + void TryInsert(const string& filename, const string& insertion_point, + GeneratorContext* context) const { + scoped_ptr output( + context->OpenForInsert(filename, insertion_point)); + io::Printer printer(output.get(), '$'); + printer.Print("// inserted $name$\n", "name", insertion_point); + } +}; + +// This test verifies that all the expected insertion points exist. It does +// not verify that they are correctly-placed; that would require actually +// compiling the output which is a bit more than I care to do for this test. +TEST(CppPluginTest, PluginTest) { + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + TestTempDir() + "/test.proto"); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + CppGenerator cpp_generator; + TestGenerator test_generator; + cli.RegisterGenerator("--cpp_out", &cpp_generator, ""); + cli.RegisterGenerator("--test_out", &test_generator, ""); + + string proto_path = "-I" + TestTempDir(); + string cpp_out = "--cpp_out=" + TestTempDir(); + string test_out = "--test_out=" + TestTempDir(); + + const char* argv[] = { + "protoc", + proto_path.c_str(), + cpp_out.c_str(), + test_out.c_str(), + "test.proto" + }; + + EXPECT_EQ(0, cli.Run(5, argv)); +} + +} // namespace +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc new file mode 100644 index 000000000..1c35fefa1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -0,0 +1,387 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +using internal::WireFormatLite; + +namespace { + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); + (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + int fixed_size = FixedSize(descriptor->type()); + if (fixed_size != -1) { + (*variables)["fixed_size"] = SimpleItoa(fixed_size); + } + (*variables)["wire_format_field_type"] = + "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( + static_cast(descriptor->type())); +} + +} // namespace + +// =================================================================== + +PrimitiveFieldGenerator:: +PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, &variables_, options); +} + +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} + +void PrimitiveFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, "$type$ $name$_;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " set_has_$name$();\n" + " $name$_ = value;\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "set_$name$(from.$name$());\n"); +} + +void PrimitiveFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); +} + +void PrimitiveFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " $type$, $wire_format_field_type$>(\n" + " input, &$name$_)));\n" + "set_has_$name$();\n"); +} + +void PrimitiveFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" + "$number$, this->$name$(), output);\n"); +} + +void PrimitiveFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + printer->Print(variables_, + "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" + "$number$, this->$name$(), target);\n"); +} + +void PrimitiveFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + int fixed_size = FixedSize(descriptor_->type()); + if (fixed_size == -1) { + printer->Print(variables_, + "total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); + } else { + printer->Print(variables_, + "total_size += $tag_size$ + $fixed_size$;\n"); + } +} + +// =================================================================== + +RepeatedPrimitiveFieldGenerator:: +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, &variables_, options); + + if (descriptor->options().packed()) { + variables_["packed_reader"] = "ReadPackedPrimitive"; + variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline"; + } else { + variables_["packed_reader"] = "ReadPackedPrimitiveNoInline"; + variables_["repeated_reader"] = "ReadRepeatedPrimitive"; + } +} + +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} + +void RepeatedPrimitiveFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { + printer->Print(variables_, + "mutable int _$name$_cached_byte_size_;\n"); + } +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + " $name$() const$deprecation$;\n" + "inline ::google::protobuf::RepeatedField< $type$ >*\n" + " mutable_$name$()$deprecation$;\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$(int index) const {\n" + " return $name$_.Get(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n" + " $name$_.Set(index, value);\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n" + " $name$_.Add(value);\n" + "}\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + "$classname$::$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline ::google::protobuf::RepeatedField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + " return &$name$_;\n" + "}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Clear();\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Not needed for repeated fields. +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n" + " $type$, $wire_format_field_type$>(\n" + " $tag_size$, $tag$, input, this->mutable_$name$())));\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n" + " $type$, $wire_format_field_type$>(\n" + " input, this->mutable_$name$())));\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + if (descriptor_->options().packed()) { + // Write the tag and the size. + printer->Print(variables_, + "if (this->$name$_size() > 0) {\n" + " ::google::protobuf::internal::WireFormatLite::WriteTag(" + "$number$, " + "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " + "output);\n" + " output->WriteVarint32(_$name$_cached_byte_size_);\n" + "}\n"); + } + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" + " this->$name$(i), output);\n"); + } else { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n"); + } + printer->Print("}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + if (descriptor_->options().packed()) { + // Write the tag and the size. + printer->Print(variables_, + "if (this->$name$_size() > 0) {\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" + " _$name$_cached_byte_size_, target);\n" + "}\n"); + } + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoTagToArray(this->$name$(i), target);\n"); + } else { + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"); + } + printer->Print("}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int data_size = 0;\n"); + printer->Indent(); + int fixed_size = FixedSize(descriptor_->type()); + if (fixed_size == -1) { + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " data_size += ::google::protobuf::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "data_size = $fixed_size$ * this->$name$_size();\n"); + } + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" + "}\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + "_$name$_cached_byte_size_ = data_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "total_size += data_size;\n"); + } else { + printer->Print(variables_, + "total_size += $tag_size$ * this->$name$_size() + data_size;\n"); + } + printer->Outdent(); + printer->Print("}\n"); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h new file mode 100644 index 000000000..48249c407 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -0,0 +1,105 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +class PrimitiveFieldGenerator : public FieldGenerator { + public: + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~PrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); +}; + +class RepeatedPrimitiveFieldGenerator : public FieldGenerator { + public: + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~RepeatedPrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc new file mode 100644 index 000000000..d20018ea2 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -0,0 +1,334 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 compiler { +namespace cpp { + +ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + vars_["classname"] = descriptor_->name(); + vars_["full_name"] = descriptor_->full_name(); + if (options.dllexport_decl.empty()) { + vars_["dllexport"] = ""; + } else { + vars_["dllexport"] = options.dllexport_decl + " "; + } +} + +ServiceGenerator::~ServiceGenerator() {} + +void ServiceGenerator::GenerateDeclarations(io::Printer* printer) { + // Forward-declare the stub type. + printer->Print(vars_, + "class $classname$_Stub;\n" + "\n"); + + GenerateInterface(printer); + GenerateStubDefinition(printer); +} + +void ServiceGenerator::GenerateInterface(io::Printer* printer) { + printer->Print(vars_, + "class $dllexport$$classname$ : public ::google::protobuf::Service {\n" + " protected:\n" + " // This class should be treated as an abstract interface.\n" + " inline $classname$() {};\n" + " public:\n" + " virtual ~$classname$();\n"); + printer->Indent(); + + printer->Print(vars_, + "\n" + "typedef $classname$_Stub Stub;\n" + "\n" + "static const ::google::protobuf::ServiceDescriptor* descriptor();\n" + "\n"); + + GenerateMethodSignatures(VIRTUAL, printer); + + printer->Print( + "\n" + "// implements Service ----------------------------------------------\n" + "\n" + "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n" + "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" + " ::google::protobuf::RpcController* controller,\n" + " const ::google::protobuf::Message* request,\n" + " ::google::protobuf::Message* response,\n" + " ::google::protobuf::Closure* done);\n" + "const ::google::protobuf::Message& GetRequestPrototype(\n" + " const ::google::protobuf::MethodDescriptor* method) const;\n" + "const ::google::protobuf::Message& GetResponsePrototype(\n" + " const ::google::protobuf::MethodDescriptor* method) const;\n"); + + printer->Outdent(); + printer->Print(vars_, + "\n" + " private:\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" + "};\n" + "\n"); +} + +void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) { + printer->Print(vars_, + "class $dllexport$$classname$_Stub : public $classname$ {\n" + " public:\n"); + + printer->Indent(); + + printer->Print(vars_, + "$classname$_Stub(::google::protobuf::RpcChannel* channel);\n" + "$classname$_Stub(::google::protobuf::RpcChannel* channel,\n" + " ::google::protobuf::Service::ChannelOwnership ownership);\n" + "~$classname$_Stub();\n" + "\n" + "inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n" + "\n" + "// implements $classname$ ------------------------------------------\n" + "\n"); + + GenerateMethodSignatures(NON_VIRTUAL, printer); + + printer->Outdent(); + printer->Print(vars_, + " private:\n" + " ::google::protobuf::RpcChannel* channel_;\n" + " bool owns_channel_;\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" + "};\n" + "\n"); +} + +void ServiceGenerator::GenerateMethodSignatures( + VirtualOrNon virtual_or_non, io::Printer* printer) { + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map sub_vars; + sub_vars["name"] = method->name(); + sub_vars["input_type"] = ClassName(method->input_type(), true); + sub_vars["output_type"] = ClassName(method->output_type(), true); + sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : ""; + + printer->Print(sub_vars, + "$virtual$void $name$(::google::protobuf::RpcController* controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done);\n"); + } +} + +// =================================================================== + +void ServiceGenerator::GenerateDescriptorInitializer( + io::Printer* printer, int index) { + map vars; + vars["classname"] = descriptor_->name(); + vars["index"] = SimpleItoa(index); + + printer->Print(vars, + "$classname$_descriptor_ = file->service($index$);\n"); +} + +// =================================================================== + +void ServiceGenerator::GenerateImplementation(io::Printer* printer) { + printer->Print(vars_, + "$classname$::~$classname$() {}\n" + "\n" + "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n" + "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n"); + + // Generate methods of the interface. + GenerateNotImplementedMethods(printer); + GenerateCallMethod(printer); + GenerateGetPrototype(REQUEST, printer); + GenerateGetPrototype(RESPONSE, printer); + + // Generate stub implementation. + printer->Print(vars_, + "$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n" + " : channel_(channel), owns_channel_(false) {}\n" + "$classname$_Stub::$classname$_Stub(\n" + " ::google::protobuf::RpcChannel* channel,\n" + " ::google::protobuf::Service::ChannelOwnership ownership)\n" + " : channel_(channel),\n" + " owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n" + "$classname$_Stub::~$classname$_Stub() {\n" + " if (owns_channel_) delete channel_;\n" + "}\n" + "\n"); + + GenerateStubMethods(printer); +} + +void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map sub_vars; + sub_vars["classname"] = descriptor_->name(); + sub_vars["name"] = method->name(); + sub_vars["index"] = SimpleItoa(i); + sub_vars["input_type"] = ClassName(method->input_type(), true); + sub_vars["output_type"] = ClassName(method->output_type(), true); + + printer->Print(sub_vars, + "void $classname$::$name$(::google::protobuf::RpcController* controller,\n" + " const $input_type$*,\n" + " $output_type$*,\n" + " ::google::protobuf::Closure* done) {\n" + " controller->SetFailed(\"Method $name$() not implemented.\");\n" + " done->Run();\n" + "}\n" + "\n"); + } +} + +void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { + printer->Print(vars_, + "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" + " ::google::protobuf::RpcController* controller,\n" + " const ::google::protobuf::Message* request,\n" + " ::google::protobuf::Message* response,\n" + " ::google::protobuf::Closure* done) {\n" + " GOOGLE_DCHECK_EQ(method->service(), $classname$_descriptor_);\n" + " switch(method->index()) {\n"); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map sub_vars; + sub_vars["name"] = method->name(); + sub_vars["index"] = SimpleItoa(i); + sub_vars["input_type"] = ClassName(method->input_type(), true); + sub_vars["output_type"] = ClassName(method->output_type(), true); + + // Note: down_cast does not work here because it only works on pointers, + // not references. + printer->Print(sub_vars, + " case $index$:\n" + " $name$(controller,\n" + " ::google::protobuf::down_cast(request),\n" + " ::google::protobuf::down_cast< $output_type$*>(response),\n" + " done);\n" + " break;\n"); + } + + printer->Print(vars_, + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " break;\n" + " }\n" + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, + io::Printer* printer) { + if (which == REQUEST) { + printer->Print(vars_, + "const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n"); + } else { + printer->Print(vars_, + "const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n"); + } + + printer->Print(vars_, + " const ::google::protobuf::MethodDescriptor* method) const {\n" + " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" + " switch(method->index()) {\n"); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + const Descriptor* type = + (which == REQUEST) ? method->input_type() : method->output_type(); + + map sub_vars; + sub_vars["index"] = SimpleItoa(i); + sub_vars["type"] = ClassName(type, true); + + printer->Print(sub_vars, + " case $index$:\n" + " return $type$::default_instance();\n"); + } + + printer->Print(vars_, + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n" + " }\n" + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateStubMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map sub_vars; + sub_vars["classname"] = descriptor_->name(); + sub_vars["name"] = method->name(); + sub_vars["index"] = SimpleItoa(i); + sub_vars["input_type"] = ClassName(method->input_type(), true); + sub_vars["output_type"] = ClassName(method->output_type(), true); + + printer->Print(sub_vars, + "void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done) {\n" + " channel_->CallMethod(descriptor()->method($index$),\n" + " controller, request, response, done);\n" + "}\n"); + } +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h new file mode 100644 index 000000000..820f9f5f7 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_service.h @@ -0,0 +1,119 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_SERVICE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace cpp { + +class ServiceGenerator { + public: + // See generator.cc for the meaning of dllexport_decl. + explicit ServiceGenerator(const ServiceDescriptor* descriptor, + const Options& options); + ~ServiceGenerator(); + + // Header stuff. + + // Generate the class definitions for the service's interface and the + // stub implementation. + void GenerateDeclarations(io::Printer* printer); + + // Source file stuff. + + // Generate code that initializes the global variable storing the service's + // descriptor. + void GenerateDescriptorInitializer(io::Printer* printer, int index); + + // Generate implementations of everything declared by GenerateDeclarations(). + void GenerateImplementation(io::Printer* printer); + + private: + enum RequestOrResponse { REQUEST, RESPONSE }; + enum VirtualOrNon { VIRTUAL, NON_VIRTUAL }; + + // Header stuff. + + // Generate the service abstract interface. + void GenerateInterface(io::Printer* printer); + + // Generate the stub class definition. + void GenerateStubDefinition(io::Printer* printer); + + // Prints signatures for all methods in the + void GenerateMethodSignatures(VirtualOrNon virtual_or_non, + io::Printer* printer); + + // Source file stuff. + + // Generate the default implementations of the service methods, which + // produce a "not implemented" error. + void GenerateNotImplementedMethods(io::Printer* printer); + + // Generate the CallMethod() method of the service. + void GenerateCallMethod(io::Printer* printer); + + // Generate the Get{Request,Response}Prototype() methods. + void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); + + // Generate the stub's implementations of the service methods. + void GenerateStubMethods(io::Printer* printer); + + const ServiceDescriptor* descriptor_; + map vars_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc new file mode 100644 index 000000000..9c0911ac9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -0,0 +1,491 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +namespace { + +void SetStringVariables(const FieldDescriptor* descriptor, + map* variables, + const Options& options) { + SetCommonFieldVariables(descriptor, variables, options); + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_length"] = + SimpleItoa(descriptor->default_value_string().length()); + (*variables)["default_variable"] = descriptor->default_value_string().empty() + ? "&::google::protobuf::internal::kEmptyString" + : "_default_" + FieldName(descriptor) + "_"; + (*variables)["pointer_type"] = + descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; +} + +} // namespace + +// =================================================================== + +StringFieldGenerator:: +StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetStringVariables(descriptor, &variables_, options); +} + +StringFieldGenerator::~StringFieldGenerator() {} + +void StringFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, "::std::string* $name$_;\n"); + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, "static ::std::string* $default_variable$;\n"); + } +} + +void StringFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + // If we're using StringFieldGenerator for a field with a ctype, it's + // because that ctype isn't actually implemented. In particular, this is + // true of ctype=CORD and ctype=STRING_PIECE in the open source release. + // We aren't releasing Cord because it has too many Google-specific + // dependencies and we aren't releasing StringPiece because it's hardly + // useful outside of Google and because it would get confusing to have + // multiple instances of the StringPiece class in different libraries (PCRE + // already includes it for their C++ bindings, which came from Google). + // + // In any case, we make all the accessors private while still actually + // using a string to represent the field internally. This way, we can + // guarantee that if we do ever implement the ctype, it won't break any + // existing users who might be -- for whatever reason -- already using .proto + // files that applied the ctype. The field can still be accessed via the + // reflection interface since the reflection interface is independent of + // the string's underlying representation. + if (descriptor_->options().ctype() != FieldOptions::STRING) { + printer->Outdent(); + printer->Print( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + printer->Indent(); + } + + printer->Print(variables_, + "inline const ::std::string& $name$() const$deprecation$;\n" + "inline void set_$name$(const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(const char* value)$deprecation$;\n" + "inline void set_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* mutable_$name$()$deprecation$;\n" + "inline ::std::string* release_$name$()$deprecation$;\n" + "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); + + + if (descriptor_->options().ctype() != FieldOptions::STRING) { + printer->Outdent(); + printer->Print(" public:\n"); + printer->Indent(); + } +} + +void StringFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$() const {\n" + " return *$name$_;\n" + "}\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" + " $name$_ = new ::std::string;\n" + " }\n" + " $name$_->assign(value);\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" + " $name$_ = new ::std::string;\n" + " }\n" + " $name$_->assign(value);\n" + "}\n" + "inline " + "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" + " $name$_ = new ::std::string;\n" + " }\n" + " $name$_->assign(reinterpret_cast(value), size);\n" + "}\n" + "inline ::std::string* $classname$::mutable_$name$() {\n" + " set_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n"); + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " $name$_ = new ::std::string;\n"); + } else { + printer->Print(variables_, + " $name$_ = new ::std::string(*$default_variable$);\n"); + } + printer->Print(variables_, + " }\n" + " return $name$_;\n" + "}\n" + "inline ::std::string* $classname$::release_$name$() {\n" + " clear_has_$name$();\n" + " if ($name$_ == $default_variable$) {\n" + " return NULL;\n" + " } else {\n" + " ::std::string* temp = $name$_;\n" + " $name$_ = const_cast< ::std::string*>($default_variable$);\n" + " return temp;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + " if ($name$_ != $default_variable$) {\n" + " delete $name$_;\n" + " }\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $name$_ = $name$;\n" + " } else {\n" + " clear_has_$name$();\n" + " $name$_ = const_cast< ::std::string*>($default_variable$);\n" + " }\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + // Initialized in GenerateDefaultInstanceAllocator. + printer->Print(variables_, + "::std::string* $classname$::$default_variable$ = NULL;\n"); + } +} + +void StringFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "if ($name$_ != $default_variable$) {\n" + " $name$_->clear();\n" + "}\n"); + } else { + printer->Print(variables_, + "if ($name$_ != $default_variable$) {\n" + " $name$_->assign(*$default_variable$);\n" + "}\n"); + } +} + +void StringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "set_$name$(from.$name$());\n"); +} + +void StringFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "std::swap($name$_, other->$name$_);\n"); +} + +void StringFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = const_cast< ::std::string*>($default_variable$);\n"); +} + +void StringFieldGenerator:: +GenerateDestructorCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($name$_ != $default_variable$) {\n" + " delete $name$_;\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateDefaultInstanceAllocator(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "$classname$::$default_variable$ =\n" + " new ::std::string($default$, $default_length$);\n"); + } +} + +void StringFieldGenerator:: +GenerateShutdownCode(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + "delete $classname$::$default_variable$;\n"); + } +} + +void StringFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } +} + +void StringFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(), output);\n"); +} + +void StringFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + "target =\n" + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n" + " $number$, this->$name$(), target);\n"); +} + +void StringFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); +} + +// =================================================================== + +RepeatedStringFieldGenerator:: +RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor) { + SetStringVariables(descriptor, &variables_, options); +} + +RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} + +void RepeatedStringFieldGenerator:: +GeneratePrivateMembers(io::Printer* printer) const { + printer->Print(variables_, + "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateAccessorDeclarations(io::Printer* printer) const { + // See comment above about unknown ctypes. + if (descriptor_->options().ctype() != FieldOptions::STRING) { + printer->Outdent(); + printer->Print( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + printer->Indent(); + } + + printer->Print(variables_, + "inline const ::std::string& $name$(int index) const$deprecation$;\n" + "inline ::std::string* mutable_$name$(int index)$deprecation$;\n" + "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(int index, const char* value)$deprecation$;\n" + "inline " + "void set_$name$(int index, const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* add_$name$()$deprecation$;\n" + "inline void add_$name$(const ::std::string& value)$deprecation$;\n" + "inline void add_$name$(const char* value)$deprecation$;\n" + "inline void add_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n"); + + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" + "$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + "$deprecation$;\n"); + + if (descriptor_->options().ctype() != FieldOptions::STRING) { + printer->Outdent(); + printer->Print(" public:\n"); + printer->Indent(); + } +} + +void RepeatedStringFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$(int index) const {\n" + " return $name$_.$cppget$(index);\n" + "}\n" + "inline ::std::string* $classname$::mutable_$name$(int index) {\n" + " return $name$_.Mutable(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" + " $name$_.Mutable(index)->assign(value);\n" + "}\n" + "inline void $classname$::set_$name$(int index, const char* value) {\n" + " $name$_.Mutable(index)->assign(value);\n" + "}\n" + "inline void " + "$classname$::set_$name$" + "(int index, const $pointer_type$* value, size_t size) {\n" + " $name$_.Mutable(index)->assign(\n" + " reinterpret_cast(value), size);\n" + "}\n" + "inline ::std::string* $classname$::add_$name$() {\n" + " return $name$_.Add();\n" + "}\n" + "inline void $classname$::add_$name$(const ::std::string& value) {\n" + " $name$_.Add()->assign(value);\n" + "}\n" + "inline void $classname$::add_$name$(const char* value) {\n" + " $name$_.Add()->assign(value);\n" + "}\n" + "inline void " + "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" + " $name$_.Add()->assign(reinterpret_cast(value), size);\n" + "}\n"); + printer->Print(variables_, + "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" + "$classname$::$name$() const {\n" + " return $name$_;\n" + "}\n" + "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" + "$classname$::mutable_$name$() {\n" + " return &$name$_;\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Clear();\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Not needed for repeated fields. +} + +void RepeatedStringFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->add_$name$()));\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(this->$name$_size() - 1).data(),\n" + " this->$name$(this->$name$_size() - 1).length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } +} + +void RepeatedStringFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateByteSize(io::Printer* printer) const { + printer->Print(variables_, + "total_size += $tag_size$ * this->$name$_size();\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n" + " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$(i));\n" + "}\n"); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h new file mode 100644 index 000000000..3264134aa --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_CPP_STRING_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +class StringFieldGenerator : public FieldGenerator { + public: + explicit StringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~StringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateDestructorCode(io::Printer* printer) const; + void GenerateDefaultInstanceAllocator(io::Printer* printer) const; + void GenerateShutdownCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); +}; + +class RepeatedStringFieldGenerator : public FieldGenerator { + public: + explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~RepeatedStringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + void GenerateSerializeWithCachedSizes(io::Printer* printer) const; + void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; + void GenerateByteSize(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); +}; + +} // namespace cpp +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto new file mode 100644 index 000000000..e14a818c9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -0,0 +1,123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 tests that various identifiers work as field and type names even +// though the same identifiers are used internally by the C++ code generator. + + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +package protobuf_unittest; + +// Test that fields can have names like "input" and "i" which are also used +// internally by the code generator for local variables. +message TestConflictingSymbolNames { + message BuildDescriptors {} + message TypeTraits {} + + optional int32 input = 1; + optional int32 output = 2; + optional string length = 3; + repeated int32 i = 4; + repeated string new_element = 5 [ctype=STRING_PIECE]; + optional int32 total_size = 6; + optional int32 tag = 7; + + enum TestEnum { FOO = 1; } + message Data1 { repeated int32 data = 1; } + message Data2 { repeated TestEnum data = 1; } + message Data3 { repeated string data = 1; } + message Data4 { repeated Data4 data = 1; } + message Data5 { repeated string data = 1 [ctype=STRING_PIECE]; } + message Data6 { repeated string data = 1 [ctype=CORD]; } + + optional int32 source = 8; + optional int32 value = 9; + optional int32 file = 10; + optional int32 from = 11; + optional int32 handle_uninterpreted = 12; + repeated int32 index = 13; + optional int32 controller = 14; + optional int32 already_here = 15; + + optional uint32 uint32 = 16; + optional uint64 uint64 = 17; + optional string string = 18; + optional int32 memset = 19; + optional int32 int32 = 20; + optional int64 int64 = 21; + + optional uint32 cached_size = 22; + optional uint32 extensions = 23; + optional uint32 bit = 24; + optional uint32 bits = 25; + optional uint32 offsets = 26; + optional uint32 reflection = 27; + + message Cord {} + optional string some_cord = 28 [ctype=CORD]; + + message StringPiece {} + optional string some_string_piece = 29 [ctype=STRING_PIECE]; + + // Some keywords. + optional uint32 int = 30; + optional uint32 friend = 31; + + // The generator used to #define a macro called "DO" inside the .cc file. + message DO {} + optional DO do = 32; + + // Some template parameter names for extensions. + optional int32 field_type = 33; + optional bool is_packed = 34; + + extensions 1000 to max; +} + +message TestConflictingSymbolNamesExtension { + extend TestConflictingSymbolNames { + repeated int32 repeated_int32_ext = 20423638 [packed=true]; + } +} + +message DummyMessage {} + +service TestConflictingMethodNames { + rpc Closure(DummyMessage) returns (DummyMessage); +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc new file mode 100644 index 000000000..1eae29b53 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -0,0 +1,1354 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// To test the code generator, we actually use it to generate code for +// google/protobuf/unittest.proto, then test that. This means that we +// are actually testing the parser and other parts of the system at the same +// time, and that problems in the generator may show up as compile-time errors +// rather than unittest failures, which may be surprising. However, testing +// the output of the C++ generator directly would be very hard. We can't very +// well just check it against golden files since those files would have to be +// updated for any small change; such a test would be very brittle and probably +// not very helpful. What we really want to test is that the code compiles +// correctly and produces the interfaces we expect, which is why this test +// is written this way. + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Can't use an anonymous namespace here due to brokenness of Tru64 compiler. +namespace cpp_unittest { + +namespace protobuf_unittest = ::protobuf_unittest; + + +class MockErrorCollector : public MultiFileErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, int line, int column, + const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", + filename, line, column, message); + } +}; + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +// Test that generated code has proper descriptors: +// Parse a descriptor directly (using google::protobuf::compiler::Importer) and +// compare it to the one that was produced by generated code. +TEST(GeneratedDescriptorTest, IdenticalDescriptors) { + const FileDescriptor* generated_descriptor = + unittest::TestAllTypes::descriptor()->file(); + + // Set up the Importer. + MockErrorCollector error_collector; + DiskSourceTree source_tree; + source_tree.MapPath("", TestSourceDir()); + Importer importer(&source_tree, &error_collector); + + // Import (parse) unittest.proto. + const FileDescriptor* parsed_descriptor = + importer.Import("google/protobuf/unittest.proto"); + EXPECT_EQ("", error_collector.text_); + ASSERT_TRUE(parsed_descriptor != NULL); + + // Test that descriptors are generated correctly by converting them to + // FileDescriptorProtos and comparing. + FileDescriptorProto generated_decsriptor_proto, parsed_descriptor_proto; + generated_descriptor->CopyTo(&generated_decsriptor_proto); + parsed_descriptor->CopyTo(&parsed_descriptor_proto); + + EXPECT_EQ(parsed_descriptor_proto.DebugString(), + generated_decsriptor_proto.DebugString()); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +TEST(GeneratedMessageTest, Defaults) { + // Check that all default values are set correctly in the initial message. + unittest::TestAllTypes message; + + TestUtil::ExpectClear(message); + + // Messages should return pointers to default instances until first use. + // (This is not checked by ExpectClear() since it is not actually true after + // the fields have been set and then cleared.) + EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(), + &message.optionalgroup()); + EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + EXPECT_EQ(&unittest::ForeignMessage::default_instance(), + &message.optional_foreign_message()); + EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), + &message.optional_import_message()); +} + +TEST(GeneratedMessageTest, FloatingPointDefaults) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ(0.0f, extreme_default.zero_float()); + EXPECT_EQ(1.0f, extreme_default.one_float()); + EXPECT_EQ(1.5f, extreme_default.small_float()); + EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); + EXPECT_EQ(-1.5f, extreme_default.negative_float()); + EXPECT_EQ(2.0e8f, extreme_default.large_float()); + EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); + EXPECT_EQ(numeric_limits::infinity(), + extreme_default.inf_double()); + EXPECT_EQ(-numeric_limits::infinity(), + extreme_default.neg_inf_double()); + EXPECT_TRUE(extreme_default.nan_double() != extreme_default.nan_double()); + EXPECT_EQ(numeric_limits::infinity(), + extreme_default.inf_float()); + EXPECT_EQ(-numeric_limits::infinity(), + extreme_default.neg_inf_float()); + EXPECT_TRUE(extreme_default.nan_float() != extreme_default.nan_float()); +} + +TEST(GeneratedMessageTest, Trigraph) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ("? ? ?? ?? ??? ?\?/ ?\?-", extreme_default.cpp_trigraph()); +} + +TEST(GeneratedMessageTest, ExtremeSmallIntegerDefault) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + EXPECT_EQ(-0x80000000, kint32min); + EXPECT_EQ(GOOGLE_LONGLONG(-0x8000000000000000), kint64min); + EXPECT_EQ(kint32min, extreme_default.really_small_int32()); + EXPECT_EQ(kint64min, extreme_default.really_small_int64()); +} + +TEST(GeneratedMessageTest, Accessors) { + // Set every field to a unique value then go back and check all those + // values. + unittest::TestAllTypes message; + + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); + + TestUtil::ModifyRepeatedFields(&message); + TestUtil::ExpectRepeatedFieldsModified(message); +} + +TEST(GeneratedMessageTest, MutableStringDefault) { + // mutable_foo() for a string should return a string initialized to its + // default value. + unittest::TestAllTypes message; + + EXPECT_EQ("hello", *message.mutable_default_string()); + + // Note that the first time we call mutable_foo(), we get a newly-allocated + // string, but if we clear it and call it again, we get the same object again. + // We should verify that it has its default value in both cases. + message.set_default_string("blah"); + message.Clear(); + + EXPECT_EQ("hello", *message.mutable_default_string()); +} + +TEST(GeneratedMessageTest, StringDefaults) { + unittest::TestExtremeDefaultValues message; + // Check if '\000' can be used in default string value. + EXPECT_EQ(string("hel\000lo", 6), message.string_with_zero()); + EXPECT_EQ(string("wor\000ld", 6), message.bytes_with_zero()); +} + +TEST(GeneratedMessageTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); + + message.set_default_string("blah"); + EXPECT_TRUE(message.has_default_string()); + string* str = message.release_default_string(); + EXPECT_FALSE(message.has_default_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + delete str; + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); +} + +TEST(GeneratedMessageTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + unittest::TestAllTypes::NestedMessage* nest = + message.release_optional_nested_message(); + EXPECT_FALSE(message.has_optional_nested_message()); + ASSERT_TRUE(nest != NULL); + EXPECT_EQ(1, nest->bb()); + delete nest; + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); +} + +TEST(GeneratedMessageTest, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + unittest::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_string()); + const string kHello("hello"); + message.set_optional_string(kHello); + EXPECT_TRUE(message.has_optional_string()); + + message.set_allocated_optional_string(NULL); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_EQ("", message.optional_string()); + + message.set_allocated_optional_string(new string(kHello)); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_EQ(kHello, message.optional_string()); +} + +TEST(GeneratedMessageTest, SetAllocatedMessage) { + // Check that set_allocated_foo() can be called in all cases. + unittest::TestAllTypes message; + + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + EXPECT_TRUE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + unittest::TestAllTypes::NestedMessage* nest = + message.release_optional_nested_message(); + ASSERT_TRUE(nest != NULL); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.set_allocated_optional_nested_message(nest); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_EQ(1, message.optional_nested_message().bb()); +} + +TEST(GeneratedMessageTest, Clear) { + // Set every field to a unique value, clear the message, then check that + // it is cleared. + unittest::TestAllTypes message; + + TestUtil::SetAllFields(&message); + message.Clear(); + TestUtil::ExpectClear(message); + + // Unlike with the defaults test, we do NOT expect that requesting embedded + // messages will return a pointer to the default instance. Instead, they + // should return the objects that were created when mutable_blah() was + // called. + EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(), + &message.optionalgroup()); + EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + EXPECT_NE(&unittest::ForeignMessage::default_instance(), + &message.optional_foreign_message()); + EXPECT_NE(&unittest_import::ImportMessage::default_instance(), + &message.optional_import_message()); +} + +TEST(GeneratedMessageTest, EmbeddedNullsInBytesCharStar) { + unittest::TestAllTypes message; + + const char* value = "\0lalala\0\0"; + message.set_optional_bytes(value, 9); + ASSERT_EQ(9, message.optional_bytes().size()); + EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9)); + + message.add_repeated_bytes(value, 9); + ASSERT_EQ(9, message.repeated_bytes(0).size()); + EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9)); +} + +TEST(GeneratedMessageTest, ClearOneField) { + // Set every field to a unique value, then clear one value and insure that + // only that one value is cleared. + unittest::TestAllTypes message; + + TestUtil::SetAllFields(&message); + int64 original_value = message.optional_int64(); + + // Clear the field and make sure it shows up as cleared. + message.clear_optional_int64(); + EXPECT_FALSE(message.has_optional_int64()); + EXPECT_EQ(0, message.optional_int64()); + + // Other adjacent fields should not be cleared. + EXPECT_TRUE(message.has_optional_int32()); + EXPECT_TRUE(message.has_optional_uint32()); + + // Make sure if we set it again, then all fields are set. + message.set_optional_int64(original_value); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GeneratedMessageTest, StringCharStarLength) { + // Verify that we can use a char*,length to set one of the string fields. + unittest::TestAllTypes message; + message.set_optional_string("abcdef", 3); + EXPECT_EQ("abc", message.optional_string()); + + // Verify that we can use a char*,length to add to a repeated string field. + message.add_repeated_string("abcdef", 3); + EXPECT_EQ(1, message.repeated_string_size()); + EXPECT_EQ("abc", message.repeated_string(0)); + + // Verify that we can use a char*,length to set a repeated string field. + message.set_repeated_string(0, "wxyz", 2); + EXPECT_EQ("wx", message.repeated_string(0)); +} + +TEST(GeneratedMessageTest, CopyFrom) { + unittest::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + message2.CopyFrom(message1); + TestUtil::ExpectAllFieldsSet(message2); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + TestUtil::ExpectAllFieldsSet(message2); +} + +TEST(GeneratedMessageTest, SwapWithEmpty) { + unittest::TestAllTypes message1, message2; + TestUtil::SetAllFields(&message1); + + TestUtil::ExpectAllFieldsSet(message1); + TestUtil::ExpectClear(message2); + message1.Swap(&message2); + TestUtil::ExpectAllFieldsSet(message2); + TestUtil::ExpectClear(message1); +} + +TEST(GeneratedMessageTest, SwapWithSelf) { + unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); + message.Swap(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GeneratedMessageTest, SwapWithOther) { + unittest::TestAllTypes message1, message2; + + message1.set_optional_int32(123); + message1.set_optional_string("abc"); + message1.mutable_optional_nested_message()->set_bb(1); + message1.set_optional_nested_enum(unittest::TestAllTypes::FOO); + message1.add_repeated_int32(1); + message1.add_repeated_int32(2); + message1.add_repeated_string("a"); + message1.add_repeated_string("b"); + message1.add_repeated_nested_message()->set_bb(7); + message1.add_repeated_nested_message()->set_bb(8); + message1.add_repeated_nested_enum(unittest::TestAllTypes::FOO); + message1.add_repeated_nested_enum(unittest::TestAllTypes::BAR); + + message2.set_optional_int32(456); + message2.set_optional_string("def"); + message2.mutable_optional_nested_message()->set_bb(2); + message2.set_optional_nested_enum(unittest::TestAllTypes::BAR); + message2.add_repeated_int32(3); + message2.add_repeated_string("c"); + message2.add_repeated_nested_message()->set_bb(9); + message2.add_repeated_nested_enum(unittest::TestAllTypes::BAZ); + + message1.Swap(&message2); + + EXPECT_EQ(456, message1.optional_int32()); + EXPECT_EQ("def", message1.optional_string()); + EXPECT_EQ(2, message1.optional_nested_message().bb()); + EXPECT_EQ(unittest::TestAllTypes::BAR, message1.optional_nested_enum()); + ASSERT_EQ(1, message1.repeated_int32_size()); + EXPECT_EQ(3, message1.repeated_int32(0)); + ASSERT_EQ(1, message1.repeated_string_size()); + EXPECT_EQ("c", message1.repeated_string(0)); + ASSERT_EQ(1, message1.repeated_nested_message_size()); + EXPECT_EQ(9, message1.repeated_nested_message(0).bb()); + ASSERT_EQ(1, message1.repeated_nested_enum_size()); + EXPECT_EQ(unittest::TestAllTypes::BAZ, message1.repeated_nested_enum(0)); + + EXPECT_EQ(123, message2.optional_int32()); + EXPECT_EQ("abc", message2.optional_string()); + EXPECT_EQ(1, message2.optional_nested_message().bb()); + EXPECT_EQ(unittest::TestAllTypes::FOO, message2.optional_nested_enum()); + ASSERT_EQ(2, message2.repeated_int32_size()); + EXPECT_EQ(1, message2.repeated_int32(0)); + EXPECT_EQ(2, message2.repeated_int32(1)); + ASSERT_EQ(2, message2.repeated_string_size()); + EXPECT_EQ("a", message2.repeated_string(0)); + EXPECT_EQ("b", message2.repeated_string(1)); + ASSERT_EQ(2, message2.repeated_nested_message_size()); + EXPECT_EQ(7, message2.repeated_nested_message(0).bb()); + EXPECT_EQ(8, message2.repeated_nested_message(1).bb()); + ASSERT_EQ(2, message2.repeated_nested_enum_size()); + EXPECT_EQ(unittest::TestAllTypes::FOO, message2.repeated_nested_enum(0)); + EXPECT_EQ(unittest::TestAllTypes::BAR, message2.repeated_nested_enum(1)); +} + +TEST(GeneratedMessageTest, CopyConstructor) { + unittest::TestAllTypes message1; + TestUtil::SetAllFields(&message1); + + unittest::TestAllTypes message2(message1); + TestUtil::ExpectAllFieldsSet(message2); +} + +TEST(GeneratedMessageTest, CopyAssignmentOperator) { + unittest::TestAllTypes message1; + TestUtil::SetAllFields(&message1); + + unittest::TestAllTypes message2; + message2 = message1; + TestUtil::ExpectAllFieldsSet(message2); + + // Make sure that self-assignment does something sane. + message2.operator=(message2); + TestUtil::ExpectAllFieldsSet(message2); +} + +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ + !defined(GOOGLE_PROTOBUF_NO_RTTI) +TEST(GeneratedMessageTest, UpcastCopyFrom) { + // Test the CopyFrom method that takes in the generic const Message& + // parameter. + unittest::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + + const Message* source = implicit_cast(&message1); + message2.CopyFrom(*source); + + TestUtil::ExpectAllFieldsSet(message2); +} +#endif + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GeneratedMessageTest, DynamicMessageCopyFrom) { + // Test copying from a DynamicMessage, which must fall back to using + // reflection. + unittest::TestAllTypes message2; + + // Construct a new version of the dynamic message via the factory. + DynamicMessageFactory factory; + scoped_ptr message1; + message1.reset(factory.GetPrototype( + unittest::TestAllTypes::descriptor())->New()); + + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + reflection_tester.SetAllFieldsViaReflection(message1.get()); + + message2.CopyFrom(*message1); + + TestUtil::ExpectAllFieldsSet(message2); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GeneratedMessageTest, NonEmptyMergeFrom) { + // Test merging with a non-empty message. Code is a modified form + // of that found in google/protobuf/reflection_ops_unittest.cc. + unittest::TestAllTypes message1, message2; + + TestUtil::SetAllFields(&message1); + + // This field will test merging into an empty spot. + message2.set_optional_int32(message1.optional_int32()); + message1.clear_optional_int32(); + + // This tests overwriting. + message2.set_optional_string(message1.optional_string()); + message1.set_optional_string("something else"); + + // This tests concatenating. + message2.add_repeated_int32(message1.repeated_int32(1)); + int32 i = message1.repeated_int32(0); + message1.clear_repeated_int32(); + message1.add_repeated_int32(i); + + message1.MergeFrom(message2); + + TestUtil::ExpectAllFieldsSet(message1); +} + +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ + !defined(GOOGLE_PROTOBUF_NO_RTTI) +#ifdef PROTOBUF_HAS_DEATH_TEST + +TEST(GeneratedMessageTest, MergeFromSelf) { + unittest::TestAllTypes message; + EXPECT_DEATH(message.MergeFrom(message), "&from"); + EXPECT_DEATH(message.MergeFrom(implicit_cast(message)), + "&from"); +} + +#endif // PROTOBUF_HAS_DEATH_TEST +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS || !GOOGLE_PROTOBUF_NO_RTTI + +// Test the generated SerializeWithCachedSizesToArray(), +TEST(GeneratedMessageTest, SerializationToArray) { + unittest::TestAllTypes message1, message2; + string data; + TestUtil::SetAllFields(&message1); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message2); + +} + +TEST(GeneratedMessageTest, PackedFieldsSerializationToArray) { + unittest::TestPackedTypes packed_message1, packed_message2; + string packed_data; + TestUtil::SetPackedFields(&packed_message1); + int packed_size = packed_message1.ByteSize(); + packed_data.resize(packed_size); + uint8* start = reinterpret_cast(string_as_array(&packed_data)); + uint8* end = packed_message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(packed_size, end - start); + EXPECT_TRUE(packed_message2.ParseFromString(packed_data)); + TestUtil::ExpectPackedFieldsSet(packed_message2); +} + +// Test the generated SerializeWithCachedSizes() by forcing the buffer to write +// one byte at a time. +TEST(GeneratedMessageTest, SerializationToStream) { + unittest::TestAllTypes message1, message2; + TestUtil::SetAllFields(&message1); + int size = message1.ByteSize(); + string data; + data.resize(size); + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message2); + +} + +TEST(GeneratedMessageTest, PackedFieldsSerializationToStream) { + unittest::TestPackedTypes message1, message2; + TestUtil::SetPackedFields(&message1); + int size = message1.ByteSize(); + string data; + data.resize(size); + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + EXPECT_TRUE(message2.ParseFromString(data)); + TestUtil::ExpectPackedFieldsSet(message2); +} + + +TEST(GeneratedMessageTest, Required) { + // Test that IsInitialized() returns false if required fields are missing. + unittest::TestRequired message; + + EXPECT_FALSE(message.IsInitialized()); + message.set_a(1); + EXPECT_FALSE(message.IsInitialized()); + message.set_b(2); + EXPECT_FALSE(message.IsInitialized()); + message.set_c(3); + EXPECT_TRUE(message.IsInitialized()); +} + +TEST(GeneratedMessageTest, RequiredForeign) { + // Test that IsInitialized() returns false if required fields in nested + // messages are missing. + unittest::TestRequiredForeign message; + + EXPECT_TRUE(message.IsInitialized()); + + message.mutable_optional_message(); + EXPECT_FALSE(message.IsInitialized()); + + message.mutable_optional_message()->set_a(1); + message.mutable_optional_message()->set_b(2); + message.mutable_optional_message()->set_c(3); + EXPECT_TRUE(message.IsInitialized()); + + message.add_repeated_message(); + EXPECT_FALSE(message.IsInitialized()); + + message.mutable_repeated_message(0)->set_a(1); + message.mutable_repeated_message(0)->set_b(2); + message.mutable_repeated_message(0)->set_c(3); + EXPECT_TRUE(message.IsInitialized()); +} + +TEST(GeneratedMessageTest, ForeignNested) { + // Test that TestAllTypes::NestedMessage can be embedded directly into + // another message. + unittest::TestForeignNested message; + + // If this compiles and runs without crashing, it must work. We have + // nothing more to test. + unittest::TestAllTypes::NestedMessage* nested = + message.mutable_foreign_nested(); + nested->set_bb(1); +} + +TEST(GeneratedMessageTest, ReallyLargeTagNumber) { + // Test that really large tag numbers don't break anything. + unittest::TestReallyLargeTagNumber message1, message2; + string data; + + // For the most part, if this compiles and runs then we're probably good. + // (The most likely cause for failure would be if something were attempting + // to allocate a lookup table of some sort using tag numbers as the index.) + // We'll try serializing just for fun. + message1.set_a(1234); + message1.set_bb(5678); + message1.SerializeToString(&data); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(1234, message2.a()); + EXPECT_EQ(5678, message2.bb()); +} + +TEST(GeneratedMessageTest, MutualRecursion) { + // Test that mutually-recursive message types work. + unittest::TestMutualRecursionA message; + unittest::TestMutualRecursionA* nested = message.mutable_bb()->mutable_a(); + unittest::TestMutualRecursionA* nested2 = nested->mutable_bb()->mutable_a(); + + // Again, if the above compiles and runs, that's all we really have to + // test, but just for run we'll check that the system didn't somehow come + // up with a pointer loop... + EXPECT_NE(&message, nested); + EXPECT_NE(&message, nested2); + EXPECT_NE(nested, nested2); +} + +TEST(GeneratedMessageTest, CamelCaseFieldNames) { + // This test is mainly checking that the following compiles, which verifies + // that the field names were coerced to lower-case. + // + // Protocol buffers standard style is to use lowercase-with-underscores for + // field names. Some old proto1 .protos unfortunately used camel-case field + // names. In proto1, these names were forced to lower-case. So, we do the + // same thing in proto2. + + unittest::TestCamelCaseFieldNames message; + + message.set_primitivefield(2); + message.set_stringfield("foo"); + message.set_enumfield(unittest::FOREIGN_FOO); + message.mutable_messagefield()->set_c(6); + + message.add_repeatedprimitivefield(8); + message.add_repeatedstringfield("qux"); + message.add_repeatedenumfield(unittest::FOREIGN_BAR); + message.add_repeatedmessagefield()->set_c(15); + + EXPECT_EQ(2, message.primitivefield()); + EXPECT_EQ("foo", message.stringfield()); + EXPECT_EQ(unittest::FOREIGN_FOO, message.enumfield()); + EXPECT_EQ(6, message.messagefield().c()); + + EXPECT_EQ(8, message.repeatedprimitivefield(0)); + EXPECT_EQ("qux", message.repeatedstringfield(0)); + EXPECT_EQ(unittest::FOREIGN_BAR, message.repeatedenumfield(0)); + EXPECT_EQ(15, message.repeatedmessagefield(0).c()); +} + +TEST(GeneratedMessageTest, TestConflictingSymbolNames) { + // test_bad_identifiers.proto successfully compiled, then it works. The + // following is just a token usage to insure that the code is, in fact, + // being compiled and linked. + + protobuf_unittest::TestConflictingSymbolNames message; + message.set_uint32(1); + EXPECT_EQ(3, message.ByteSize()); + + message.set_friend_(5); + EXPECT_EQ(5, message.friend_()); + + // Instantiate extension template functions to test conflicting template + // parameter names. + typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage; + message.AddExtension(ExtensionMessage::repeated_int32_ext, 123); + EXPECT_EQ(123, + message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); +} + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GeneratedMessageTest, TestOptimizedForSize) { + // We rely on the tests in reflection_ops_unittest and wire_format_unittest + // to really test that reflection-based methods work. Here we are mostly + // just making sure that TestOptimizedForSize actually builds and seems to + // function. + + protobuf_unittest::TestOptimizedForSize message, message2; + message.set_i(1); + message.mutable_msg()->set_c(2); + message2.CopyFrom(message); + EXPECT_EQ(1, message2.i()); + EXPECT_EQ(2, message2.msg().c()); +} + +TEST(GeneratedMessageTest, TestEmbedOptimizedForSize) { + // Verifies that something optimized for speed can contain something optimized + // for size. + + protobuf_unittest::TestEmbedOptimizedForSize message, message2; + message.mutable_optional_message()->set_i(1); + message.add_repeated_message()->mutable_msg()->set_c(2); + string data; + message.SerializeToString(&data); + ASSERT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(1, message2.optional_message().i()); + EXPECT_EQ(2, message2.repeated_message(0).msg().c()); +} + +TEST(GeneratedMessageTest, TestSpaceUsed) { + unittest::TestAllTypes message1; + // sizeof provides a lower bound on SpaceUsed(). + EXPECT_LE(sizeof(unittest::TestAllTypes), message1.SpaceUsed()); + const int empty_message_size = message1.SpaceUsed(); + + // Setting primitive types shouldn't affect the space used. + message1.set_optional_int32(123); + message1.set_optional_int64(12345); + message1.set_optional_uint32(123); + message1.set_optional_uint64(12345); + EXPECT_EQ(empty_message_size, message1.SpaceUsed()); + + // On some STL implementations, setting the string to a small value should + // only increase SpaceUsed() by the size of a string object, though this is + // not true everywhere. + message1.set_optional_string("abc"); + EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); + + // Setting a string to a value larger than the string object itself should + // increase SpaceUsed(), because it cannot store the value internally. + message1.set_optional_string(string(sizeof(string) + 1, 'x')); + int min_expected_increase = message1.optional_string().capacity() + + sizeof(string); + EXPECT_LE(empty_message_size + min_expected_increase, + message1.SpaceUsed()); + + int previous_size = message1.SpaceUsed(); + // Adding an optional message should increase the size by the size of the + // nested message type. NestedMessage is simple enough (1 int field) that it + // is equal to sizeof(NestedMessage) + message1.mutable_optional_nested_message(); + ASSERT_EQ(sizeof(unittest::TestAllTypes::NestedMessage), + message1.optional_nested_message().SpaceUsed()); + EXPECT_EQ(previous_size + + sizeof(unittest::TestAllTypes::NestedMessage), + message1.SpaceUsed()); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + + +TEST(GeneratedMessageTest, FieldConstantValues) { + unittest::TestRequired message; + EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51); +} + +TEST(GeneratedMessageTest, ExtensionConstantValues) { + EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000); + EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001); + EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1); + EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16); + EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18); + EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21); + EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31); + EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46); + EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48); + EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); +} + +// =================================================================== + +TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { + // Test that our nested enum values can be used as switch cases. This test + // doesn't actually do anything, the proof that it works is that it + // compiles. + int i =0; + unittest::TestAllTypes::NestedEnum a = unittest::TestAllTypes::BAR; + switch (a) { + case unittest::TestAllTypes::FOO: + i = 1; + break; + case unittest::TestAllTypes::BAR: + i = 2; + break; + case unittest::TestAllTypes::BAZ: + i = 3; + break; + // no default case: We want to make sure the compiler recognizes that + // all cases are covered. (GCC warns if you do not cover all cases of + // an enum in a switch.) + } + + // Token check just for fun. + EXPECT_EQ(2, i); +} + +TEST(GeneratedEnumTest, IsValidValue) { + // Test enum IsValidValue. + EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(1)); + EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(2)); + EXPECT_TRUE(unittest::TestAllTypes::NestedEnum_IsValid(3)); + + EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(0)); + EXPECT_FALSE(unittest::TestAllTypes::NestedEnum_IsValid(4)); + + // Make sure it also works when there are dups. + EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(1)); + EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(2)); + EXPECT_TRUE(unittest::TestEnumWithDupValue_IsValid(3)); + + EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(0)); + EXPECT_FALSE(unittest::TestEnumWithDupValue_IsValid(4)); +} + +TEST(GeneratedEnumTest, MinAndMax) { + EXPECT_EQ(unittest::TestAllTypes::FOO, + unittest::TestAllTypes::NestedEnum_MIN); + EXPECT_EQ(unittest::TestAllTypes::BAZ, + unittest::TestAllTypes::NestedEnum_MAX); + EXPECT_EQ(4, unittest::TestAllTypes::NestedEnum_ARRAYSIZE); + + EXPECT_EQ(unittest::FOREIGN_FOO, unittest::ForeignEnum_MIN); + EXPECT_EQ(unittest::FOREIGN_BAZ, unittest::ForeignEnum_MAX); + EXPECT_EQ(7, unittest::ForeignEnum_ARRAYSIZE); + + EXPECT_EQ(1, unittest::TestEnumWithDupValue_MIN); + EXPECT_EQ(3, unittest::TestEnumWithDupValue_MAX); + EXPECT_EQ(4, unittest::TestEnumWithDupValue_ARRAYSIZE); + + EXPECT_EQ(unittest::SPARSE_E, unittest::TestSparseEnum_MIN); + EXPECT_EQ(unittest::SPARSE_C, unittest::TestSparseEnum_MAX); + EXPECT_EQ(12589235, unittest::TestSparseEnum_ARRAYSIZE); + + // Make sure we can take the address of _MIN, _MAX and _ARRAYSIZE. + void* null_pointer = 0; // NULL may be integer-type, not pointer-type. + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MIN); + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_MAX); + EXPECT_NE(null_pointer, &unittest::TestAllTypes::NestedEnum_ARRAYSIZE); + + EXPECT_NE(null_pointer, &unittest::ForeignEnum_MIN); + EXPECT_NE(null_pointer, &unittest::ForeignEnum_MAX); + EXPECT_NE(null_pointer, &unittest::ForeignEnum_ARRAYSIZE); + + // Make sure we can use _MIN and _MAX as switch cases. + switch (unittest::SPARSE_A) { + case unittest::TestSparseEnum_MIN: + case unittest::TestSparseEnum_MAX: + break; + default: + break; + } +} + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +TEST(GeneratedEnumTest, Name) { + // "Names" in the presence of dup values are a bit arbitrary. + EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO1)); + EXPECT_EQ("FOO1", unittest::TestEnumWithDupValue_Name(unittest::FOO2)); + + EXPECT_EQ("SPARSE_A", unittest::TestSparseEnum_Name(unittest::SPARSE_A)); + EXPECT_EQ("SPARSE_B", unittest::TestSparseEnum_Name(unittest::SPARSE_B)); + EXPECT_EQ("SPARSE_C", unittest::TestSparseEnum_Name(unittest::SPARSE_C)); + EXPECT_EQ("SPARSE_D", unittest::TestSparseEnum_Name(unittest::SPARSE_D)); + EXPECT_EQ("SPARSE_E", unittest::TestSparseEnum_Name(unittest::SPARSE_E)); + EXPECT_EQ("SPARSE_F", unittest::TestSparseEnum_Name(unittest::SPARSE_F)); + EXPECT_EQ("SPARSE_G", unittest::TestSparseEnum_Name(unittest::SPARSE_G)); +} + +TEST(GeneratedEnumTest, Parse) { + unittest::TestEnumWithDupValue dup_value = unittest::FOO1; + EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO1", &dup_value)); + EXPECT_EQ(unittest::FOO1, dup_value); + EXPECT_TRUE(unittest::TestEnumWithDupValue_Parse("FOO2", &dup_value)); + EXPECT_EQ(unittest::FOO2, dup_value); + EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value)); +} + +TEST(GeneratedEnumTest, GetEnumDescriptor) { + EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::ForeignEnum_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(), + GetEnumDescriptor()); + EXPECT_EQ(unittest::TestSparseEnum_descriptor(), + GetEnumDescriptor()); +} + +#endif // PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + +// Support code for testing services. +class GeneratedServiceTest : public testing::Test { + protected: + class MockTestService : public unittest::TestService { + public: + MockTestService() + : called_(false), + method_(""), + controller_(NULL), + request_(NULL), + response_(NULL), + done_(NULL) {} + + ~MockTestService() {} + + void Reset() { called_ = false; } + + // implements TestService ---------------------------------------- + + void Foo(RpcController* controller, + const unittest::FooRequest* request, + unittest::FooResponse* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = "Foo"; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + void Bar(RpcController* controller, + const unittest::BarRequest* request, + unittest::BarResponse* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = "Bar"; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + // --------------------------------------------------------------- + + bool called_; + string method_; + RpcController* controller_; + const Message* request_; + Message* response_; + Closure* done_; + }; + + class MockRpcChannel : public RpcChannel { + public: + MockRpcChannel() + : called_(false), + method_(NULL), + controller_(NULL), + request_(NULL), + response_(NULL), + done_(NULL), + destroyed_(NULL) {} + + ~MockRpcChannel() { + if (destroyed_ != NULL) *destroyed_ = true; + } + + void Reset() { called_ = false; } + + // implements TestService ---------------------------------------- + + void CallMethod(const MethodDescriptor* method, + RpcController* controller, + const Message* request, + Message* response, + Closure* done) { + ASSERT_FALSE(called_); + called_ = true; + method_ = method; + controller_ = controller; + request_ = request; + response_ = response; + done_ = done; + } + + // --------------------------------------------------------------- + + bool called_; + const MethodDescriptor* method_; + RpcController* controller_; + const Message* request_; + Message* response_; + Closure* done_; + bool* destroyed_; + }; + + class MockController : public RpcController { + public: + void Reset() { + ADD_FAILURE() << "Reset() not expected during this test."; + } + bool Failed() const { + ADD_FAILURE() << "Failed() not expected during this test."; + return false; + } + string ErrorText() const { + ADD_FAILURE() << "ErrorText() not expected during this test."; + return ""; + } + void StartCancel() { + ADD_FAILURE() << "StartCancel() not expected during this test."; + } + void SetFailed(const string& reason) { + ADD_FAILURE() << "SetFailed() not expected during this test."; + } + bool IsCanceled() const { + ADD_FAILURE() << "IsCanceled() not expected during this test."; + return false; + } + void NotifyOnCancel(Closure* callback) { + ADD_FAILURE() << "NotifyOnCancel() not expected during this test."; + } + }; + + GeneratedServiceTest() + : descriptor_(unittest::TestService::descriptor()), + foo_(descriptor_->FindMethodByName("Foo")), + bar_(descriptor_->FindMethodByName("Bar")), + stub_(&mock_channel_), + done_(NewPermanentCallback(&DoNothing)) {} + + virtual void SetUp() { + ASSERT_TRUE(foo_ != NULL); + ASSERT_TRUE(bar_ != NULL); + } + + const ServiceDescriptor* descriptor_; + const MethodDescriptor* foo_; + const MethodDescriptor* bar_; + + MockTestService mock_service_; + MockController mock_controller_; + + MockRpcChannel mock_channel_; + unittest::TestService::Stub stub_; + + // Just so we don't have to re-define these with every test. + unittest::FooRequest foo_request_; + unittest::FooResponse foo_response_; + unittest::BarRequest bar_request_; + unittest::BarResponse bar_response_; + scoped_ptr done_; +}; + +TEST_F(GeneratedServiceTest, GetDescriptor) { + // Test that GetDescriptor() works. + + EXPECT_EQ(descriptor_, mock_service_.GetDescriptor()); +} + +TEST_F(GeneratedServiceTest, GetChannel) { + EXPECT_EQ(&mock_channel_, stub_.channel()); +} + +TEST_F(GeneratedServiceTest, OwnsChannel) { + MockRpcChannel* channel = new MockRpcChannel; + bool destroyed = false; + channel->destroyed_ = &destroyed; + + { + unittest::TestService::Stub owning_stub(channel, + Service::STUB_OWNS_CHANNEL); + EXPECT_FALSE(destroyed); + } + + EXPECT_TRUE(destroyed); +} + +TEST_F(GeneratedServiceTest, CallMethod) { + // Test that CallMethod() works. + + // Call Foo() via CallMethod(). + mock_service_.CallMethod(foo_, &mock_controller_, + &foo_request_, &foo_response_, done_.get()); + + ASSERT_TRUE(mock_service_.called_); + + EXPECT_EQ("Foo" , mock_service_.method_ ); + EXPECT_EQ(&mock_controller_, mock_service_.controller_); + EXPECT_EQ(&foo_request_ , mock_service_.request_ ); + EXPECT_EQ(&foo_response_ , mock_service_.response_ ); + EXPECT_EQ(done_.get() , mock_service_.done_ ); + + // Try again, but call Bar() instead. + mock_service_.Reset(); + mock_service_.CallMethod(bar_, &mock_controller_, + &bar_request_, &bar_response_, done_.get()); + + ASSERT_TRUE(mock_service_.called_); + EXPECT_EQ("Bar", mock_service_.method_); +} + +TEST_F(GeneratedServiceTest, CallMethodTypeFailure) { + // Verify death if we call Foo() with Bar's message types. + +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet + EXPECT_DEBUG_DEATH( + mock_service_.CallMethod(foo_, &mock_controller_, + &foo_request_, &bar_response_, done_.get()), + "dynamic_cast"); + + mock_service_.Reset(); + EXPECT_DEBUG_DEATH( + mock_service_.CallMethod(foo_, &mock_controller_, + &bar_request_, &foo_response_, done_.get()), + "dynamic_cast"); +#endif // PROTOBUF_HAS_DEATH_TEST +} + +TEST_F(GeneratedServiceTest, GetPrototypes) { + // Test Get{Request,Response}Prototype() methods. + + EXPECT_EQ(&unittest::FooRequest::default_instance(), + &mock_service_.GetRequestPrototype(foo_)); + EXPECT_EQ(&unittest::BarRequest::default_instance(), + &mock_service_.GetRequestPrototype(bar_)); + + EXPECT_EQ(&unittest::FooResponse::default_instance(), + &mock_service_.GetResponsePrototype(foo_)); + EXPECT_EQ(&unittest::BarResponse::default_instance(), + &mock_service_.GetResponsePrototype(bar_)); +} + +TEST_F(GeneratedServiceTest, Stub) { + // Test that the stub class works. + + // Call Foo() via the stub. + stub_.Foo(&mock_controller_, &foo_request_, &foo_response_, done_.get()); + + ASSERT_TRUE(mock_channel_.called_); + + EXPECT_EQ(foo_ , mock_channel_.method_ ); + EXPECT_EQ(&mock_controller_, mock_channel_.controller_); + EXPECT_EQ(&foo_request_ , mock_channel_.request_ ); + EXPECT_EQ(&foo_response_ , mock_channel_.response_ ); + EXPECT_EQ(done_.get() , mock_channel_.done_ ); + + // Call Bar() via the stub. + mock_channel_.Reset(); + stub_.Bar(&mock_controller_, &bar_request_, &bar_response_, done_.get()); + + ASSERT_TRUE(mock_channel_.called_); + EXPECT_EQ(bar_, mock_channel_.method_); +} + +TEST_F(GeneratedServiceTest, NotImplemented) { + // Test that failing to implement a method of a service causes it to fail + // with a "not implemented" error message. + + // A service which doesn't implement any methods. + class UnimplementedService : public unittest::TestService { + public: + UnimplementedService() {} + }; + + UnimplementedService unimplemented_service; + + // And a controller which expects to get a "not implemented" error. + class ExpectUnimplementedController : public MockController { + public: + ExpectUnimplementedController() : called_(false) {} + + void SetFailed(const string& reason) { + EXPECT_FALSE(called_); + called_ = true; + EXPECT_EQ("Method Foo() not implemented.", reason); + } + + bool called_; + }; + + ExpectUnimplementedController controller; + + // Call Foo. + unimplemented_service.Foo(&controller, &foo_request_, &foo_response_, + done_.get()); + + EXPECT_TRUE(controller.called_); +} + +} // namespace cpp_unittest +} // namespace cpp +} // namespace compiler + +namespace no_generic_services_test { + // Verify that no class called "TestService" was defined in + // unittest_no_generic_services.pb.h by defining a different type by the same + // name. If such a service was generated, this will not compile. + struct TestService { + int i; + }; +} + +namespace compiler { +namespace cpp { +namespace cpp_unittest { + +TEST_F(GeneratedServiceTest, NoGenericServices) { + // Verify that non-services in unittest_no_generic_services.proto were + // generated. + no_generic_services_test::TestMessage message; + message.set_a(1); + message.SetExtension(no_generic_services_test::test_extension, 123); + no_generic_services_test::TestEnum e = no_generic_services_test::FOO; + EXPECT_EQ(e, 1); + + // Verify that a ServiceDescriptor is generated for the service even if the + // class itself is not. + const FileDescriptor* file = + no_generic_services_test::TestMessage::descriptor()->file(); + + ASSERT_EQ(1, file->service_count()); + EXPECT_EQ("TestService", file->service(0)->name()); + ASSERT_EQ(1, file->service(0)->method_count()); + EXPECT_EQ("Foo", file->service(0)->method(0)->name()); +} + +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS + +// =================================================================== + +// This test must run last. It verifies that descriptors were or were not +// initialized depending on whether PROTOBUF_TEST_NO_DESCRIPTORS was defined. +// When this is defined, we skip all tests which are expected to trigger +// descriptor initialization. This verifies that everything else still works +// if descriptors are not initialized. +TEST(DescriptorInitializationTest, Initialized) { +#ifdef PROTOBUF_TEST_NO_DESCRIPTORS + bool should_have_descriptors = false; +#else + bool should_have_descriptors = true; +#endif + + EXPECT_EQ(should_have_descriptors, + DescriptorPool::generated_pool()->InternalIsFileLoaded( + "google/protobuf/unittest.proto")); +} + +} // namespace cpp_unittest + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h new file mode 100644 index 000000000..a3a1d1baa --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/cpp/cpp_unittest.h @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 declares the namespace google::protobuf::protobuf_unittest in order to expose +// any problems with the generated class names. We use this header to ensure +// unittest.cc will declare the namespace prior to other includes, while obeying +// normal include ordering. +// +// When generating a class name of "foo.Bar" we must ensure we prefix the class +// name with "::", in case the namespace google::protobuf::foo exists. We intentionally +// trigger that case here by declaring google::protobuf::protobuf_unittest. +// +// See ClassName in helpers.h for more details. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ + +namespace google { +namespace protobuf { +namespace protobuf_unittest {} +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.cc new file mode 100644 index 000000000..422f759f2 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.cc @@ -0,0 +1,459 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 _MSC_VER +#include +#else +#include +#endif +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +#ifdef _WIN32 +#ifndef F_OK +#define F_OK 00 // not defined by MSVC for whatever reason +#endif +#include +#endif + +// Returns true if the text looks like a Windows-style absolute path, starting +// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with +// copy in command_line_interface.cc? +static bool IsWindowsAbsolutePath(const string& text) { +#if defined(_WIN32) || defined(__CYGWIN__) + return text.size() >= 3 && text[1] == ':' && + isalpha(text[0]) && + (text[2] == '/' || text[2] == '\\') && + text.find_last_of(':') == 1; +#else + return false; +#endif +} + +MultiFileErrorCollector::~MultiFileErrorCollector() {} + +// This class serves two purposes: +// - It implements the ErrorCollector interface (used by Tokenizer and Parser) +// in terms of MultiFileErrorCollector, using a particular filename. +// - It lets us check if any errors have occurred. +class SourceTreeDescriptorDatabase::SingleFileErrorCollector + : public io::ErrorCollector { + public: + SingleFileErrorCollector(const string& filename, + MultiFileErrorCollector* multi_file_error_collector) + : filename_(filename), + multi_file_error_collector_(multi_file_error_collector), + had_errors_(false) {} + ~SingleFileErrorCollector() {} + + bool had_errors() { return had_errors_; } + + // implements ErrorCollector --------------------------------------- + void AddError(int line, int column, const string& message) { + if (multi_file_error_collector_ != NULL) { + multi_file_error_collector_->AddError(filename_, line, column, message); + } + had_errors_ = true; + } + + private: + string filename_; + MultiFileErrorCollector* multi_file_error_collector_; + bool had_errors_; +}; + +// =================================================================== + +SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase( + SourceTree* source_tree) + : source_tree_(source_tree), + error_collector_(NULL), + using_validation_error_collector_(false), + validation_error_collector_(this) {} + +SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {} + +bool SourceTreeDescriptorDatabase::FindFileByName( + const string& filename, FileDescriptorProto* output) { + scoped_ptr input(source_tree_->Open(filename)); + if (input == NULL) { + if (error_collector_ != NULL) { + error_collector_->AddError(filename, -1, 0, "File not found."); + } + return false; + } + + // Set up the tokenizer and parser. + SingleFileErrorCollector file_error_collector(filename, error_collector_); + io::Tokenizer tokenizer(input.get(), &file_error_collector); + + Parser parser; + if (error_collector_ != NULL) { + parser.RecordErrorsTo(&file_error_collector); + } + if (using_validation_error_collector_) { + parser.RecordSourceLocationsTo(&source_locations_); + } + + // Parse it. + output->set_name(filename); + return parser.Parse(&tokenizer, output) && + !file_error_collector.had_errors(); +} + +bool SourceTreeDescriptorDatabase::FindFileContainingSymbol( + const string& symbol_name, FileDescriptorProto* output) { + return false; +} + +bool SourceTreeDescriptorDatabase::FindFileContainingExtension( + const string& containing_type, int field_number, + FileDescriptorProto* output) { + return false; +} + +// ------------------------------------------------------------------- + +SourceTreeDescriptorDatabase::ValidationErrorCollector:: +ValidationErrorCollector(SourceTreeDescriptorDatabase* owner) + : owner_(owner) {} + +SourceTreeDescriptorDatabase::ValidationErrorCollector:: +~ValidationErrorCollector() {} + +void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError( + const string& filename, + const string& element_name, + const Message* descriptor, + ErrorLocation location, + const string& message) { + if (owner_->error_collector_ == NULL) return; + + int line, column; + owner_->source_locations_.Find(descriptor, location, &line, &column); + owner_->error_collector_->AddError(filename, line, column, message); +} + +// =================================================================== + +Importer::Importer(SourceTree* source_tree, + MultiFileErrorCollector* error_collector) + : database_(source_tree), + pool_(&database_, database_.GetValidationErrorCollector()) { + database_.RecordErrorsTo(error_collector); +} + +Importer::~Importer() {} + +const FileDescriptor* Importer::Import(const string& filename) { + return pool_.FindFileByName(filename); +} + +// =================================================================== + +SourceTree::~SourceTree() {} + +DiskSourceTree::DiskSourceTree() {} + +DiskSourceTree::~DiskSourceTree() {} + +static inline char LastChar(const string& str) { + return str[str.size() - 1]; +} + +// Given a path, returns an equivalent path with these changes: +// - On Windows, any backslashes are replaced with forward slashes. +// - Any instances of the directory "." are removed. +// - Any consecutive '/'s are collapsed into a single slash. +// Note that the resulting string may be empty. +// +// TODO(kenton): It would be nice to handle "..", e.g. so that we can figure +// out that "foo/bar.proto" is inside "baz/../foo". However, if baz is a +// symlink or doesn't exist, then things get complicated, and we can't +// actually determine this without investigating the filesystem, probably +// in non-portable ways. So, we punt. +// +// TODO(kenton): It would be nice to use realpath() here except that it +// resolves symbolic links. This could cause problems if people place +// symbolic links in their source tree. For example, if you executed: +// protoc --proto_path=foo foo/bar/baz.proto +// then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize +// to a path which does not appear to be under foo, and thus the compiler +// will complain that baz.proto is not inside the --proto_path. +static string CanonicalizePath(string path) { +#ifdef _WIN32 + // The Win32 API accepts forward slashes as a path delimiter even though + // backslashes are standard. Let's avoid confusion and use only forward + // slashes. + if (HasPrefixString(path, "\\\\")) { + // Avoid converting two leading backslashes. + path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true); + } else { + path = StringReplace(path, "\\", "/", true); + } +#endif + + vector parts; + vector canonical_parts; + SplitStringUsing(path, "/", &parts); // Note: Removes empty parts. + for (int i = 0; i < parts.size(); i++) { + if (parts[i] == ".") { + // Ignore. + } else { + canonical_parts.push_back(parts[i]); + } + } + string result = JoinStrings(canonical_parts, "/"); + if (!path.empty() && path[0] == '/') { + // Restore leading slash. + result = '/' + result; + } + if (!path.empty() && LastChar(path) == '/' && + !result.empty() && LastChar(result) != '/') { + // Restore trailing slash. + result += '/'; + } + return result; +} + +static inline bool ContainsParentReference(const string& path) { + return path == ".." || + HasPrefixString(path, "../") || + HasSuffixString(path, "/..") || + path.find("/../") != string::npos; +} + +// Maps a file from an old location to a new one. Typically, old_prefix is +// a virtual path and new_prefix is its corresponding disk path. Returns +// false if the filename did not start with old_prefix, otherwise replaces +// old_prefix with new_prefix and stores the result in *result. Examples: +// string result; +// assert(ApplyMapping("foo/bar", "", "baz", &result)); +// assert(result == "baz/foo/bar"); +// +// assert(ApplyMapping("foo/bar", "foo", "baz", &result)); +// assert(result == "baz/bar"); +// +// assert(ApplyMapping("foo", "foo", "bar", &result)); +// assert(result == "bar"); +// +// assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); +// assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); +// assert(!ApplyMapping("foobar", "foo", "baz", &result)); +static bool ApplyMapping(const string& filename, + const string& old_prefix, + const string& new_prefix, + string* result) { + if (old_prefix.empty()) { + // old_prefix matches any relative path. + if (ContainsParentReference(filename)) { + // We do not allow the file name to use "..". + return false; + } + if (HasPrefixString(filename, "/") || + IsWindowsAbsolutePath(filename)) { + // This is an absolute path, so it isn't matched by the empty string. + return false; + } + result->assign(new_prefix); + if (!result->empty()) result->push_back('/'); + result->append(filename); + return true; + } else if (HasPrefixString(filename, old_prefix)) { + // old_prefix is a prefix of the filename. Is it the whole filename? + if (filename.size() == old_prefix.size()) { + // Yep, it's an exact match. + *result = new_prefix; + return true; + } else { + // Not an exact match. Is the next character a '/'? Otherwise, + // this isn't actually a match at all. E.g. the prefix "foo/bar" + // does not match the filename "foo/barbaz". + int after_prefix_start = -1; + if (filename[old_prefix.size()] == '/') { + after_prefix_start = old_prefix.size() + 1; + } else if (filename[old_prefix.size() - 1] == '/') { + // old_prefix is never empty, and canonicalized paths never have + // consecutive '/' characters. + after_prefix_start = old_prefix.size(); + } + if (after_prefix_start != -1) { + // Yep. So the prefixes are directories and the filename is a file + // inside them. + string after_prefix = filename.substr(after_prefix_start); + if (ContainsParentReference(after_prefix)) { + // We do not allow the file name to use "..". + return false; + } + result->assign(new_prefix); + if (!result->empty()) result->push_back('/'); + result->append(after_prefix); + return true; + } + } + } + + return false; +} + +void DiskSourceTree::MapPath(const string& virtual_path, + const string& disk_path) { + mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path))); +} + +DiskSourceTree::DiskFileToVirtualFileResult +DiskSourceTree::DiskFileToVirtualFile( + const string& disk_file, + string* virtual_file, + string* shadowing_disk_file) { + int mapping_index = -1; + string canonical_disk_file = CanonicalizePath(disk_file); + + for (int i = 0; i < mappings_.size(); i++) { + // Apply the mapping in reverse. + if (ApplyMapping(canonical_disk_file, mappings_[i].disk_path, + mappings_[i].virtual_path, virtual_file)) { + // Success. + mapping_index = i; + break; + } + } + + if (mapping_index == -1) { + return NO_MAPPING; + } + + // Iterate through all mappings with higher precedence and verify that none + // of them map this file to some other existing file. + for (int i = 0; i < mapping_index; i++) { + if (ApplyMapping(*virtual_file, mappings_[i].virtual_path, + mappings_[i].disk_path, shadowing_disk_file)) { + if (access(shadowing_disk_file->c_str(), F_OK) >= 0) { + // File exists. + return SHADOWED; + } + } + } + shadowing_disk_file->clear(); + + // Verify that we can open the file. Note that this also has the side-effect + // of verifying that we are not canonicalizing away any non-existent + // directories. + scoped_ptr stream(OpenDiskFile(disk_file)); + if (stream == NULL) { + return CANNOT_OPEN; + } + + return SUCCESS; +} + +bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file, + string* disk_file) { + scoped_ptr stream(OpenVirtualFile(virtual_file, + disk_file)); + return stream != NULL; +} + +io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) { + return OpenVirtualFile(filename, NULL); +} + +io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( + const string& virtual_file, + string* disk_file) { + if (virtual_file != CanonicalizePath(virtual_file) || + ContainsParentReference(virtual_file)) { + // We do not allow importing of paths containing things like ".." or + // consecutive slashes since the compiler expects files to be uniquely + // identified by file name. + return NULL; + } + + for (int i = 0; i < mappings_.size(); i++) { + string temp_disk_file; + if (ApplyMapping(virtual_file, mappings_[i].virtual_path, + mappings_[i].disk_path, &temp_disk_file)) { + io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file); + if (stream != NULL) { + if (disk_file != NULL) { + *disk_file = temp_disk_file; + } + return stream; + } + + if (errno == EACCES) { + // The file exists but is not readable. + // TODO(kenton): Find a way to report this more nicely. + GOOGLE_LOG(WARNING) << "Read access is denied for file: " << temp_disk_file; + return NULL; + } + } + } + + return NULL; +} + +io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( + const string& filename) { + int file_descriptor; + do { + file_descriptor = open(filename.c_str(), O_RDONLY); + } while (file_descriptor < 0 && errno == EINTR); + if (file_descriptor >= 0) { + io::FileInputStream* result = new io::FileInputStream(file_descriptor); + result->SetCloseOnDelete(true); + return result; + } else { + return NULL; + } +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.h new file mode 100644 index 000000000..7a62fa0e6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer.h @@ -0,0 +1,304 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is the public interface to the .proto file parser. + +#ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ +#define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace io { class ZeroCopyInputStream; } + +namespace compiler { + +// Defined in this file. +class Importer; +class MultiFileErrorCollector; +class SourceTree; +class DiskSourceTree; + +// TODO(kenton): Move all SourceTree stuff to a separate file? + +// An implementation of DescriptorDatabase which loads files from a SourceTree +// and parses them. +// +// Note: This class is not thread-safe since it maintains a table of source +// code locations for error reporting. However, when a DescriptorPool wraps +// a DescriptorDatabase, it uses mutex locking to make sure only one method +// of the database is called at a time, even if the DescriptorPool is used +// from multiple threads. Therefore, there is only a problem if you create +// multiple DescriptorPools wrapping the same SourceTreeDescriptorDatabase +// and use them from multiple threads. +// +// Note: This class does not implement FindFileContainingSymbol() or +// FindFileContainingExtension(); these will always return false. +class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { + public: + SourceTreeDescriptorDatabase(SourceTree* source_tree); + ~SourceTreeDescriptorDatabase(); + + // Instructs the SourceTreeDescriptorDatabase to report any parse errors + // to the given MultiFileErrorCollector. This should be called before + // parsing. error_collector must remain valid until either this method + // is called again or the SourceTreeDescriptorDatabase is destroyed. + void RecordErrorsTo(MultiFileErrorCollector* error_collector) { + error_collector_ = error_collector; + } + + // Gets a DescriptorPool::ErrorCollector which records errors to the + // MultiFileErrorCollector specified with RecordErrorsTo(). This collector + // has the ability to determine exact line and column numbers of errors + // from the information given to it by the DescriptorPool. + DescriptorPool::ErrorCollector* GetValidationErrorCollector() { + using_validation_error_collector_ = true; + return &validation_error_collector_; + } + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const string& filename, FileDescriptorProto* output); + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output); + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output); + + private: + class SingleFileErrorCollector; + + SourceTree* source_tree_; + MultiFileErrorCollector* error_collector_; + + class LIBPROTOBUF_EXPORT ValidationErrorCollector : public DescriptorPool::ErrorCollector { + public: + ValidationErrorCollector(SourceTreeDescriptorDatabase* owner); + ~ValidationErrorCollector(); + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, + const string& element_name, + const Message* descriptor, + ErrorLocation location, + const string& message); + + private: + SourceTreeDescriptorDatabase* owner_; + }; + friend class ValidationErrorCollector; + + bool using_validation_error_collector_; + SourceLocationTable source_locations_; + ValidationErrorCollector validation_error_collector_; +}; + +// Simple interface for parsing .proto files. This wraps the process +// of opening the file, parsing it with a Parser, recursively parsing all its +// imports, and then cross-linking the results to produce a FileDescriptor. +// +// This is really just a thin wrapper around SourceTreeDescriptorDatabase. +// You may find that SourceTreeDescriptorDatabase is more flexible. +// +// TODO(kenton): I feel like this class is not well-named. +class LIBPROTOBUF_EXPORT Importer { + public: + Importer(SourceTree* source_tree, + MultiFileErrorCollector* error_collector); + ~Importer(); + + // Import the given file and build a FileDescriptor representing it. If + // the file is already in the DescriptorPool, the existing FileDescriptor + // will be returned. The FileDescriptor is property of the DescriptorPool, + // and will remain valid until it is destroyed. If any errors occur, they + // will be reported using the error collector and Import() will return NULL. + // + // A particular Importer object will only report errors for a particular + // file once. All future attempts to import the same file will return NULL + // without reporting any errors. The idea is that you might want to import + // a lot of files without seeing the same errors over and over again. If + // you want to see errors for the same files repeatedly, you can use a + // separate Importer object to import each one (but use the same + // DescriptorPool so that they can be cross-linked). + const FileDescriptor* Import(const string& filename); + + // The DescriptorPool in which all imported FileDescriptors and their + // contents are stored. + inline const DescriptorPool* pool() const { + return &pool_; + } + + private: + SourceTreeDescriptorDatabase database_; + DescriptorPool pool_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer); +}; + +// If the importer encounters problems while trying to import the proto files, +// it reports them to a MultiFileErrorCollector. +class LIBPROTOBUF_EXPORT MultiFileErrorCollector { + public: + inline MultiFileErrorCollector() {} + virtual ~MultiFileErrorCollector(); + + // Line and column numbers are zero-based. A line number of -1 indicates + // an error with the entire file (e.g. "not found"). + virtual void AddError(const string& filename, int line, int column, + const string& message) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector); +}; + +// Abstract interface which represents a directory tree containing proto files. +// Used by the default implementation of Importer to resolve import statements +// Most users will probably want to use the DiskSourceTree implementation, +// below. +class LIBPROTOBUF_EXPORT SourceTree { + public: + inline SourceTree() {} + virtual ~SourceTree(); + + // Open the given file and return a stream that reads it, or NULL if not + // found. The caller takes ownership of the returned object. The filename + // must be a path relative to the root of the source tree and must not + // contain "." or ".." components. + virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); +}; + +// An implementation of SourceTree which loads files from locations on disk. +// Multiple mappings can be set up to map locations in the DiskSourceTree to +// locations in the physical filesystem. +class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { + public: + DiskSourceTree(); + ~DiskSourceTree(); + + // Map a path on disk to a location in the SourceTree. The path may be + // either a file or a directory. If it is a directory, the entire tree + // under it will be mapped to the given virtual location. To map a directory + // to the root of the source tree, pass an empty string for virtual_path. + // + // If multiple mapped paths apply when opening a file, they will be searched + // in order. For example, if you do: + // MapPath("bar", "foo/bar"); + // MapPath("", "baz"); + // and then you do: + // Open("bar/qux"); + // the DiskSourceTree will first try to open foo/bar/qux, then baz/bar/qux, + // returning the first one that opens successfuly. + // + // disk_path may be an absolute path or relative to the current directory, + // just like a path you'd pass to open(). + void MapPath(const string& virtual_path, const string& disk_path); + + // Return type for DiskFileToVirtualFile(). + enum DiskFileToVirtualFileResult { + SUCCESS, + SHADOWED, + CANNOT_OPEN, + NO_MAPPING + }; + + // Given a path to a file on disk, find a virtual path mapping to that + // file. The first mapping created with MapPath() whose disk_path contains + // the filename is used. However, that virtual path may not actually be + // usable to open the given file. Possible return values are: + // * SUCCESS: The mapping was found. *virtual_file is filled in so that + // calling Open(*virtual_file) will open the file named by disk_file. + // * SHADOWED: A mapping was found, but using Open() to open this virtual + // path will end up returning some different file. This is because some + // other mapping with a higher precedence also matches this virtual path + // and maps it to a different file that exists on disk. *virtual_file + // is filled in as it would be in the SUCCESS case. *shadowing_disk_file + // is filled in with the disk path of the file which would be opened if + // you were to call Open(*virtual_file). + // * CANNOT_OPEN: The mapping was found and was not shadowed, but the + // file specified cannot be opened. When this value is returned, + // errno will indicate the reason the file cannot be opened. *virtual_file + // will be set to the virtual path as in the SUCCESS case, even though + // it is not useful. + // * NO_MAPPING: Indicates that no mapping was found which contains this + // file. + DiskFileToVirtualFileResult + DiskFileToVirtualFile(const string& disk_file, + string* virtual_file, + string* shadowing_disk_file); + + // Given a virtual path, find the path to the file on disk. + // Return true and update disk_file with the on-disk path if the file exists. + // Return false and leave disk_file untouched if the file doesn't exist. + bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); + + // implements SourceTree ------------------------------------------- + io::ZeroCopyInputStream* Open(const string& filename); + + private: + struct Mapping { + string virtual_path; + string disk_path; + + inline Mapping(const string& virtual_path_param, + const string& disk_path_param) + : virtual_path(virtual_path_param), disk_path(disk_path_param) {} + }; + vector mappings_; + + // Like Open(), but returns the on-disk path in disk_file if disk_file is + // non-NULL and the file could be successfully opened. + io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file, + string* disk_file); + + // Like Open() but given the actual on-disk path. + io::ZeroCopyInputStream* OpenDiskFile(const string& filename); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree); +}; + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer_unittest.cc new file mode 100644 index 000000000..56fad56ed --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/importer_unittest.cc @@ -0,0 +1,600 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { + +#define EXPECT_SUBSTRING(needle, haystack) \ + EXPECT_PRED_FORMAT2(testing::IsSubstring, (needle), (haystack)) + +class MockErrorCollector : public MultiFileErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, int line, int column, + const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", + filename, line, column, message); + } +}; + +// ------------------------------------------------------------------- + +// A dummy implementation of SourceTree backed by a simple map. +class MockSourceTree : public SourceTree { + public: + MockSourceTree() {} + ~MockSourceTree() {} + + void AddFile(const string& name, const char* contents) { + files_[name] = contents; + } + + // implements SourceTree ------------------------------------------- + io::ZeroCopyInputStream* Open(const string& filename) { + const char* contents = FindPtrOrNull(files_, filename); + if (contents == NULL) { + return NULL; + } else { + return new io::ArrayInputStream(contents, strlen(contents)); + } + } + + private: + hash_map files_; +}; + +// =================================================================== + +class ImporterTest : public testing::Test { + protected: + ImporterTest() + : importer_(&source_tree_, &error_collector_) {} + + void AddFile(const string& filename, const char* text) { + source_tree_.AddFile(filename, text); + } + + // Return the collected error text + string error() const { return error_collector_.text_; } + + MockErrorCollector error_collector_; + MockSourceTree source_tree_; + Importer importer_; +}; + +TEST_F(ImporterTest, Import) { + // Test normal importing. + AddFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + + const FileDescriptor* file = importer_.Import("foo.proto"); + EXPECT_EQ("", error_collector_.text_); + ASSERT_TRUE(file != NULL); + + ASSERT_EQ(1, file->message_type_count()); + EXPECT_EQ("Foo", file->message_type(0)->name()); + + // Importing again should return same object. + EXPECT_EQ(file, importer_.Import("foo.proto")); +} + +TEST_F(ImporterTest, ImportNested) { + // Test that importing a file which imports another file works. + AddFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n" + "message Foo {\n" + " optional Bar bar = 1;\n" + "}\n"); + AddFile("bar.proto", + "syntax = \"proto2\";\n" + "message Bar {}\n"); + + // Note that both files are actually parsed by the first call to Import() + // here, since foo.proto imports bar.proto. The second call just returns + // the same ProtoFile for bar.proto which was constructed while importing + // foo.proto. We test that this is the case below by checking that bar + // is among foo's dependencies (by pointer). + const FileDescriptor* foo = importer_.Import("foo.proto"); + const FileDescriptor* bar = importer_.Import("bar.proto"); + EXPECT_EQ("", error_collector_.text_); + ASSERT_TRUE(foo != NULL); + ASSERT_TRUE(bar != NULL); + + // Check that foo's dependency is the same object as bar. + ASSERT_EQ(1, foo->dependency_count()); + EXPECT_EQ(bar, foo->dependency(0)); + + // Check that foo properly cross-links bar. + ASSERT_EQ(1, foo->message_type_count()); + ASSERT_EQ(1, bar->message_type_count()); + ASSERT_EQ(1, foo->message_type(0)->field_count()); + ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, + foo->message_type(0)->field(0)->type()); + EXPECT_EQ(bar->message_type(0), + foo->message_type(0)->field(0)->message_type()); +} + +TEST_F(ImporterTest, FileNotFound) { + // Error: Parsing a file that doesn't exist. + EXPECT_TRUE(importer_.Import("foo.proto") == NULL); + EXPECT_EQ( + "foo.proto:-1:0: File not found.\n", + error_collector_.text_); +} + +TEST_F(ImporterTest, ImportNotFound) { + // Error: Importing a file that doesn't exist. + AddFile("foo.proto", + "syntax = \"proto2\";\n" + "import \"bar.proto\";\n"); + + EXPECT_TRUE(importer_.Import("foo.proto") == NULL); + EXPECT_EQ( + "bar.proto:-1:0: File not found.\n" + "foo.proto:-1:0: Import \"bar.proto\" was not found or had errors.\n", + error_collector_.text_); +} + +TEST_F(ImporterTest, RecursiveImport) { + // Error: Recursive import. + AddFile("recursive1.proto", + "syntax = \"proto2\";\n" + "import \"recursive2.proto\";\n"); + AddFile("recursive2.proto", + "syntax = \"proto2\";\n" + "import \"recursive1.proto\";\n"); + + EXPECT_TRUE(importer_.Import("recursive1.proto") == NULL); + EXPECT_EQ( + "recursive1.proto:-1:0: File recursively imports itself: recursive1.proto " + "-> recursive2.proto -> recursive1.proto\n" + "recursive2.proto:-1:0: Import \"recursive1.proto\" was not found " + "or had errors.\n" + "recursive1.proto:-1:0: Import \"recursive2.proto\" was not found " + "or had errors.\n", + error_collector_.text_); +} + +// TODO(sanjay): The MapField tests below more properly belong in +// descriptor_unittest, but are more convenient to test here. +TEST_F(ImporterTest, MapFieldValid) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Item {\n" + " required string key = 1;\n" + "}\n" + "message Map {\n" + " repeated Item items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + const FileDescriptor* file = importer_.Import("map.proto"); + ASSERT_TRUE(file != NULL) << error_collector_.text_; + EXPECT_EQ("", error_collector_.text_); + + // Check that Map::items points to Item::key + const Descriptor* item_type = file->FindMessageTypeByName("Item"); + ASSERT_TRUE(item_type != NULL); + const Descriptor* map_type = file->FindMessageTypeByName("Map"); + ASSERT_TRUE(map_type != NULL); + const FieldDescriptor* key_field = item_type->FindFieldByName("key"); + ASSERT_TRUE(key_field != NULL); + const FieldDescriptor* items_field = map_type->FindFieldByName("items"); + ASSERT_TRUE(items_field != NULL); + EXPECT_EQ(items_field->experimental_map_key(), key_field); +} + +TEST_F(ImporterTest, MapFieldNotRepeated) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Item {\n" + " required string key = 1;\n" + "}\n" + "message Map {\n" + " required Item items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("only allowed for repeated fields", error()); +} + +TEST_F(ImporterTest, MapFieldNotMessageType) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Map {\n" + " repeated int32 items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("only allowed for fields with a message type", error()); +} + +TEST_F(ImporterTest, MapFieldTypeNotFound) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Map {\n" + " repeated Unknown items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("not defined", error()); +} + +TEST_F(ImporterTest, MapFieldKeyNotFound) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Item {\n" + " required string key = 1;\n" + "}\n" + "message Map {\n" + " repeated Item items = 1 [experimental_map_key = \"badkey\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("Could not find field", error()); +} + +TEST_F(ImporterTest, MapFieldKeyRepeated) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message Item {\n" + " repeated string key = 1;\n" + "}\n" + "message Map {\n" + " repeated Item items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("must not name a repeated field", error()); +} + +TEST_F(ImporterTest, MapFieldKeyNotScalar) { + AddFile( + "map.proto", + "syntax = \"proto2\";\n" + "message ItemKey { }\n" + "message Item {\n" + " required ItemKey key = 1;\n" + "}\n" + "message Map {\n" + " repeated Item items = 1 [experimental_map_key = \"key\"];\n" + "}\n" + ); + EXPECT_TRUE(importer_.Import("map.proto") == NULL); + EXPECT_SUBSTRING("must name a scalar or string", error()); +} + +// =================================================================== + +class DiskSourceTreeTest : public testing::Test { + protected: + virtual void SetUp() { + dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_1"); + dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_2"); + + for (int i = 0; i < dirnames_.size(); i++) { + if (File::Exists(dirnames_[i])) { + File::DeleteRecursively(dirnames_[i], NULL, NULL); + } + GOOGLE_CHECK(File::CreateDir(dirnames_[i].c_str(), DEFAULT_FILE_MODE)); + } + } + + virtual void TearDown() { + for (int i = 0; i < dirnames_.size(); i++) { + File::DeleteRecursively(dirnames_[i], NULL, NULL); + } + } + + void AddFile(const string& filename, const char* contents) { + File::WriteStringToFileOrDie(contents, filename); + } + + void AddSubdir(const string& dirname) { + GOOGLE_CHECK(File::CreateDir(dirname.c_str(), DEFAULT_FILE_MODE)); + } + + void ExpectFileContents(const string& filename, + const char* expected_contents) { + scoped_ptr input(source_tree_.Open(filename)); + + ASSERT_FALSE(input == NULL); + + // Read all the data from the file. + string file_contents; + const void* data; + int size; + while (input->Next(&data, &size)) { + file_contents.append(reinterpret_cast(data), size); + } + + EXPECT_EQ(expected_contents, file_contents); + } + + void ExpectFileNotFound(const string& filename) { + scoped_ptr input(source_tree_.Open(filename)); + EXPECT_TRUE(input == NULL); + } + + DiskSourceTree source_tree_; + + // Paths of two on-disk directories to use during the test. + vector dirnames_; +}; + +TEST_F(DiskSourceTreeTest, MapRoot) { + // Test opening a file in a directory that is mapped to the root of the + // source tree. + AddFile(dirnames_[0] + "/foo", "Hello World!"); + source_tree_.MapPath("", dirnames_[0]); + + ExpectFileContents("foo", "Hello World!"); + ExpectFileNotFound("bar"); +} + +TEST_F(DiskSourceTreeTest, MapDirectory) { + // Test opening a file in a directory that is mapped to somewhere other + // than the root of the source tree. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + source_tree_.MapPath("baz", dirnames_[0]); + + ExpectFileContents("baz/foo", "Hello World!"); + ExpectFileNotFound("baz/bar"); + ExpectFileNotFound("foo"); + ExpectFileNotFound("bar"); + + // Non-canonical file names should not work. + ExpectFileNotFound("baz//foo"); + ExpectFileNotFound("baz/../baz/foo"); + ExpectFileNotFound("baz/./foo"); + ExpectFileNotFound("baz/foo/"); +} + +TEST_F(DiskSourceTreeTest, NoParent) { + // Test that we cannot open files in a parent of a mapped directory. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + AddSubdir(dirnames_[0] + "/bar"); + AddFile(dirnames_[0] + "/bar/baz", "Blah."); + source_tree_.MapPath("", dirnames_[0] + "/bar"); + + ExpectFileContents("baz", "Blah."); + ExpectFileNotFound("../foo"); + ExpectFileNotFound("../bar/baz"); +} + +TEST_F(DiskSourceTreeTest, MapFile) { + // Test opening a file that is mapped directly into the source tree. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + source_tree_.MapPath("foo", dirnames_[0] + "/foo"); + + ExpectFileContents("foo", "Hello World!"); + ExpectFileNotFound("bar"); +} + +TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { + // Test mapping and searching multiple directories. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + AddFile(dirnames_[1] + "/foo", "This file should be hidden."); + AddFile(dirnames_[1] + "/bar", "Goodbye World!"); + source_tree_.MapPath("", dirnames_[0]); + source_tree_.MapPath("", dirnames_[1]); + + ExpectFileContents("foo", "Hello World!"); + ExpectFileContents("bar", "Goodbye World!"); + ExpectFileNotFound("baz"); +} + +TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { + // Test that directories are always searched in order, even when a latter + // directory is more-specific than a former one. + + // Create the "bar" directory so we can put a file in it. + ASSERT_TRUE(File::CreateDir((dirnames_[0] + "/bar").c_str(), + DEFAULT_FILE_MODE)); + + // Add files and map paths. + AddFile(dirnames_[0] + "/bar/foo", "Hello World!"); + AddFile(dirnames_[1] + "/foo", "This file should be hidden."); + source_tree_.MapPath("", dirnames_[0]); + source_tree_.MapPath("bar", dirnames_[1]); + + // Check. + ExpectFileContents("bar/foo", "Hello World!"); +} + +TEST_F(DiskSourceTreeTest, DiskFileToVirtualFile) { + // Test DiskFileToVirtualFile. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + AddFile(dirnames_[1] + "/foo", "This file should be hidden."); + source_tree_.MapPath("bar", dirnames_[0]); + source_tree_.MapPath("bar", dirnames_[1]); + + string virtual_file; + string shadowing_disk_file; + + EXPECT_EQ(DiskSourceTree::NO_MAPPING, + source_tree_.DiskFileToVirtualFile( + "/foo", &virtual_file, &shadowing_disk_file)); + + EXPECT_EQ(DiskSourceTree::SHADOWED, + source_tree_.DiskFileToVirtualFile( + dirnames_[1] + "/foo", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("bar/foo", virtual_file); + EXPECT_EQ(dirnames_[0] + "/foo", shadowing_disk_file); + + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + dirnames_[1] + "/baz", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("bar/baz", virtual_file); + + EXPECT_EQ(DiskSourceTree::SUCCESS, + source_tree_.DiskFileToVirtualFile( + dirnames_[0] + "/foo", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("bar/foo", virtual_file); +} + +TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) { + // Test handling of "..", ".", etc. in DiskFileToVirtualFile(). + + source_tree_.MapPath("dir1", ".."); + source_tree_.MapPath("dir2", "../../foo"); + source_tree_.MapPath("dir3", "./foo/bar/."); + source_tree_.MapPath("dir4", "."); + source_tree_.MapPath("", "/qux"); + source_tree_.MapPath("dir5", "/quux/"); + + string virtual_file; + string shadowing_disk_file; + + // "../.." should not be considered to be under "..". + EXPECT_EQ(DiskSourceTree::NO_MAPPING, + source_tree_.DiskFileToVirtualFile( + "../../baz", &virtual_file, &shadowing_disk_file)); + + // "/foo" is not mapped (it should not be misintepreted as being under "."). + EXPECT_EQ(DiskSourceTree::NO_MAPPING, + source_tree_.DiskFileToVirtualFile( + "/foo", &virtual_file, &shadowing_disk_file)); + +#ifdef WIN32 + // "C:\foo" is not mapped (it should not be misintepreted as being under "."). + EXPECT_EQ(DiskSourceTree::NO_MAPPING, + source_tree_.DiskFileToVirtualFile( + "C:\\foo", &virtual_file, &shadowing_disk_file)); +#endif // WIN32 + + // But "../baz" should be. + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "../baz", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("dir1/baz", virtual_file); + + // "../../foo/baz" is under "../../foo". + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "../../foo/baz", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("dir2/baz", virtual_file); + + // "foo/./bar/baz" is under "./foo/bar/.". + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "foo/bar/baz", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("dir3/baz", virtual_file); + + // "bar" is under ".". + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "bar", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("dir4/bar", virtual_file); + + // "/qux/baz" is under "/qux". + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "/qux/baz", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("baz", virtual_file); + + // "/quux/bar" is under "/quux". + EXPECT_EQ(DiskSourceTree::CANNOT_OPEN, + source_tree_.DiskFileToVirtualFile( + "/quux/bar", &virtual_file, &shadowing_disk_file)); + EXPECT_EQ("dir5/bar", virtual_file); +} + +TEST_F(DiskSourceTreeTest, VirtualFileToDiskFile) { + // Test VirtualFileToDiskFile. + + AddFile(dirnames_[0] + "/foo", "Hello World!"); + AddFile(dirnames_[1] + "/foo", "This file should be hidden."); + AddFile(dirnames_[1] + "/quux", "This file should not be hidden."); + source_tree_.MapPath("bar", dirnames_[0]); + source_tree_.MapPath("bar", dirnames_[1]); + + // Existent files, shadowed and non-shadowed case. + string disk_file; + EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", &disk_file)); + EXPECT_EQ(dirnames_[0] + "/foo", disk_file); + EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/quux", &disk_file)); + EXPECT_EQ(dirnames_[1] + "/quux", disk_file); + + // Nonexistent file in existent directory and vice versa. + string not_touched = "not touched"; + EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("bar/baz", ¬_touched)); + EXPECT_EQ("not touched", not_touched); + EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", ¬_touched)); + EXPECT_EQ("not touched", not_touched); + + // Accept NULL as output parameter. + EXPECT_TRUE(source_tree_.VirtualFileToDiskFile("bar/foo", NULL)); + EXPECT_FALSE(source_tree_.VirtualFileToDiskFile("baz/foo", NULL)); +} + +} // namespace + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc new file mode 100644 index 000000000..60b4f2ac6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -0,0 +1,236 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 compiler { +namespace java { + +string EscapeJavadoc(const string& input) { + string result; + result.reserve(input.size() * 2); + + char prev = '*'; + + for (string::size_type i = 0; i < input.size(); i++) { + char c = input[i]; + switch (c) { + case '*': + // Avoid "/*". + if (prev == '/') { + result.append("*"); + } else { + result.push_back(c); + } + break; + case '/': + // Avoid "*/". + if (prev == '*') { + result.append("/"); + } else { + result.push_back(c); + } + break; + case '@': + // "{@" starts Javadoc markup. + if (prev == '{') { + result.append("@"); + } else { + result.push_back(c); + } + break; + case '<': + // Avoid interpretation as HTML. + result.append("<"); + break; + case '>': + // Avoid interpretation as HTML. + result.append(">"); + break; + case '&': + // Avoid interpretation as HTML. + result.append("&"); + break; + case '\\': + // Java interprets Unicode escape sequences anywhere! + result.append("\"); + break; + default: + result.push_back(c); + break; + } + + prev = c; + } + + return result; +} + +static void WriteDocCommentBodyForLocation( + io::Printer* printer, const SourceLocation& location) { + string comments = location.leading_comments.empty() ? + location.trailing_comments : location.leading_comments; + if (!comments.empty()) { + // TODO(kenton): Ideally we should parse the comment text as Markdown and + // write it back as HTML, but this requires a Markdown parser. For now + // we just use
 to get fixed-width text formatting.
+
+    // If the comment itself contains block comment start or end markers,
+    // HTML-escape them so that they don't accidentally close the doc comment.
+    comments = EscapeJavadoc(comments);
+
+    vector lines;
+    SplitStringAllowEmpty(comments, "\n", &lines);
+    while (!lines.empty() && lines.back().empty()) {
+      lines.pop_back();
+    }
+
+    printer->Print(
+        " *\n"
+        " * 
\n");
+    for (int i = 0; i < lines.size(); i++) {
+      // Most lines should start with a space.  Watch out for lines that start
+      // with a /, since putting that right after the leading asterisk will
+      // close the comment.
+      if (!lines[i].empty() && lines[i][0] == '/') {
+        printer->Print(" * $line$\n", "line", lines[i]);
+      } else {
+        printer->Print(" *$line$\n", "line", lines[i]);
+      }
+    }
+    printer->Print(" * 
\n"); + } +} + +template +static void WriteDocCommentBody( + io::Printer* printer, const DescriptorType* descriptor) { + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + WriteDocCommentBodyForLocation(printer, location); + } +} + +static string FirstLineOf(const string& value) { + string result = value; + + string::size_type pos = result.find_first_of('\n'); + if (pos != string::npos) { + result.erase(pos); + } + + // If line ends in an opening brace, make it "{ ... }" so it looks nice. + if (!result.empty() && result[result.size() - 1] == '{') { + result.append(" ... }"); + } + + return result; +} + +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { + printer->Print( + "/**\n" + " * Protobuf type {@code $fullname$}\n", + "fullname", EscapeJavadoc(message->full_name())); + WriteDocCommentBody(printer, message); + printer->Print(" */\n"); +} + +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { + // In theory we should have slightly different comments for setters, getters, + // etc., but in practice everyone already knows the difference between these + // so it's redundant information. + + // We use the field declaration as the first line of the comment, e.g.: + // optional string foo = 5; + // This communicates a lot of information about the field in a small space. + // If the field is a group, the debug string might end with {. + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(field->DebugString()))); + WriteDocCommentBody(printer, field); + printer->Print(" */\n"); +} + +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { + printer->Print( + "/**\n" + " * Protobuf enum {@code $fullname$}\n", + "fullname", EscapeJavadoc(enum_->full_name())); + WriteDocCommentBody(printer, enum_); + printer->Print(" */\n"); +} + +void WriteEnumValueDocComment(io::Printer* printer, + const EnumValueDescriptor* value) { + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(value->DebugString()))); + WriteDocCommentBody(printer, value); + printer->Print(" */\n"); +} + +void WriteServiceDocComment(io::Printer* printer, + const ServiceDescriptor* service) { + printer->Print( + "/**\n" + " * Protobuf service {@code $fullname$}\n", + "fullname", EscapeJavadoc(service->full_name())); + WriteDocCommentBody(printer, service); + printer->Print(" */\n"); +} + +void WriteMethodDocComment(io::Printer* printer, + const MethodDescriptor* method) { + printer->Print( + "/**\n" + " * $def$\n", + "def", EscapeJavadoc(FirstLineOf(method->DebugString()))); + WriteDocCommentBody(printer, method); + printer->Print(" */\n"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h new file mode 100644 index 000000000..7244d9bac --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment.h @@ -0,0 +1,69 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_DOC_COMMENT_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ + +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message); +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field); +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_); +void WriteEnumValueDocComment(io::Printer* printer, + const EnumValueDescriptor* value); +void WriteServiceDocComment(io::Printer* printer, + const ServiceDescriptor* service); +void WriteMethodDocComment(io::Printer* printer, + const MethodDescriptor* method); + +// Exposed for testing only. +LIBPROTOC_EXPORT string EscapeJavadoc(const string& input); + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc new file mode 100644 index 000000000..28b6d8b49 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc @@ -0,0 +1,66 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +TEST(JavaDocCommentTest, Escaping) { + EXPECT_EQ("foo /* bar */ baz", EscapeJavadoc("foo /* bar */ baz")); + EXPECT_EQ("foo /*/ baz", EscapeJavadoc("foo /*/ baz")); + EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}")); + EXPECT_EQ("<i>&</i>", EscapeJavadoc("&")); + EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar")); +} + +// TODO(kenton): It's hard to write a robust test of the doc comments -- we +// can only really compare the output against a golden value, which is a +// fairly tedious and fragile testing strategy. If we want to go that route, +// it probably makes sense to bite the bullet and write a test that compares +// the whole generated output for unittest.proto against a golden value, with +// a very simple script that can be run to regenerate it with the latest code. +// This would mean that updates to the golden file would have to be included +// in any change to the code generator, which would actually be fairly useful +// as it allows the reviewer to see clearly how the generated code is +// changing. + +} // namespace +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.cc new file mode 100644 index 000000000..cfed815f8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.cc @@ -0,0 +1,271 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) + : descriptor_(descriptor) { + for (int i = 0; i < descriptor_->value_count(); i++) { + const EnumValueDescriptor* value = descriptor_->value(i); + const EnumValueDescriptor* canonical_value = + descriptor_->FindValueByNumber(value->number()); + + if (value == canonical_value) { + canonical_values_.push_back(value); + } else { + Alias alias; + alias.value = value; + alias.canonical_value = canonical_value; + aliases_.push_back(alias); + } + } +} + +EnumGenerator::~EnumGenerator() {} + +void EnumGenerator::Generate(io::Printer* printer) { + WriteEnumDocComment(printer, descriptor_); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.ProtocolMessageEnum {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.Internal.EnumLite {\n", + "classname", descriptor_->name()); + } + printer->Indent(); + + for (int i = 0; i < canonical_values_.size(); i++) { + map vars; + vars["name"] = canonical_values_[i]->name(); + vars["index"] = SimpleItoa(canonical_values_[i]->index()); + vars["number"] = SimpleItoa(canonical_values_[i]->number()); + WriteEnumValueDocComment(printer, canonical_values_[i]); + printer->Print(vars, + "$name$($index$, $number$),\n"); + } + + printer->Print( + ";\n" + "\n"); + + // ----------------------------------------------------------------- + + for (int i = 0; i < aliases_.size(); i++) { + map vars; + vars["classname"] = descriptor_->name(); + vars["name"] = aliases_[i].value->name(); + vars["canonical_name"] = aliases_[i].canonical_value->name(); + WriteEnumValueDocComment(printer, aliases_[i].value); + printer->Print(vars, + "public static final $classname$ $name$ = $canonical_name$;\n"); + } + + for (int i = 0; i < descriptor_->value_count(); i++) { + map vars; + vars["name"] = descriptor_->value(i)->name(); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + WriteEnumValueDocComment(printer, descriptor_->value(i)); + printer->Print(vars, + "public static final int $name$_VALUE = $number$;\n"); + } + printer->Print("\n"); + + // ----------------------------------------------------------------- + + printer->Print( + "\n" + "public final int getNumber() { return value; }\n" + "\n" + "public static $classname$ valueOf(int value) {\n" + " switch (value) {\n", + "classname", descriptor_->name()); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < canonical_values_.size(); i++) { + printer->Print( + "case $number$: return $name$;\n", + "name", canonical_values_[i]->name(), + "number", SimpleItoa(canonical_values_[i]->number())); + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " default: return null;\n" + " }\n" + "}\n" + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.valueOf(number);\n" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); + + // ----------------------------------------------------------------- + // Reflection + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" + " getValueDescriptor() {\n" + " return getDescriptor().getValues().get(index);\n" + "}\n" + "public final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n" + "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptor() {\n"); + + // TODO(kenton): Cache statically? Note that we can't access descriptors + // at module init time because it wouldn't work with descriptor.proto, but + // we can cache the value the first time getDescriptor() is called. + if (descriptor_->containing_type() == NULL) { + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", ClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + } else { + printer->Print( + " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", + "parent", ClassName(descriptor_->containing_type()), + "index", SimpleItoa(descriptor_->index())); + } + + printer->Print( + "}\n" + "\n" + "private static final $classname$[] VALUES = ", + "classname", descriptor_->name()); + + if (CanUseEnumValues()) { + // If the constants we are going to output are exactly the ones we + // have declared in the Java enum in the same order, then we can use + // the values() method that the Java compiler automatically generates + // for every enum. + printer->Print("values();\n"); + } else { + printer->Print( + "{\n" + " "); + for (int i = 0; i < descriptor_->value_count(); i++) { + printer->Print("$name$, ", + "name", descriptor_->value(i)->name()); + } + printer->Print( + "\n" + "};\n"); + } + + printer->Print( + "\n" + "public static $classname$ valueOf(\n" + " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" + " if (desc.getType() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"EnumValueDescriptor is not for this type.\");\n" + " }\n" + " return VALUES[desc.getIndex()];\n" + "}\n" + "\n", + "classname", descriptor_->name()); + + // index is only used for reflection; lite implementation does not need it + printer->Print("private final int index;\n"); + } + + // ----------------------------------------------------------------- + + printer->Print( + "private final int value;\n\n" + "private $classname$(int index, int value) {\n", + "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(" this.index = index;\n"); + } + printer->Print( + " this.value = value;\n" + "}\n"); + + printer->Print( + "\n" + "// @@protoc_insertion_point(enum_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n\n"); +} + +bool EnumGenerator::CanUseEnumValues() { + if (canonical_values_.size() != descriptor_->value_count()) { + return false; + } + for (int i = 0; i < descriptor_->value_count(); i++) { + if (descriptor_->value(i)->name() != canonical_values_[i]->name()) { + return false; + } + } + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.h new file mode 100644 index 000000000..9a9e5742a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum.h @@ -0,0 +1,86 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_ENUM_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class EnumGenerator { + public: + explicit EnumGenerator(const EnumDescriptor* descriptor); + ~EnumGenerator(); + + void Generate(io::Printer* printer); + + private: + const EnumDescriptor* descriptor_; + + // The proto language allows multiple enum constants to have the same numeric + // value. Java, however, does not allow multiple enum constants to be + // considered equivalent. We treat the first defined constant for any + // given numeric value as "canonical" and the rest as aliases of that + // canonical value. + vector canonical_values_; + + struct Alias { + const EnumValueDescriptor* value; + const EnumValueDescriptor* canonical_value; + }; + vector aliases_; + + bool CanUseEnumValues(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc new file mode 100644 index 000000000..ec0b067ee --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc @@ -0,0 +1,603 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of +// repeat code between this and the other field types. +void SetEnumVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + map* variables) { + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = ClassName(descriptor->enum_type()); + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +EnumFieldGenerator:: +EnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); +} + +EnumFieldGenerator::~EnumFieldGenerator() {} + +int EnumFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int EnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void EnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void EnumFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $type$ $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $type$ $name$_ = $default$;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$;\n" + " $name$_ = $default$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void EnumFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void EnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); +} + +void EnumFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void EnumFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, + " $set_has_field_bit_message$;\n" + " $name$_ = value;\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for enums +} + +void EnumFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeEnum($number$, $name$_.getNumber());\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, $name$_.getNumber());\n" + "}\n"); +} + +void EnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result &&\n" + " (get$capitalized_name$() == other.get$capitalized_name$());\n"); +} + +void EnumFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n"); +} + +string EnumFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->enum_type()); +} + +// =================================================================== + +RepeatedEnumFieldGenerator:: +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); +} + +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} + +int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedEnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.util.List<$type$> $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize;\n"); + } +} + +void RepeatedEnumFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = java.util.Collections.emptyList();\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void RepeatedEnumFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. + printer->Print(variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + // Read and store the enum + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, + " if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$type$>();\n" + " $set_mutable_bit_parser$;\n" + " }\n" + " $name$_.add(value);\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + // Wrap GenerateParsingCode's contents with a while loop. + + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int oldLimit = input.pushLimit(length);\n" + "while(input.getBytesUntilLimit() > 0) {\n"); + printer->Indent(); + + GenerateParsingCode(printer); + + printer->Outdent(); + printer->Print(variables_, + "}\n" + "input.popLimit(oldLimit);\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnumNoTag($name$_.get(i).getNumber());\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnum($number$, $name$_.get(i).getNumber());\n" + "}\n"); + } +} + +void RepeatedEnumFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n" + "}\n"); + printer->Print( + "size += dataSize;\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeRawVarint32Size(dataSize);\n" + "}"); + } else { + printer->Print(variables_, + "size += $tag_size$ * $name$_.size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n" + "}\n"); +} + +string RepeatedEnumFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->enum_type()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.h new file mode 100644 index 000000000..90fae6394 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_enum_field.h @@ -0,0 +1,123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class EnumFieldGenerator : public FieldGenerator { + public: + explicit EnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~EnumFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); +}; + +class RepeatedEnumFieldGenerator : public FieldGenerator { + public: + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~RepeatedEnumFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.cc new file mode 100644 index 000000000..921fe6589 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.cc @@ -0,0 +1,218 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +const char* TypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} + +ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) + : descriptor_(descriptor) { + if (descriptor_->extension_scope() != NULL) { + scope_ = ClassName(descriptor_->extension_scope()); + } else { + scope_ = ClassName(descriptor_->file()); + } +} + +ExtensionGenerator::~ExtensionGenerator() {} + +// Initializes the vars referenced in the generated code templates. +void InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + map* vars_pointer) { + map &vars = *vars_pointer; + vars["scope"] = scope; + vars["name"] = UnderscoresToCamelCase(descriptor); + vars["containing_type"] = ClassName(descriptor->containing_type()); + vars["number"] = SimpleItoa(descriptor->number()); + vars["constant_name"] = FieldConstantName(descriptor); + vars["index"] = SimpleItoa(descriptor->index()); + vars["default"] = + descriptor->is_repeated() ? "" : DefaultValue(descriptor); + vars["type_constant"] = TypeName(GetType(descriptor)); + vars["packed"] = descriptor->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; + + JavaType java_type = GetJavaType(descriptor); + string singular_type; + switch (java_type) { + case JAVATYPE_MESSAGE: + singular_type = ClassName(descriptor->message_type()); + vars["prototype"] = singular_type + ".getDefaultInstance()"; + break; + case JAVATYPE_ENUM: + singular_type = ClassName(descriptor->enum_type()); + vars["enum_map"] = singular_type + ".internalGetValueMap()"; + break; + default: + singular_type = BoxedPrimitiveTypeName(java_type); + break; + } + vars["type"] = descriptor->is_repeated() ? + "java.util.List<" + singular_type + ">" : singular_type; + vars["singular_type"] = singular_type; +} + +void ExtensionGenerator::Generate(io::Printer* printer) { + map vars; + InitTemplateVars(descriptor_, scope_, &vars); + printer->Print(vars, + "public static final int $constant_name$ = $number$;\n"); + + WriteFieldDocComment(printer, descriptor_); + if (HasDescriptorMethods(descriptor_->file())) { + // Non-lite extensions + if (descriptor_->extension_scope() == NULL) { + // Non-nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newFileScopedGeneratedExtension(\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } else { + // Nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newMessageScopedGeneratedExtension(\n" + " $scope$.getDefaultInstance(),\n" + " $index$,\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } + } else { + // Lite extensions + if (descriptor_->is_repeated()) { + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newRepeatedGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$);\n"); + } else { + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newSingularGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + } + } +} + +void ExtensionGenerator::GenerateNonNestedInitializationCode( + io::Printer* printer) { + if (descriptor_->extension_scope() == NULL && + HasDescriptorMethods(descriptor_->file())) { + // Only applies to non-nested, non-lite extensions. + printer->Print( + "$name$.internalInit(descriptor.getExtensions().get($index$));\n", + "name", UnderscoresToCamelCase(descriptor_), + "index", SimpleItoa(descriptor_->index())); + } +} + +void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { + printer->Print( + "registry.add($scope$.$name$);\n", + "scope", scope_, + "name", UnderscoresToCamelCase(descriptor_)); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.h new file mode 100644 index 000000000..009ed9ffa --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_extension.h @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_EXTENSION_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ + +#include + +#include + +namespace google { +namespace protobuf { + class FieldDescriptor; // descriptor.h + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +// Generates code for an extension, which may be within the scope of some +// message or may be at file scope. This is much simpler than FieldGenerator +// since extensions are just simple identifiers with interesting types. +class ExtensionGenerator { + public: + explicit ExtensionGenerator(const FieldDescriptor* descriptor); + ~ExtensionGenerator(); + + void Generate(io::Printer* printer); + void GenerateNonNestedInitializationCode(io::Printer* printer); + void GenerateRegistrationCode(io::Printer* printer); + + private: + const FieldDescriptor* descriptor_; + string scope_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.cc new file mode 100644 index 000000000..c7d433c8e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.cc @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +FieldGenerator::~FieldGenerator() {} + +void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const { + // Reaching here indicates a bug. Cases are: + // - This FieldGenerator should support packing, but this method should be + // overridden. + // - This FieldGenerator doesn't support packing, and this method should + // never have been called. + GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " + << "called on field generator that does not support packing."; +} + +FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_( + new scoped_ptr[descriptor->field_count()]), + extension_generators_( + new scoped_ptr[descriptor->extension_count()]) { + + // Construct all the FieldGenerators and assign them bit indices for their + // bit fields. + int messageBitIndex = 0; + int builderBitIndex = 0; + for (int i = 0; i < descriptor->field_count(); i++) { + FieldGenerator* generator = MakeGenerator(descriptor->field(i), + messageBitIndex, builderBitIndex); + field_generators_[i].reset(generator); + messageBitIndex += generator->GetNumBitsForMessage(); + builderBitIndex += generator->GetNumBitsForBuilder(); + } + for (int i = 0; i < descriptor->extension_count(); i++) { + FieldGenerator* generator = MakeGenerator(descriptor->extension(i), + messageBitIndex, builderBitIndex); + extension_generators_[i].reset(generator); + messageBitIndex += generator->GetNumBitsForMessage(); + builderBitIndex += generator->GetNumBitsForBuilder(); + } +} + +FieldGenerator* FieldGeneratorMap::MakeGenerator( + const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) { + if (field->is_repeated()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + return new RepeatedMessageFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_ENUM: + return new RepeatedEnumFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_STRING: + return new RepeatedStringFieldGenerator( + field, messageBitIndex, builderBitIndex); + default: + return new RepeatedPrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex); + } + } else { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + return new MessageFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_ENUM: + return new EnumFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_STRING: + return new StringFieldGenerator( + field, messageBitIndex, builderBitIndex); + default: + return new PrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex); + } + } +} + +FieldGeneratorMap::~FieldGeneratorMap() {} + +const FieldGenerator& FieldGeneratorMap::get( + const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + +const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { + return *extension_generators_[index]; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.h new file mode 100644 index 000000000..4dd0efd60 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_field.h @@ -0,0 +1,109 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class FieldGenerator { + public: + FieldGenerator() {} + virtual ~FieldGenerator(); + + virtual int GetNumBitsForMessage() const = 0; + virtual int GetNumBitsForBuilder() const = 0; + virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; + virtual void GenerateMembers(io::Printer* printer) const = 0; + virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; + virtual void GenerateInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0; + virtual void GenerateMergingCode(io::Printer* printer) const = 0; + virtual void GenerateBuildingCode(io::Printer* printer) const = 0; + virtual void GenerateParsingCode(io::Printer* printer) const = 0; + virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; + virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; + virtual void GenerateSerializationCode(io::Printer* printer) const = 0; + virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; + virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) + const = 0; + + virtual void GenerateEqualsCode(io::Printer* printer) const = 0; + virtual void GenerateHashCode(io::Printer* printer) const = 0; + + virtual string GetBoxedType() const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); +}; + +// Convenience class which constructs FieldGenerators for a Descriptor. +class FieldGeneratorMap { + public: + explicit FieldGeneratorMap(const Descriptor* descriptor); + ~FieldGeneratorMap(); + + const FieldGenerator& get(const FieldDescriptor* field) const; + const FieldGenerator& get_extension(int index) const; + + private: + const Descriptor* descriptor_; + scoped_array > field_generators_; + scoped_array > extension_generators_; + + static FieldGenerator* MakeGenerator(const FieldDescriptor* field, + int messageBitIndex, int builderBitIndex); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.cc new file mode 100644 index 000000000..f43e55001 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.cc @@ -0,0 +1,490 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + + +// Recursively searches the given message to collect extensions. +// Returns true if all the extensions can be recognized. The extensions will be +// appended in to the extensions parameter. +// Returns false when there are unknown fields, in which case the data in the +// extensions output parameter is not reliable and should be discarded. +bool CollectExtensions(const Message& message, + vector* extensions) { + const Reflection* reflection = message.GetReflection(); + + // There are unknown fields that could be extensions, thus this call fails. + if (reflection->GetUnknownFields(message).field_count() > 0) return false; + + vector fields; + reflection->ListFields(message, &fields); + + for (int i = 0; i < fields.size(); i++) { + if (fields[i]->is_extension()) extensions->push_back(fields[i]); + + if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) { + if (fields[i]->is_repeated()) { + int size = reflection->FieldSize(message, fields[i]); + for (int j = 0; j < size; j++) { + const Message& sub_message = + reflection->GetRepeatedMessage(message, fields[i], j); + if (!CollectExtensions(sub_message, extensions)) return false; + } + } else { + const Message& sub_message = reflection->GetMessage(message, fields[i]); + if (!CollectExtensions(sub_message, extensions)) return false; + } + } + } + + return true; +} + +// Finds all extensions in the given message and its sub-messages. If the +// message contains unknown fields (which could be extensions), then those +// extensions are defined in alternate_pool. +// The message will be converted to a DynamicMessage backed by alternate_pool +// in order to handle this case. +void CollectExtensions(const FileDescriptorProto& file_proto, + const DescriptorPool& alternate_pool, + vector* extensions, + const string& file_data) { + if (!CollectExtensions(file_proto, extensions)) { + // There are unknown fields in the file_proto, which are probably + // extensions. We need to parse the data into a dynamic message based on the + // builder-pool to find out all extensions. + const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName( + file_proto.GetDescriptor()->full_name()); + GOOGLE_CHECK(file_proto_desc) + << "Find unknown fields in FileDescriptorProto when building " + << file_proto.name() + << ". It's likely that those fields are custom options, however, " + "descriptor.proto is not in the transitive dependencies. " + "This normally should not happen. Please report a bug."; + DynamicMessageFactory factory; + scoped_ptr dynamic_file_proto( + factory.GetPrototype(file_proto_desc)->New()); + GOOGLE_CHECK(dynamic_file_proto.get() != NULL); + GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data)); + + // Collect the extensions again from the dynamic message. There should be no + // more unknown fields this time, i.e. all the custom options should be + // parsed as extensions now. + extensions->clear(); + GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) + << "Find unknown fields in FileDescriptorProto when building " + << file_proto.name() + << ". It's likely that those fields are custom options, however, " + "those options cannot be recognized in the builder pool. " + "This normally should not happen. Please report a bug."; + } +} + + +} // namespace + +FileGenerator::FileGenerator(const FileDescriptor* file) + : file_(file), + java_package_(FileJavaPackage(file)), + classname_(FileClassName(file)) { +} + +FileGenerator::~FileGenerator() {} + +bool FileGenerator::Validate(string* error) { + // Check that no class name matches the file's class name. This is a common + // problem that leads to Java compile errors that can be hard to understand. + // It's especially bad when using the java_multiple_files, since we would + // end up overwriting the outer class with one of the inner ones. + + bool found_conflict = false; + for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) { + if (file_->enum_type(i)->name() == classname_) { + found_conflict = true; + } + } + for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) { + if (file_->message_type(i)->name() == classname_) { + found_conflict = true; + } + } + for (int i = 0; i < file_->service_count() && !found_conflict; i++) { + if (file_->service(i)->name() == classname_) { + found_conflict = true; + } + } + + if (found_conflict) { + error->assign(file_->name()); + error->append( + ": Cannot generate Java output because the file's outer class name, \""); + error->append(classname_); + error->append( + "\", matches the name of one of the types declared inside it. " + "Please either rename the type or use the java_outer_classname " + "option to specify a different outer class name for the .proto file."); + return false; + } + + return true; +} + +void FileGenerator::Generate(io::Printer* printer) { + // We don't import anything because we refer to all classes by their + // fully-qualified names in the generated source. + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + if (!java_package_.empty()) { + printer->Print( + "package $package$;\n" + "\n", + "package", java_package_); + } + printer->Print( + "public final class $classname$ {\n" + " private $classname$() {}\n", + "classname", classname_); + printer->Indent(); + + // ----------------------------------------------------------------- + + printer->Print( + "public static void registerAllExtensions(\n" + " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n", + "lite", HasDescriptorMethods(file_) ? "" : "Lite"); + + printer->Indent(); + + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer); + } + + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator(file_->message_type(i)) + .GenerateExtensionRegistrationCode(printer); + } + + printer->Outdent(); + printer->Print( + "}\n"); + + // ----------------------------------------------------------------- + + if (!file_->options().java_multiple_files()) { + for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator(file_->enum_type(i)).Generate(printer); + } + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); + } + if (HasGenericServices(file_)) { + for (int i = 0; i < file_->service_count(); i++) { + ServiceGenerator(file_->service(i)).Generate(printer); + } + } + } + + // Extensions must be generated in the outer class since they are values, + // not classes. + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator(file_->extension(i)).Generate(printer); + } + + // Static variables. + for (int i = 0; i < file_->message_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer); + } + + printer->Print("\n"); + + if (HasDescriptorMethods(file_)) { + GenerateEmbeddedDescriptor(printer); + } else { + printer->Print( + "static {\n"); + printer->Indent(); + + for (int i = 0; i < file_->message_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); + } + + printer->Outdent(); + printer->Print( + "}\n"); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(outer_class_scope)\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. We unfortunately have to put it in + // a string literal, not a byte array, because apparently using a literal + // byte array causes the Java compiler to generate *instructions* to + // initialize each and every byte of the array, e.g. as if you typed: + // b[0] = 123; b[1] = 456; b[2] = 789; + // This makes huge bytecode files and can easily hit the compiler's internal + // code size limits (error "code to large"). String literals are apparently + // embedded raw, which is what we want. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + + string file_data; + file_proto.SerializeToString(&file_data); + + printer->Print( + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " getDescriptor() {\n" + " return descriptor;\n" + "}\n" + "private static com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n" + " java.lang.String[] descriptorData = {\n"); + printer->Indent(); + printer->Indent(); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + if (i > 0) { + // Every 400 lines, start a new string literal, in order to avoid the + // 64k length limit. + if (i % 400 == 0) { + printer->Print(",\n"); + } else { + printer->Print(" +\n"); + } + } + printer->Print("\"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + + printer->Outdent(); + printer->Print("\n};\n"); + + // ----------------------------------------------------------------- + // Create the InternalDescriptorAssigner. + + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner assigner =\n" + " new com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner() {\n" + " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" + " com.google.protobuf.Descriptors.FileDescriptor root) {\n" + " descriptor = root;\n"); + + printer->Indent(); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < file_->message_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); + } + for (int i = 0; i < file_->extension_count(); i++) { + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(file_->extension(i)) + .GenerateNonNestedInitializationCode(printer); + } + + // Proto compiler builds a DescriptorPool, which holds all the descriptors to + // generate, when processing the ".proto" files. We call this DescriptorPool + // the parsed pool (a.k.a. file_->pool()). + // + // Note that when users try to extend the (.*)DescriptorProto in their + // ".proto" files, it does not affect the pre-built FileDescriptorProto class + // in proto compiler. When we put the descriptor data in the file_proto, those + // extensions become unknown fields. + // + // Now we need to find out all the extension value to the (.*)DescriptorProto + // in the file_proto message, and prepare an ExtensionRegistry to return. + // + // To find those extensions, we need to parse the data into a dynamic message + // of the FileDescriptor based on the builder-pool, then we can use + // reflections to find all extension fields + vector extensions; + CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + + if (extensions.size() > 0) { + // Must construct an ExtensionRegistry containing all existing extensions + // and return it. + printer->Print( + "com.google.protobuf.ExtensionRegistry registry =\n" + " com.google.protobuf.ExtensionRegistry.newInstance();\n"); + for (int i = 0; i < extensions.size(); i++) { + ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer); + } + printer->Print( + "return registry;\n"); + } else { + printer->Print( + "return null;\n"); + } + + printer->Outdent(); + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " };\n"); + + // ----------------------------------------------------------------- + // Invoke internalBuildGeneratedFileFrom() to build the file. + + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalBuildGeneratedFileFrom(descriptorData,\n" + " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + + for (int i = 0; i < file_->dependency_count(); i++) { + if (ShouldIncludeDependency(file_->dependency(i))) { + printer->Print( + " $dependency$.getDescriptor(),\n", + "dependency", ClassName(file_->dependency(i))); + } + } + + printer->Print( + " }, assigner);\n"); + + printer->Outdent(); + printer->Print( + "}\n"); +} + +template +static void GenerateSibling(const string& package_dir, + const string& java_package, + const DescriptorClass* descriptor, + GeneratorContext* context, + vector* file_list, + const string& name_suffix, + void (GeneratorClass::*pfn)(io::Printer* printer)) { + string filename = package_dir + descriptor->name() + name_suffix + ".java"; + file_list->push_back(filename); + + scoped_ptr output(context->Open(filename)); + io::Printer printer(output.get(), '$'); + + printer.Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", descriptor->file()->name()); + if (!java_package.empty()) { + printer.Print( + "package $package$;\n" + "\n", + "package", java_package); + } + + GeneratorClass generator(descriptor); + (generator.*pfn)(&printer); +} + +void FileGenerator::GenerateSiblings(const string& package_dir, + GeneratorContext* context, + vector* file_list) { + if (file_->options().java_multiple_files()) { + for (int i = 0; i < file_->enum_type_count(); i++) { + GenerateSibling(package_dir, java_package_, + file_->enum_type(i), + context, file_list, "", + &EnumGenerator::Generate); + } + for (int i = 0; i < file_->message_type_count(); i++) { + GenerateSibling(package_dir, java_package_, + file_->message_type(i), + context, file_list, "OrBuilder", + &MessageGenerator::GenerateInterface); + GenerateSibling(package_dir, java_package_, + file_->message_type(i), + context, file_list, "", + &MessageGenerator::Generate); + } + if (HasGenericServices(file_)) { + for (int i = 0; i < file_->service_count(); i++) { + GenerateSibling(package_dir, java_package_, + file_->service(i), + context, file_list, "", + &ServiceGenerator::Generate); + } + } + } +} + +bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) { + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.h new file mode 100644 index 000000000..599114626 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_file.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_FILE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + class FileDescriptor; // descriptor.h + namespace io { + class Printer; // printer.h + } + namespace compiler { + class GeneratorContext; // code_generator.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class FileGenerator { + public: + explicit FileGenerator(const FileDescriptor* file); + ~FileGenerator(); + + // Checks for problems that would otherwise lead to cryptic compile errors. + // Returns true if there are no problems, or writes an error description to + // the given string and returns false otherwise. + bool Validate(string* error); + + void Generate(io::Printer* printer); + + // If we aren't putting everything into one file, this will write all the + // files other than the outer file (i.e. one for each message, enum, and + // service type). + void GenerateSiblings(const string& package_dir, + GeneratorContext* generator_context, + vector* file_list); + + const string& java_package() { return java_package_; } + const string& classname() { return classname_; } + + + private: + // Returns whether the dependency should be included in the output file. + // Always returns true for opensource, but used internally at Google to help + // improve compatibility with version 1 of protocol buffers. + bool ShouldIncludeDependency(const FileDescriptor* descriptor); + + const FileDescriptor* file_; + string java_package_; + string classname_; + + + void GenerateEmbeddedDescriptor(io::Printer* printer); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.cc new file mode 100644 index 000000000..e6c79abcd --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.cc @@ -0,0 +1,128 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + + +JavaGenerator::JavaGenerator() {} +JavaGenerator::~JavaGenerator() {} + +bool JavaGenerator::Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + // ----------------------------------------------------------------- + // parse generator options + + // Name a file where we will write a list of generated file names, one + // per line. + string output_list_file; + + + vector > options; + ParseGeneratorParameter(parameter, &options); + + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "output_list_file") { + output_list_file = options[i].second; + } else { + *error = "Unknown generator option: " + options[i].first; + return false; + } + } + + // ----------------------------------------------------------------- + + + if (file->options().optimize_for() == FileOptions::LITE_RUNTIME && + file->options().java_generate_equals_and_hash()) { + *error = "The \"java_generate_equals_and_hash\" option is incompatible " + "with \"optimize_for = LITE_RUNTIME\". You must optimize for " + "SPEED or CODE_SIZE if you want to use this option."; + return false; + } + + FileGenerator file_generator(file); + if (!file_generator.Validate(error)) { + return false; + } + + string package_dir = JavaPackageToDir(file_generator.java_package()); + + vector all_files; + + string java_filename = package_dir; + java_filename += file_generator.classname(); + java_filename += ".java"; + all_files.push_back(java_filename); + + // Generate main java file. + scoped_ptr output( + context->Open(java_filename)); + io::Printer printer(output.get(), '$'); + file_generator.Generate(&printer); + + // Generate sibling files. + file_generator.GenerateSiblings(package_dir, context, &all_files); + + // Generate output list if requested. + if (!output_list_file.empty()) { + // Generate output list. This is just a simple text file placed in a + // deterministic location which lists the .java files being generated. + scoped_ptr srclist_raw_output( + context->Open(output_list_file)); + io::Printer srclist_printer(srclist_raw_output.get(), '$'); + for (int i = 0; i < all_files.size(); i++) { + srclist_printer.Print("$filename$\n", "filename", all_files[i]); + } + } + + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.h new file mode 100644 index 000000000..888b8d85e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_generator.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Generates Java code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +// CodeGenerator implementation which generates Java code. If you create your +// own protocol compiler binary and you want it to support Java output, you +// can do so by registering an instance of this CodeGenerator with the +// CommandLineInterface in your main() function. +class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { + public: + JavaGenerator(); + ~JavaGenerator(); + + // implements CodeGenerator ---------------------------------------- + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.cc new file mode 100644 index 000000000..cf241b8a5 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.cc @@ -0,0 +1,500 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +const char kThickSeparator[] = + "// ===================================================================\n"; +const char kThinSeparator[] = + "// -------------------------------------------------------------------\n"; + +namespace { + +const char* kDefaultPackage = ""; + +const string& FieldName(const FieldDescriptor* field) { + // Groups are hacky: The name of the field is just the lower-cased name + // of the group type. In Java, though, we would like to retain the original + // capitalization of the type name. + if (GetType(field) == FieldDescriptor::TYPE_GROUP) { + return field->message_type()->name(); + } else { + return field->name(); + } +} + +string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { + string result; + // Note: I distrust ctype.h due to locales. + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + if (cap_next_letter) { + result += input[i] + ('A' - 'a'); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if ('A' <= input[i] && input[i] <= 'Z') { + if (i == 0 && !cap_next_letter) { + // Force first letter to lower-case unless explicitly told to + // capitalize it. + result += input[i] + ('a' - 'A'); + } else { + // Capital letters after the first are left as-is. + result += input[i]; + } + cap_next_letter = false; + } else if ('0' <= input[i] && input[i] <= '9') { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + } + } + return result; +} + +} // namespace + +string UnderscoresToCamelCase(const FieldDescriptor* field) { + return UnderscoresToCamelCaseImpl(FieldName(field), false); +} + +string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { + return UnderscoresToCamelCaseImpl(FieldName(field), true); +} + +string UnderscoresToCamelCase(const MethodDescriptor* method) { + return UnderscoresToCamelCaseImpl(method->name(), false); +} + +string StripProto(const string& filename) { + if (HasSuffixString(filename, ".protodevel")) { + return StripSuffixString(filename, ".protodevel"); + } else { + return StripSuffixString(filename, ".proto"); + } +} + +string FileClassName(const FileDescriptor* file) { + if (file->options().has_java_outer_classname()) { + return file->options().java_outer_classname(); + } else { + string basename; + string::size_type last_slash = file->name().find_last_of('/'); + if (last_slash == string::npos) { + basename = file->name(); + } else { + basename = file->name().substr(last_slash + 1); + } + return UnderscoresToCamelCaseImpl(StripProto(basename), true); + } +} + +string FileJavaPackage(const FileDescriptor* file) { + string result; + + if (file->options().has_java_package()) { + result = file->options().java_package(); + } else { + result = kDefaultPackage; + if (!file->package().empty()) { + if (!result.empty()) result += '.'; + result += file->package(); + } + } + + + return result; +} + +string JavaPackageToDir(string package_name) { + string package_dir = + StringReplace(package_name, ".", "/", true); + if (!package_dir.empty()) package_dir += "/"; + return package_dir; +} + +string ToJavaName(const string& full_name, const FileDescriptor* file) { + string result; + if (file->options().java_multiple_files()) { + result = FileJavaPackage(file); + } else { + result = ClassName(file); + } + if (!result.empty()) { + result += '.'; + } + if (file->package().empty()) { + result += full_name; + } else { + // Strip the proto package from full_name since we've replaced it with + // the Java package. + result += full_name.substr(file->package().size() + 1); + } + return result; +} + +string ClassName(const Descriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} + +string ClassName(const EnumDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} + +string ClassName(const ServiceDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} + +string ClassName(const FileDescriptor* descriptor) { + string result = FileJavaPackage(descriptor); + if (!result.empty()) result += '.'; + result += FileClassName(descriptor); + return result; +} + +string FieldConstantName(const FieldDescriptor *field) { + string name = field->name() + "_FIELD_NUMBER"; + UpperString(&name); + return name; +} + +FieldDescriptor::Type GetType(const FieldDescriptor* field) { + return field->type(); +} + +JavaType GetJavaType(const FieldDescriptor* field) { + switch (GetType(field)) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SFIXED32: + return JAVATYPE_INT; + + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SFIXED64: + return JAVATYPE_LONG; + + case FieldDescriptor::TYPE_FLOAT: + return JAVATYPE_FLOAT; + + case FieldDescriptor::TYPE_DOUBLE: + return JAVATYPE_DOUBLE; + + case FieldDescriptor::TYPE_BOOL: + return JAVATYPE_BOOLEAN; + + case FieldDescriptor::TYPE_STRING: + return JAVATYPE_STRING; + + case FieldDescriptor::TYPE_BYTES: + return JAVATYPE_BYTES; + + case FieldDescriptor::TYPE_ENUM: + return JAVATYPE_ENUM; + + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + return JAVATYPE_MESSAGE; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return JAVATYPE_INT; +} + +const char* BoxedPrimitiveTypeName(JavaType type) { + switch (type) { + case JAVATYPE_INT : return "java.lang.Integer"; + case JAVATYPE_LONG : return "java.lang.Long"; + case JAVATYPE_FLOAT : return "java.lang.Float"; + case JAVATYPE_DOUBLE : return "java.lang.Double"; + case JAVATYPE_BOOLEAN: return "java.lang.Boolean"; + case JAVATYPE_STRING : return "java.lang.String"; + case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; + case JAVATYPE_ENUM : return NULL; + case JAVATYPE_MESSAGE: return NULL; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +bool AllAscii(const string& text) { + for (int i = 0; i < text.size(); i++) { + if ((text[i] & 0x80) != 0) { + return false; + } + } + return true; +} + +string DefaultValue(const FieldDescriptor* field) { + // Switch on CppType since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return SimpleItoa(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + // Need to print as a signed int since Java has no unsigned. + return SimpleItoa(static_cast(field->default_value_uint32())); + case FieldDescriptor::CPPTYPE_INT64: + return SimpleItoa(field->default_value_int64()) + "L"; + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(static_cast(field->default_value_uint64())) + + "L"; + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value = field->default_value_double(); + if (value == numeric_limits::infinity()) { + return "Double.POSITIVE_INFINITY"; + } else if (value == -numeric_limits::infinity()) { + return "Double.NEGATIVE_INFINITY"; + } else if (value != value) { + return "Double.NaN"; + } else { + return SimpleDtoa(value) + "D"; + } + } + case FieldDescriptor::CPPTYPE_FLOAT: { + float value = field->default_value_float(); + if (value == numeric_limits::infinity()) { + return "Float.POSITIVE_INFINITY"; + } else if (value == -numeric_limits::infinity()) { + return "Float.NEGATIVE_INFINITY"; + } else if (value != value) { + return "Float.NaN"; + } else { + return SimpleFtoa(value) + "F"; + } + } + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_STRING: + if (GetType(field) == FieldDescriptor::TYPE_BYTES) { + if (field->has_default_value()) { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } else { + return "com.google.protobuf.ByteString.EMPTY"; + } + } else { + if (AllAscii(field->default_value_string())) { + // All chars are ASCII. In this case CEscape() works fine. + return "\"" + CEscape(field->default_value_string()) + "\""; + } else { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } + } + + case FieldDescriptor::CPPTYPE_ENUM: + return ClassName(field->enum_type()) + "." + + field->default_value_enum()->name(); + + case FieldDescriptor::CPPTYPE_MESSAGE: + return ClassName(field->message_type()) + ".getDefaultInstance()"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + +bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { + // Switch on CppType since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0L; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0L; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0.0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0.0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + return false; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* bit_masks[] = { + "0x00000001", + "0x00000002", + "0x00000004", + "0x00000008", + "0x00000010", + "0x00000020", + "0x00000040", + "0x00000080", + + "0x00000100", + "0x00000200", + "0x00000400", + "0x00000800", + "0x00001000", + "0x00002000", + "0x00004000", + "0x00008000", + + "0x00010000", + "0x00020000", + "0x00040000", + "0x00080000", + "0x00100000", + "0x00200000", + "0x00400000", + "0x00800000", + + "0x01000000", + "0x02000000", + "0x04000000", + "0x08000000", + "0x10000000", + "0x20000000", + "0x40000000", + "0x80000000", +}; + +string GetBitFieldName(int index) { + string varName = "bitField"; + varName += SimpleItoa(index); + varName += "_"; + return varName; +} + +string GetBitFieldNameForBit(int bitIndex) { + return GetBitFieldName(bitIndex / 32); +} + +namespace { + +string GenerateGetBitInternal(const string& prefix, int bitIndex) { + string varName = prefix + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = "((" + varName + " & " + mask + ") == " + mask + ")"; + return result; +} + +string GenerateSetBitInternal(const string& prefix, int bitIndex) { + string varName = prefix + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " |= " + mask; + return result; +} + +} // namespace + +string GenerateGetBit(int bitIndex) { + return GenerateGetBitInternal("", bitIndex); +} + +string GenerateSetBit(int bitIndex) { + return GenerateSetBitInternal("", bitIndex); +} + +string GenerateClearBit(int bitIndex) { + string varName = GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " = (" + varName + " & ~" + mask + ")"; + return result; +} + +string GenerateGetBitFromLocal(int bitIndex) { + return GenerateGetBitInternal("from_", bitIndex); +} + +string GenerateSetBitToLocal(int bitIndex) { + return GenerateSetBitInternal("to_", bitIndex); +} + +string GenerateGetBitMutableLocal(int bitIndex) { + return GenerateGetBitInternal("mutable_", bitIndex); +} + +string GenerateSetBitMutableLocal(int bitIndex) { + return GenerateSetBitInternal("mutable_", bitIndex); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.h new file mode 100644 index 000000000..3937f069b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_helpers.h @@ -0,0 +1,220 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +// Commonly-used separator comments. Thick is a line of '=', thin is a line +// of '-'. +extern const char kThickSeparator[]; +extern const char kThinSeparator[]; + +// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes +// "fooBarBaz" or "FooBarBaz", respectively. +string UnderscoresToCamelCase(const FieldDescriptor* field); +string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); + +// Similar, but for method names. (Typically, this merely has the effect +// of lower-casing the first letter of the name.) +string UnderscoresToCamelCase(const MethodDescriptor* method); + +// Strips ".proto" or ".protodevel" from the end of a filename. +string StripProto(const string& filename); + +// Gets the unqualified class name for the file. Each .proto file becomes a +// single Java class, with all its contents nested in that class. +string FileClassName(const FileDescriptor* file); + +// Returns the file's Java package name. +string FileJavaPackage(const FileDescriptor* file); + +// Returns output directory for the given package name. +string JavaPackageToDir(string package_name); + +// Converts the given fully-qualified name in the proto namespace to its +// fully-qualified name in the Java namespace, given that it is in the given +// file. +string ToJavaName(const string& full_name, const FileDescriptor* file); + +// These return the fully-qualified class name corresponding to the given +// descriptor. +string ClassName(const Descriptor* descriptor); +string ClassName(const EnumDescriptor* descriptor); +string ClassName(const ServiceDescriptor* descriptor); +string ClassName(const FileDescriptor* descriptor); + +inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) { + return ToJavaName(descriptor->full_name(), descriptor->file()); +} + +// Get the unqualified name that should be used for a field's field +// number constant. +string FieldConstantName(const FieldDescriptor *field); + +// Returns the type of the FieldDescriptor. +// This does nothing interesting for the open source release, but is used for +// hacks that improve compatability with version 1 protocol buffers at Google. +FieldDescriptor::Type GetType(const FieldDescriptor* field); + +enum JavaType { + JAVATYPE_INT, + JAVATYPE_LONG, + JAVATYPE_FLOAT, + JAVATYPE_DOUBLE, + JAVATYPE_BOOLEAN, + JAVATYPE_STRING, + JAVATYPE_BYTES, + JAVATYPE_ENUM, + JAVATYPE_MESSAGE +}; + +JavaType GetJavaType(const FieldDescriptor* field); + +// Get the fully-qualified class name for a boxed primitive type, e.g. +// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message +// types. +const char* BoxedPrimitiveTypeName(JavaType type); + +string DefaultValue(const FieldDescriptor* field); +bool IsDefaultValueJavaDefault(const FieldDescriptor* field); + +// Does this message class keep track of unknown fields? +inline bool HasUnknownFields(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + +// Does this message class have generated parsing, serialization, and other +// standard methods for which reflection-based fallback implementations exist? +inline bool HasGeneratedMethods(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::CODE_SIZE; +} + +// Does this message have specialized equals() and hashCode() methods? +inline bool HasEqualsAndHashCode(const Descriptor* descriptor) { + return descriptor->file()->options().java_generate_equals_and_hash(); +} + +// Does this message class have descriptor and reflection methods? +inline bool HasDescriptorMethods(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { + return descriptor->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + +inline bool HasNestedBuilders(const Descriptor* descriptor) { + // The proto-lite version doesn't support nested builders. + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + +// Should we generate generic services for this file? +inline bool HasGenericServices(const FileDescriptor *file) { + return file->service_count() > 0 && + file->options().optimize_for() != FileOptions::LITE_RUNTIME && + file->options().java_generic_services(); +} + + +// Methods for shared bitfields. + +// Gets the name of the shared bitfield for the given index. +string GetBitFieldName(int index); + +// Gets the name of the shared bitfield for the given bit index. +// Effectively, GetBitFieldName(bitIndex / 32) +string GetBitFieldNameForBit(int bitIndex); + +// Generates the java code for the expression that returns the boolean value +// of the bit of the shared bitfields for the given bit index. +// Example: "((bitField1_ & 0x04) == 0x04)" +string GenerateGetBit(int bitIndex); + +// Generates the java code for the expression that sets the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ | 0x04)" +string GenerateSetBit(int bitIndex); + +// Generates the java code for the expression that clears the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ & ~0x04)" +string GenerateClearBit(int bitIndex); + +// Does the same as GenerateGetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "((from_bitField1_ & 0x04) == 0x04)" +string GenerateGetBitFromLocal(int bitIndex); + +// Does the same as GenerateSetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "to_bitField1_ = (to_bitField1_ | 0x04)" +string GenerateSetBitToLocal(int bitIndex); + +// Does the same as GenerateGetBit but operates on the bit field on a local +// variable. This is used by the parsing constructor to record if a repeated +// field is mutable. +// Example: "((mutable_bitField1_ & 0x04) == 0x04)" +string GenerateGetBitMutableLocal(int bitIndex); + +// Does the same as GenerateSetBit but operates on the bit field on a local +// variable. This is used by the parsing constructor to record if a repeated +// field is mutable. +// Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" +string GenerateSetBitMutableLocal(int bitIndex); + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.cc new file mode 100644 index 000000000..9322e242b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.cc @@ -0,0 +1,1435 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { + // Print the field's proto-syntax definition as a comment. We don't want to + // print group bodies so we cut off after the first line. + string def = field->DebugString(); + printer->Print("// $def$\n", + "def", def.substr(0, def.find_first_of('\n'))); +} + +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Get an identifier that uniquely identifies this type within the file. +// This is used to declare static variables related to this type at the +// outermost file scope. +string UniqueFileScopeIdentifier(const Descriptor* descriptor) { + return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its isInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +static bool HasRequiredFields( + const Descriptor* type, + hash_set* already_seen) { + if (already_seen->count(type) > 0) { + // The type is already in cache. This means that either: + // a. The type has no required fields. + // b. We are in the midst of checking if the type has required fields, + // somewhere up the stack. In this case, we know that if the type + // has any required fields, they'll be found when we return to it, + // and the whole call to HasRequiredFields() will return true. + // Therefore, we don't have to check if this type has required fields + // here. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (GetJavaType(field) == JAVATYPE_MESSAGE) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + + return false; +} + +static bool HasRequiredFields(const Descriptor* type) { + hash_set already_seen; + return HasRequiredFields(type, &already_seen); +} + +} // namespace + +// =================================================================== + +MessageGenerator::MessageGenerator(const Descriptor* descriptor) + : descriptor_(descriptor), + field_generators_(descriptor) { +} + +MessageGenerator::~MessageGenerator() {} + +void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is + // used in the construction of descriptors, we have a tricky bootstrapping + // problem. To help control static initialization order, we make sure all + // descriptors and other static data that depends on them are members of + // the outermost class in the file. This way, they will be initialized in + // a deterministic order. + + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } + if (descriptor_->file()->options().java_multiple_files()) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } + + // The descriptor for this type. + printer->Print(vars, + "$private$static com.google.protobuf.Descriptors.Descriptor\n" + " internal_$identifier$_descriptor;\n"); + + // And the FieldAccessorTable. + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); + } + + // Generate static members for all nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(descriptor_->nested_type(i)) + .GenerateStaticVariables(printer); + } +} + +void MessageGenerator::GenerateStaticVariableInitializers( + io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } + + // The descriptor for this type. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " getDescriptor().getMessageTypes().get($index$);\n"); + } else { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + } + + // And the FieldAccessorTable. + printer->Print(vars, + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print( + "\"$field_name$\", ", + "field_name", + UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + } + printer->Print( + "});\n"); + } + + // Generate static member initializers for all nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(descriptor_->nested_type(i)) + .GenerateStaticVariableInitializers(printer); + } +} + +// =================================================================== + +void MessageGenerator::GenerateInterface(io::Printer* printer) { + if (descriptor_->extension_range_count() > 0) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public interface $classname$OrBuilder extends\n" + " com.google.protobuf.GeneratedMessage.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public interface $classname$OrBuilder extends \n" + " com.google.protobuf.GeneratedMessageLite.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "classname", descriptor_->name()); + } + } else { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public interface $classname$OrBuilder\n" + " extends com.google.protobuf.MessageOrBuilder {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public interface $classname$OrBuilder\n" + " extends com.google.protobuf.MessageLiteOrBuilder {\n", + "classname", descriptor_->name()); + } + } + + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + PrintFieldComment(printer, descriptor_->field(i)); + field_generators_.get(descriptor_->field(i)) + .GenerateInterfaceMembers(printer); + } + printer->Outdent(); + + printer->Print("}\n"); +} + +// =================================================================== + +void MessageGenerator::Generate(io::Printer* printer) { + bool is_own_file = + descriptor_->containing_type() == NULL && + descriptor_->file()->options().java_multiple_files(); + + WriteMessageDocComment(printer, descriptor_); + + // The builder_type stores the super type name of the nested Builder class. + string builder_type; + if (descriptor_->extension_range_count() > 0) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements $classname$OrBuilder {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", + ClassName(descriptor_)); + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$> implements $classname$OrBuilder {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", + ClassName(descriptor_)); + } + } else { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage\n" + " implements $classname$OrBuilder {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + builder_type = "com.google.protobuf.GeneratedMessage.Builder"; + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite\n" + " implements $classname$OrBuilder {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; + } + } + printer->Indent(); + // Using builder_type, instead of Builder, prevents the Builder class from + // being loaded into PermGen space when the default instance is created. + // This optimizes the PermGen space usage for clients that do not modify + // messages. + printer->Print( + "// Use $classname$.newBuilder() to construct.\n" + "private $classname$($buildertype$ builder) {\n" + " super(builder);\n" + "$set_unknown_fields$\n" + "}\n", + "classname", descriptor_->name(), + "buildertype", builder_type, + "set_unknown_fields", HasUnknownFields(descriptor_) + ? " this.unknownFields = builder.getUnknownFields();" : ""); + printer->Print( + // Used when constructing the default instance, which cannot be initialized + // immediately because it may cyclically refer to other default instances. + "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n" + "\n" + "private static final $classname$ defaultInstance;\n" + "public static $classname$ getDefaultInstance() {\n" + " return defaultInstance;\n" + "}\n" + "\n" + "public $classname$ getDefaultInstanceForType() {\n" + " return defaultInstance;\n" + "}\n" + "\n", + "classname", descriptor_->name(), + "set_default_unknown_fields", HasUnknownFields(descriptor_) + ? " this.unknownFields =" + " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : ""); + + if (HasUnknownFields(descriptor_)) { + printer->Print( + "private final com.google.protobuf.UnknownFieldSet unknownFields;\n" + "" + "@java.lang.Override\n" + "public final com.google.protobuf.UnknownFieldSet\n" + " getUnknownFields() {\n" + " return this.unknownFields;\n" + "}\n"); + } + + if (HasGeneratedMethods(descriptor_)) { + GenerateParsingConstructor(printer); + } + + GenerateDescriptorMethods(printer); + GenerateParser(printer); + + // Nested types + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator(descriptor_->enum_type(i)).Generate(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); + } + + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + + // Fields + for (int i = 0; i < descriptor_->field_count(); i++) { + PrintFieldComment(printer, descriptor_->field(i)); + printer->Print("public static final int $constant_name$ = $number$;\n", + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", SimpleItoa(descriptor_->field(i)->number())); + field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); + printer->Print("\n"); + } + + // Called by the constructor, except in the case of the default instance, + // in which case this is called by static init code later on. + printer->Print("private void initFields() {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); + } + printer->Outdent(); + printer->Print("}\n"); + + if (HasGeneratedMethods(descriptor_)) { + GenerateIsInitialized(printer, MEMOIZE); + GenerateMessageSerializationMethods(printer); + } + + if (HasEqualsAndHashCode(descriptor_)) { + GenerateEqualsAndHashCode(printer); + } + + GenerateParseFromMethods(printer); + GenerateBuilder(printer); + + // Carefully initialize the default instance in such a way that it doesn't + // conflict with other initialization. + printer->Print( + "\n" + "static {\n" + " defaultInstance = new $classname$(true);\n" + " defaultInstance.initFields();\n" + "}\n" + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "classname", descriptor_->name(), + "full_name", descriptor_->full_name()); + + // Extensions must be declared after the defaultInstance is initialized + // because the defaultInstance is used by the extension to lazily retrieve + // the outer class's FileDescriptor. + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator(descriptor_->extension(i)).Generate(printer); + } + + printer->Outdent(); + printer->Print("}\n\n"); +} + + +// =================================================================== + +void MessageGenerator:: +GenerateMessageSerializationMethods(io::Printer* printer) { + scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); + + vector sorted_extensions; + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + printer->Print( + "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n"); + printer->Indent(); + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks for + // each packed field, just call getSerializedSize() up front for all messages. + // In most cases, getSerializedSize() will have already been called anyway by + // one of the wrapper writeTo() methods, making this call cheap. + printer->Print( + "getSerializedSize();\n"); + + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", + "classname", ClassName(descriptor_)); + } + } + + // Merge the fields and the extension ranges, both sorted by field number. + for (int i = 0, j = 0; + i < descriptor_->field_count() || j < sorted_extensions.size(); + ) { + if (i == descriptor_->field_count()) { + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + } else if (j == sorted_extensions.size()) { + GenerateSerializeOneField(printer, sorted_fields[i++]); + } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { + GenerateSerializeOneField(printer, sorted_fields[i++]); + } else { + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + } + } + + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "getUnknownFields().writeAsMessageSetTo(output);\n"); + } else { + printer->Print( + "getUnknownFields().writeTo(output);\n"); + } + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "private int memoizedSerializedSize = -1;\n" + "public int getSerializedSize() {\n" + " int size = memoizedSerializedSize;\n" + " if (size != -1) return size;\n" + "\n" + " size = 0;\n"); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); + } + + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += extensionsSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += extensionsSerializedSize();\n"); + } + } + + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += getUnknownFields().getSerializedSize();\n"); + } + } + + printer->Outdent(); + printer->Print( + " memoizedSerializedSize = size;\n" + " return size;\n" + "}\n" + "\n"); + + printer->Print( + "private static final long serialVersionUID = 0L;\n" + "@java.lang.Override\n" + "protected java.lang.Object writeReplace()\n" + " throws java.io.ObjectStreamException {\n" + " return super.writeReplace();\n" + "}\n" + "\n"); +} + +void MessageGenerator:: +GenerateParseFromMethods(io::Printer* printer) { + // Note: These are separate from GenerateMessageSerializationMethods() + // because they need to be generated even for messages that are optimized + // for code size. + printer->Print( + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(byte[] data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " byte[] data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseDelimitedFrom(input);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); +} + +void MessageGenerator::GenerateSerializeOneField( + io::Printer* printer, const FieldDescriptor* field) { + field_generators_.get(field).GenerateSerializationCode(printer); +} + +void MessageGenerator::GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range) { + printer->Print( + "extensionWriter.writeUntil($end$, output);\n", + "end", SimpleItoa(range->end)); +} + +// =================================================================== + +void MessageGenerator::GenerateBuilder(io::Printer* printer) { + printer->Print( + "public static Builder newBuilder() { return Builder.create(); }\n" + "public Builder newBuilderForType() { return newBuilder(); }\n" + "public static Builder newBuilder($classname$ prototype) {\n" + " return newBuilder().mergeFrom(prototype);\n" + "}\n" + "public Builder toBuilder() { return newBuilder(this); }\n" + "\n", + "classname", ClassName(descriptor_)); + + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "@java.lang.Override\n" + "protected Builder newBuilderForType(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " Builder builder = new Builder(parent);\n" + " return builder;\n" + "}\n"); + } + + WriteMessageDocComment(printer, descriptor_); + + if (descriptor_->extension_range_count() > 0) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" + " $classname$, Builder> implements $classname$OrBuilder {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" + " $classname$, Builder> implements $classname$OrBuilder {\n", + "classname", ClassName(descriptor_)); + } + } else { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.Builder\n" + " implements $classname$OrBuilder {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.Builder<\n" + " $classname$, Builder>\n" + " implements $classname$OrBuilder {\n", + "classname", ClassName(descriptor_)); + } + } + printer->Indent(); + + GenerateDescriptorMethods(printer); + GenerateCommonBuilderMethods(printer); + + if (HasGeneratedMethods(descriptor_)) { + GenerateIsInitialized(printer, DONT_MEMOIZE); + GenerateBuilderParsingMethods(printer); + } + + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + PrintFieldComment(printer, descriptor_->field(i)); + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderMembers(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(builder_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + if (!descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } + printer->Print( + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" + "}\n" + "\n", + "classname", ClassName(descriptor_), + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } +} + +// =================================================================== + +void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { + printer->Print( + "// Construct using $classname$.newBuilder()\n" + "private Builder() {\n" + " maybeForceBuilderInitialization();\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "private Builder(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " super(parent);\n" + " maybeForceBuilderInitialization();\n" + "}\n", + "classname", ClassName(descriptor_)); + } + + + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); + + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n"); + } else { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + "}\n"); + } + + printer->Print( + "private static Builder create() {\n" + " return new Builder();\n" + "}\n" + "\n" + "public Builder clear() {\n" + " super.clear();\n", + "classname", ClassName(descriptor_)); + + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + + printer->Outdent(); + + printer->Print( + " return this;\n" + "}\n" + "\n" + "public Builder clone() {\n" + " return create().mergeFrom(buildPartial());\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptorForType() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } + printer->Print( + "public $classname$ getDefaultInstanceForType() {\n" + " return $classname$.getDefaultInstance();\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + + // ----------------------------------------------------------------- + + printer->Print( + "public $classname$ build() {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" + " throw newUninitializedMessageException(result);\n" + " }\n" + " return result;\n" + "}\n" + "\n" + "public $classname$ buildPartial() {\n" + " $classname$ result = new $classname$(this);\n", + "classname", ClassName(descriptor_)); + + printer->Indent(); + + // Local vars for from and to bit fields to avoid accessing the builder and + // message over and over for these fields. Seems to provide a slight + // perforamance improvement in micro benchmark and this is also what proto1 + // code does. + int totalBuilderBits = 0; + int totalMessageBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldGenerator& field = field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + totalMessageBits += field.GetNumBitsForMessage(); + } + int totalBuilderInts = (totalBuilderBits + 31) / 32; + int totalMessageInts = (totalMessageBits + 31) / 32; + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("int to_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + + // Output generation code for each field. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); + } + + // Copy the bit field results to the generated message + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + + printer->Outdent(); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + " onBuilt();\n"); + } + + printer->Print( + " return result;\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + + // ----------------------------------------------------------------- + + if (HasGeneratedMethods(descriptor_)) { + // MergeFrom(Message other) requires the ability to distinguish the other + // messages type by its descriptor. + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public Builder mergeFrom(com.google.protobuf.Message other) {\n" + " if (other instanceof $classname$) {\n" + " return mergeFrom(($classname$)other);\n" + " } else {\n" + " super.mergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + } + + printer->Print( + "public Builder mergeFrom($classname$ other) {\n" + // Optimization: If other is the default instance, we know none of its + // fields are set so we can skip the merge. + " if (other == $classname$.getDefaultInstance()) return this;\n", + "classname", ClassName(descriptor_)); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer); + } + + printer->Outdent(); + + // if message type has extensions + if (descriptor_->extension_range_count() > 0) { + printer->Print( + " this.mergeExtensionFields(other);\n"); + } + + if (HasUnknownFields(descriptor_)) { + printer->Print( + " this.mergeUnknownFields(other.getUnknownFields());\n"); + } + + printer->Print( + " return this;\n" + "}\n" + "\n"); + } +} + +// =================================================================== + +void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { + printer->Print( + "public Builder mergeFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " $classname$ parsedMessage = null;\n" + " try {\n" + " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" + " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" + " throw e;\n" + " } finally {\n" + " if (parsedMessage != null) {\n" + " mergeFrom(parsedMessage);\n" + " }\n" + " }\n" + " return this;\n" + "}\n", + "classname", ClassName(descriptor_)); +} + +// =================================================================== + +void MessageGenerator::GenerateIsInitialized( + io::Printer* printer, UseMemoization useMemoization) { + bool memoization = useMemoization == MEMOIZE; + if (memoization) { + // Memoizes whether the protocol buffer is fully initialized (has all + // required fields). -1 means not yet computed. 0 means false and 1 means + // true. + printer->Print( + "private byte memoizedIsInitialized = -1;\n"); + } + printer->Print( + "public final boolean isInitialized() {\n"); + printer->Indent(); + + if (memoization) { + printer->Print( + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized != -1) return isInitialized == 1;\n" + "\n"); + } + + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_required()) { + printer->Print( + "if (!has$name$()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + } + } + + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type())) { + switch (field->label()) { + case FieldDescriptor::LABEL_REQUIRED: + printer->Print( + "if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + case FieldDescriptor::LABEL_OPTIONAL: + printer->Print( + "if (has$name$()) {\n" + " if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" + "}\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + case FieldDescriptor::LABEL_REPEATED: + printer->Print( + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" + "}\n", + "type", ClassName(field->message_type()), + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + break; + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if (!extensionsAreInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + } + + printer->Outdent(); + + if (memoization) { + printer->Print( + " memoizedIsInitialized = 1;\n"); + } + + printer->Print( + " return true;\n" + "}\n" + "\n"); +} + +// =================================================================== + +void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { + printer->Print( + "@java.lang.Override\n" + "public boolean equals(final java.lang.Object obj) {\n"); + printer->Indent(); + printer->Print( + "if (obj == this) {\n" + " return true;\n" + "}\n" + "if (!(obj instanceof $classname$)) {\n" + " return super.equals(obj);\n" + "}\n" + "$classname$ other = ($classname$) obj;\n" + "\n", + "classname", ClassName(descriptor_)); + + printer->Print("boolean result = true;\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated()) { + printer->Print( + "result = result && (has$name$() == other.has$name$());\n" + "if (has$name$()) {\n", + "name", UnderscoresToCapitalizedCamelCase(field)); + printer->Indent(); + } + field_generators_.get(field).GenerateEqualsCode(printer); + if (!field->is_repeated()) { + printer->Outdent(); + printer->Print( + "}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "result = result &&\n" + " getUnknownFields().equals(other.getUnknownFields());\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "result = result &&\n" + " getExtensionFields().equals(other.getExtensionFields());\n"); + } + } + printer->Print( + "return result;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + printer->Print( + "private int memoizedHashCode = 0;\n"); + printer->Print( + "@java.lang.Override\n" + "public int hashCode() {\n"); + printer->Indent(); + printer->Print( + "if (memoizedHashCode != 0) {\n"); + printer->Indent(); + printer->Print( + "return memoizedHashCode;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "int hash = 41;\n" + "hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated()) { + printer->Print( + "if (has$name$()) {\n", + "name", UnderscoresToCapitalizedCamelCase(field)); + printer->Indent(); + } + field_generators_.get(field).GenerateHashCode(printer); + if (!field->is_repeated()) { + printer->Outdent(); + printer->Print("}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "hash = hashFields(hash, getExtensionFields());\n"); + } + } + printer->Print( + "hash = (29 * hash) + getUnknownFields().hashCode();\n" + "memoizedHashCode = hash;\n" + "return hash;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); +} + +// =================================================================== + +void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator(descriptor_->extension(i)) + .GenerateRegistrationCode(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator(descriptor_->nested_type(i)) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { + scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); + + printer->Print( + "private $classname$(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n", + "classname", descriptor_->name()); + printer->Indent(); + + // Initialize all fields to default. + printer->Print( + "initFields();\n"); + + // Use builder bits to track mutable repeated fields. + int totalBuilderBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldGenerator& field = field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + } + int totalBuilderInts = (totalBuilderBits + 31) / 32; + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int mutable_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + + if (HasUnknownFields(descriptor_)) { + printer->Print( + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); + } + + printer->Print( + "try {\n"); + printer->Indent(); + + printer->Print( + "boolean done = false;\n" + "while (!done) {\n"); + printer->Indent(); + + printer->Print( + "int tag = input.readTag();\n" + "switch (tag) {\n"); + printer->Indent(); + + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n" + "default: {\n" + " if (!parseUnknownField(input,$unknown_fields$\n" + " extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n", + "unknown_fields", HasUnknownFields(descriptor_) + ? " unknownFields," : ""); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + uint32 tag = WireFormatLite::MakeTag(field->number(), + WireFormat::WireTypeForFieldType(field->type())); + + printer->Print( + "case $tag$: {\n", + "tag", SimpleItoa(tag)); + printer->Indent(); + + field_generators_.get(field).GenerateParsingCode(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + + if (field->is_packable()) { + // To make packed = true wire compatible, we generate parsing code from a + // packed version of this field regardless of field->options().packed(). + uint32 packed_tag = WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + printer->Print( + "case $tag$: {\n", + "tag", SimpleItoa(packed_tag)); + printer->Indent(); + + field_generators_.get(field).GenerateParsingCodeFromPacked(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + } + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // switch (tag) + "}\n"); // while (!done) + + printer->Outdent(); + printer->Print( + "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw e.setUnfinishedMessage(this);\n" + "} catch (java.io.IOException e) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this);\n" + "} finally {\n"); + printer->Indent(); + + // Make repeated field list immutable. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + field_generators_.get(field).GenerateParsingDoneCode(printer); + } + + // Make unknown fields immutable. + if (HasUnknownFields(descriptor_)) { + printer->Print( + "this.unknownFields = unknownFields.build();\n"); + } + + // Make extensions immutable. + printer->Print( + "makeExtensionsImmutable();\n"); + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // finally + "}\n"); +} + +// =================================================================== +void MessageGenerator::GenerateParser(io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.Parser<$classname$> PARSER =\n" + " new com.google.protobuf.AbstractParser<$classname$>() {\n", + "classname", descriptor_->name()); + printer->Indent(); + printer->Print( + "public $classname$ parsePartialFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n", + "classname", descriptor_->name()); + if (HasGeneratedMethods(descriptor_)) { + printer->Print( + " return new $classname$(input, extensionRegistry);\n", + "classname", descriptor_->name()); + } else { + // When parsing constructor isn't generated, use builder to parse messages. + // Note, will fallback to use reflection based mergeFieldFrom() in + // AbstractMessage.Builder. + printer->Indent(); + printer->Print( + "Builder builder = newBuilder();\n" + "try {\n" + " builder.mergeFrom(input, extensionRegistry);\n" + "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw e.setUnfinishedMessage(builder.buildPartial());\n" + "} catch (java.io.IOException e) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n" + "}\n" + "return builder.buildPartial();\n"); + printer->Outdent(); + } + printer->Print( + "}\n"); + printer->Outdent(); + printer->Print( + "};\n" + "\n"); + + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.h new file mode 100644 index 000000000..a30f02026 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message.h @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class MessageGenerator { + public: + explicit MessageGenerator(const Descriptor* descriptor); + ~MessageGenerator(); + + // All static variables have to be declared at the top-level of the file + // so that we can control initialization order, which is important for + // DescriptorProto bootstrapping to work. + void GenerateStaticVariables(io::Printer* printer); + + // Output code which initializes the static variables generated by + // GenerateStaticVariables(). + void GenerateStaticVariableInitializers(io::Printer* printer); + + // Generate the class itself. + void Generate(io::Printer* printer); + + // Generates the base interface that both the class and its builder implement + void GenerateInterface(io::Printer* printer); + + // Generate code to register all contained extensions with an + // ExtensionRegistry. + void GenerateExtensionRegistrationCode(io::Printer* printer); + + private: + enum UseMemoization { + MEMOIZE, + DONT_MEMOIZE + }; + + void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateParseFromMethods(io::Printer* printer); + void GenerateSerializeOneField(io::Printer* printer, + const FieldDescriptor* field); + void GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range); + + void GenerateBuilder(io::Printer* printer); + void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer); + void GenerateBuilderParsingMethods(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer, + UseMemoization useMemoization); + void GenerateEqualsAndHashCode(io::Printer* printer); + + void GenerateParser(io::Printer* printer); + void GenerateParsingConstructor(io::Printer* printer); + + const Descriptor* descriptor_; + FieldGeneratorMap field_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.cc new file mode 100644 index 000000000..b0b284f76 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.cc @@ -0,0 +1,974 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of +// repeat code between this and the other field types. +void SetMessageVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + map* variables) { + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = ClassName(descriptor->message_type()); + (*variables)["group_or_message"] = + (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? + "Group" : "Message"; + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +MessageFieldGenerator:: +MessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +MessageFieldGenerator::~MessageFieldGenerator() {} + +int MessageFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int MessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void MessageFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having a method specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); + } +} + +void MessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $type$ $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } +} + +void MessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void MessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + // Used when the builder is null. + "private $type$ $name$_ = $type$.getDefaultInstance();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$()", + + "return $name$_;\n", + + "return $name$Builder_.getMessage();\n", + + NULL); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$name$_ = value;\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(value);\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$name$_ = builderForValue.build();\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(builderForValue.build());\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($get_has_field_bit_builder$ &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n", + + "$name$Builder_.mergeFrom(value);\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = $type$.getDefaultInstance();\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "$clear_has_field_bit_builder$;\n" + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$;\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void MessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); +} + + +void MessageFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); +} + +void MessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + PrintNestedBuilderCondition(printer, + "$name$_ = $type$.getDefaultInstance();\n", + + "$name$Builder_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); +} + +void MessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " merge$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); +} + +void MessageFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + + PrintNestedBuilderCondition(printer, + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); +} + +void MessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($get_has_field_bit_message$) {\n" + " subBuilder = $name$_.toBuilder();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); + } else { + printer->Print(variables_, + "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + } + + printer->Print(variables_, + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom($name$_);\n" + " $name$_ = subBuilder.buildPartial();\n" + "}\n"); + printer->Print(variables_, + "$set_has_field_bit_message$;\n"); +} + +void MessageFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for messages. +} + +void MessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.write$group_or_message$($number$, $name$_);\n" + "}\n"); +} + +void MessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, $name$_);\n" + "}\n"); +} + +void MessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void MessageFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string MessageFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->message_type()); +} + +// =================================================================== + +RepeatedMessageFieldGenerator:: +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} + +int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedMessageFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having methods specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List \n" + " get$capitalized_name$OrBuilderList();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index);\n"); + } +} + +void RepeatedMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.util.List<$type$> $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + +} + +void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + // Used when the builder is null. + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n" + "\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // repeated field of type "Field" called "RepeatedField". + + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", + + "return java.util.Collections.unmodifiableList($name$_);\n", + "return $name$Builder_.getMessageList();\n", + + NULL); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public int get$capitalized_name$Count()", + + "return $name$_.size();\n", + "return $name$Builder_.getCount();\n", + + NULL); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$(int index)", + + "return $name$_.get(index);\n", + + "return $name$Builder_.getMessage(index);\n", + + NULL); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, value);\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", + "return this;\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(value);\n" + + "$on_changed$\n", + + "$name$Builder_.addMessage(value);\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, value);\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, value);\n", + + "return this;\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values)", + + "ensure$capitalized_name$IsMutable();\n" + "super.addAll(values, $name$_);\n" + "$on_changed$\n", + + "$name$Builder_.addAllMessages(values);\n", + + "return this;\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "return this;\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder remove$capitalized_name$(int index)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.remove(index);\n" + "$on_changed$\n", + + "$name$Builder_.remove(index);\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void RepeatedMessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + PrintNestedBuilderCondition(printer, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n", + + "$name$Builder_.clear();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations (non-nested builder case): + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + PrintNestedBuilderCondition(printer, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n", + + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$Builder_.isEmpty()) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " $name$Builder_ = \n" + " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n" + " get$capitalized_name$FieldBuilder() : null;\n" + " } else {\n" + " $name$Builder_.addAllMessages(other.$name$_);\n" + " }\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // The code below (non-nested builder case) ensures that the result has an + // immutable list. If our list is immutable, we can just reuse it. If not, + // we make it immutable. + PrintNestedBuilderCondition(printer, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry));\n"); + } else { + printer->Print(variables_, + "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); + } +} + +void RepeatedMessageFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$group_or_message$($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedMessageFieldGenerator::GetBoxedType() const { + return ClassName(descriptor_->message_type()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.h new file mode 100644 index 000000000..5c8078a15 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_message_field.h @@ -0,0 +1,136 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class MessageFieldGenerator : public FieldGenerator { + public: + explicit MessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~MessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; +}; + +class RepeatedMessageFieldGenerator : public FieldGenerator { + public: + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~RepeatedMessageFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_plugin_unittest.cc new file mode 100644 index 000000000..ccc94c9df --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// TODO(kenton): Share code with the versions of this test in other languages? +// It seemed like parameterizing it would add more complexity than it is +// worth. + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { +namespace { + +class TestGenerator : public CodeGenerator { + public: + TestGenerator() {} + ~TestGenerator() {} + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + string filename = "Test.java"; + TryInsert(filename, "outer_class_scope", context); + TryInsert(filename, "class_scope:foo.Bar", context); + TryInsert(filename, "class_scope:foo.Bar.Baz", context); + TryInsert(filename, "builder_scope:foo.Bar", context); + TryInsert(filename, "builder_scope:foo.Bar.Baz", context); + TryInsert(filename, "enum_scope:foo.Qux", context); + return true; + } + + void TryInsert(const string& filename, const string& insertion_point, + GeneratorContext* context) const { + scoped_ptr output( + context->OpenForInsert(filename, insertion_point)); + io::Printer printer(output.get(), '$'); + printer.Print("// inserted $name$\n", "name", insertion_point); + } +}; + +// This test verifies that all the expected insertion points exist. It does +// not verify that they are correctly-placed; that would require actually +// compiling the output which is a bit more than I care to do for this test. +TEST(JavaPluginTest, PluginTest) { + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "option java_package = \"\";\n" + "option java_outer_classname = \"Test\";\n" + "message Bar {\n" + " message Baz {}\n" + "}\n" + "enum Qux { BLAH = 1; }\n", + TestTempDir() + "/test.proto"); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + JavaGenerator java_generator; + TestGenerator test_generator; + cli.RegisterGenerator("--java_out", &java_generator, ""); + cli.RegisterGenerator("--test_out", &test_generator, ""); + + string proto_path = "-I" + TestTempDir(); + string java_out = "--java_out=" + TestTempDir(); + string test_out = "--test_out=" + TestTempDir(); + + const char* argv[] = { + "protoc", + proto_path.c_str(), + java_out.c_str(), + test_out.c_str(), + "test.proto" + }; + + EXPECT_EQ(0, cli.Run(5, argv)); +} + +} // namespace +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc new file mode 100644 index 000000000..0140e23f8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -0,0 +1,787 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +const char* PrimitiveTypeName(JavaType type) { + switch (type) { + case JAVATYPE_INT : return "int"; + case JAVATYPE_LONG : return "long"; + case JAVATYPE_FLOAT : return "float"; + case JAVATYPE_DOUBLE : return "double"; + case JAVATYPE_BOOLEAN: return "boolean"; + case JAVATYPE_STRING : return "java.lang.String"; + case JAVATYPE_BYTES : return "com.google.protobuf.ByteString"; + case JAVATYPE_ENUM : return NULL; + case JAVATYPE_MESSAGE: return NULL; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +bool IsReferenceType(JavaType type) { + switch (type) { + case JAVATYPE_INT : return false; + case JAVATYPE_LONG : return false; + case JAVATYPE_FLOAT : return false; + case JAVATYPE_DOUBLE : return false; + case JAVATYPE_BOOLEAN: return false; + case JAVATYPE_STRING : return true; + case JAVATYPE_BYTES : return true; + case JAVATYPE_ENUM : return true; + case JAVATYPE_MESSAGE: return true; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* GetCapitalizedType(const FieldDescriptor* field) { + switch (GetType(field)) { + case FieldDescriptor::TYPE_INT32 : return "Int32" ; + case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; + case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; + case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; + case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; + case FieldDescriptor::TYPE_INT64 : return "Int64" ; + case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; + case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; + case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; + case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT : return "Float" ; + case FieldDescriptor::TYPE_DOUBLE : return "Double" ; + case FieldDescriptor::TYPE_BOOL : return "Bool" ; + case FieldDescriptor::TYPE_STRING : return "String" ; + case FieldDescriptor::TYPE_BYTES : return "Bytes" ; + case FieldDescriptor::TYPE_ENUM : return "Enum" ; + case FieldDescriptor::TYPE_GROUP : return "Group" ; + case FieldDescriptor::TYPE_MESSAGE : return "Message" ; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + map* variables) { + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["field_type"] = (*variables)["type"]; + (*variables)["field_list_type"] = "java.util.List<" + + (*variables)["boxed_type"] + ">"; + (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? + "" : ("= " + DefaultValue(descriptor)); + (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + if (IsReferenceType(GetJavaType(descriptor))) { + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + } else { + (*variables)["null_check"] = ""; + } + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + int fixed_size = FixedSize(GetType(descriptor)); + if (fixed_size != -1) { + (*variables)["fixed_size"] = SimpleItoa(fixed_size); + } + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +PrimitiveFieldGenerator:: +PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} + +int PrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int PrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void PrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void PrimitiveFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_type$ $name$_;\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_type$ $name$_ $default_init$;\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$;\n"); + JavaType type = GetJavaType(descriptor_); + if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + } else { + printer->Print(variables_, + " $name$_ = $default$;\n"); + } + printer->Print(variables_, + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void PrimitiveFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_has_field_bit_message$;\n" + "$name$_ = input.read$capitalized_type$();\n"); +} + +void PrimitiveFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for primitives. +} + +void PrimitiveFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" + "}\n"); +} + +void PrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "result = result && (get$capitalized_name$()\n" + " == other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "result = result && (Float.floatToIntBits(get$capitalized_name$())" + " == Float.floatToIntBits(other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "result = result && (Double.doubleToLongBits(get$capitalized_name$())" + " == Double.doubleToLongBits(other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +void PrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$();\n"); + break; + + case JAVATYPE_LONG: + printer->Print(variables_, + "hash = (53 * hash) + hashLong(get$capitalized_name$());\n"); + break; + + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "hash = (53 * hash) + Float.floatToIntBits(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "hash = (53 * hash) + hashLong(\n" + " Double.doubleToLongBits(get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +string PrimitiveFieldGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); +} + +// =================================================================== + +RepeatedPrimitiveFieldGenerator:: +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} + +int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + + +void RepeatedPrimitiveFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_list_type$ $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // One field is the list and the bit field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private $field_list_type$ $name$_ = $empty_list$;\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. + printer->Print(variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(input.read$capitalized_type$());\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " $name$_.add(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$($number$, $name$_.get(i));\n" + "}\n"); + } +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + if (FixedSize(GetType(descriptor_)) == -1) { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); + } + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h new file mode 100644 index 000000000..1b5b6d95d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_primitive_field.h @@ -0,0 +1,123 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class PrimitiveFieldGenerator : public FieldGenerator { + public: + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~PrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); +}; + +class RepeatedPrimitiveFieldGenerator : public FieldGenerator { + public: + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~RepeatedPrimitiveFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.cc new file mode 100644 index 000000000..bcd803590 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.cc @@ -0,0 +1,453 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) + : descriptor_(descriptor) {} + +ServiceGenerator::~ServiceGenerator() {} + +void ServiceGenerator::Generate(io::Printer* printer) { + bool is_own_file = descriptor_->file()->options().java_multiple_files(); + WriteServiceDocComment(printer, descriptor_); + printer->Print( + "public $static$ abstract class $classname$\n" + " implements com.google.protobuf.Service {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + printer->Indent(); + + printer->Print( + "protected $classname$() {}\n\n", + "classname", descriptor_->name()); + + GenerateInterface(printer); + + GenerateNewReflectiveServiceMethod(printer); + GenerateNewReflectiveBlockingServiceMethod(printer); + + GenerateAbstractMethods(printer); + + // Generate getDescriptor() and getDescriptorForType(). + printer->Print( + "public static final\n" + " com.google.protobuf.Descriptors.ServiceDescriptor\n" + " getDescriptor() {\n" + " return $file$.getDescriptor().getServices().get($index$);\n" + "}\n", + "file", ClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + GenerateGetDescriptorForType(printer); + + // Generate more stuff. + GenerateCallMethod(printer); + GenerateGetPrototype(REQUEST, printer); + GenerateGetPrototype(RESPONSE, printer); + GenerateStub(printer); + GenerateBlockingStub(printer); + + // Add an insertion point. + printer->Print( + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n\n"); +} + +void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { + printer->Print( + "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n"); +} + +void ServiceGenerator::GenerateInterface(io::Printer* printer) { + printer->Print("public interface Interface {\n"); + printer->Indent(); + GenerateAbstractMethods(printer); + printer->Outdent(); + printer->Print("}\n\n"); +} + +void ServiceGenerator::GenerateNewReflectiveServiceMethod( + io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.Service newReflectiveService(\n" + " final Interface impl) {\n" + " return new $classname$() {\n", + "classname", descriptor_->name()); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + printer->Print("@java.lang.Override\n"); + GenerateMethodSignature(printer, method, IS_CONCRETE); + printer->Print( + " {\n" + " impl.$method$(controller, request, done);\n" + "}\n\n", + "method", UnderscoresToCamelCase(method)); + } + + printer->Outdent(); + printer->Print("};\n"); + printer->Outdent(); + printer->Print("}\n\n"); +} + +void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( + io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.BlockingService\n" + " newReflectiveBlockingService(final BlockingInterface impl) {\n" + " return new com.google.protobuf.BlockingService() {\n"); + printer->Indent(); + printer->Indent(); + + GenerateGetDescriptorForType(printer); + + GenerateCallBlockingMethod(printer); + GenerateGetPrototype(REQUEST, printer); + GenerateGetPrototype(RESPONSE, printer); + + printer->Outdent(); + printer->Print("};\n"); + printer->Outdent(); + printer->Print("}\n\n"); +} + +void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + WriteMethodDocComment(printer, method); + GenerateMethodSignature(printer, method, IS_ABSTRACT); + printer->Print(";\n\n"); + } +} + +void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { + printer->Print( + "\n" + "public final void callMethod(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method,\n" + " com.google.protobuf.RpcController controller,\n" + " com.google.protobuf.Message request,\n" + " com.google.protobuf.RpcCallback<\n" + " com.google.protobuf.Message> done) {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.callMethod() given method descriptor for wrong \" +\n" + " \"service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n"); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map vars; + vars["index"] = SimpleItoa(i); + vars["method"] = UnderscoresToCamelCase(method); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); + printer->Print(vars, + "case $index$:\n" + " this.$method$(controller, ($input$)request,\n" + " com.google.protobuf.RpcUtil.<$output$>specializeCallback(\n" + " done));\n" + " return;\n"); + } + + printer->Print( + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { + printer->Print( + "\n" + "public final com.google.protobuf.Message callBlockingMethod(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method,\n" + " com.google.protobuf.RpcController controller,\n" + " com.google.protobuf.Message request)\n" + " throws com.google.protobuf.ServiceException {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.callBlockingMethod() given method descriptor for \" +\n" + " \"wrong service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n"); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map vars; + vars["index"] = SimpleItoa(i); + vars["method"] = UnderscoresToCamelCase(method); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); + printer->Print(vars, + "case $index$:\n" + " return impl.$method$(controller, ($input$)request);\n"); + } + + printer->Print( + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, + io::Printer* printer) { + /* + * TODO(cpovirk): The exception message says "Service.foo" when it may be + * "BlockingService.foo." Consider fixing. + */ + printer->Print( + "public final com.google.protobuf.Message\n" + " get$request_or_response$Prototype(\n" + " com.google.protobuf.Descriptors.MethodDescriptor method) {\n" + " if (method.getService() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"Service.get$request_or_response$Prototype() given method \" +\n" + " \"descriptor for wrong service type.\");\n" + " }\n" + " switch(method.getIndex()) {\n", + "request_or_response", (which == REQUEST) ? "Request" : "Response"); + printer->Indent(); + printer->Indent(); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + map vars; + vars["index"] = SimpleItoa(i); + vars["type"] = ClassName( + (which == REQUEST) ? method->input_type() : method->output_type()); + printer->Print(vars, + "case $index$:\n" + " return $type$.getDefaultInstance();\n"); + } + + printer->Print( + "default:\n" + " throw new java.lang.AssertionError(\"Can't get here.\");\n"); + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateStub(io::Printer* printer) { + printer->Print( + "public static Stub newStub(\n" + " com.google.protobuf.RpcChannel channel) {\n" + " return new Stub(channel);\n" + "}\n" + "\n" + "public static final class Stub extends $classname$ implements Interface {" + "\n", + "classname", ClassName(descriptor_)); + printer->Indent(); + + printer->Print( + "private Stub(com.google.protobuf.RpcChannel channel) {\n" + " this.channel = channel;\n" + "}\n" + "\n" + "private final com.google.protobuf.RpcChannel channel;\n" + "\n" + "public com.google.protobuf.RpcChannel getChannel() {\n" + " return channel;\n" + "}\n"); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + printer->Print("\n"); + GenerateMethodSignature(printer, method, IS_CONCRETE); + printer->Print(" {\n"); + printer->Indent(); + + map vars; + vars["index"] = SimpleItoa(i); + vars["output"] = ClassName(method->output_type()); + printer->Print(vars, + "channel.callMethod(\n" + " getDescriptor().getMethods().get($index$),\n" + " controller,\n" + " request,\n" + " $output$.getDefaultInstance(),\n" + " com.google.protobuf.RpcUtil.generalizeCallback(\n" + " done,\n" + " $output$.class,\n" + " $output$.getDefaultInstance()));\n"); + + printer->Outdent(); + printer->Print("}\n"); + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); +} + +void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { + printer->Print( + "public static BlockingInterface newBlockingStub(\n" + " com.google.protobuf.BlockingRpcChannel channel) {\n" + " return new BlockingStub(channel);\n" + "}\n" + "\n"); + + printer->Print( + "public interface BlockingInterface {"); + printer->Indent(); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + GenerateBlockingMethodSignature(printer, method); + printer->Print(";\n"); + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + printer->Print( + "private static final class BlockingStub implements BlockingInterface {\n"); + printer->Indent(); + + printer->Print( + "private BlockingStub(com.google.protobuf.BlockingRpcChannel channel) {\n" + " this.channel = channel;\n" + "}\n" + "\n" + "private final com.google.protobuf.BlockingRpcChannel channel;\n"); + + for (int i = 0; i < descriptor_->method_count(); i++) { + const MethodDescriptor* method = descriptor_->method(i); + GenerateBlockingMethodSignature(printer, method); + printer->Print(" {\n"); + printer->Indent(); + + map vars; + vars["index"] = SimpleItoa(i); + vars["output"] = ClassName(method->output_type()); + printer->Print(vars, + "return ($output$) channel.callBlockingMethod(\n" + " getDescriptor().getMethods().get($index$),\n" + " controller,\n" + " request,\n" + " $output$.getDefaultInstance());\n"); + + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, + const MethodDescriptor* method, + IsAbstract is_abstract) { + map vars; + vars["name"] = UnderscoresToCamelCase(method); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); + vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : ""; + printer->Print(vars, + "public $abstract$ void $name$(\n" + " com.google.protobuf.RpcController controller,\n" + " $input$ request,\n" + " com.google.protobuf.RpcCallback<$output$> done)"); +} + +void ServiceGenerator::GenerateBlockingMethodSignature( + io::Printer* printer, + const MethodDescriptor* method) { + map vars; + vars["method"] = UnderscoresToCamelCase(method); + vars["input"] = ClassName(method->input_type()); + vars["output"] = ClassName(method->output_type()); + printer->Print(vars, + "\n" + "public $output$ $method$(\n" + " com.google.protobuf.RpcController controller,\n" + " $input$ request)\n" + " throws com.google.protobuf.ServiceException"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.h new file mode 100644 index 000000000..e07eebf75 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_service.h @@ -0,0 +1,113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_COMPILER_JAVA_SERVICE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__ + +#include +#include + +namespace google { +namespace protobuf { + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ServiceGenerator { + public: + explicit ServiceGenerator(const ServiceDescriptor* descriptor); + ~ServiceGenerator(); + + void Generate(io::Printer* printer); + + private: + + // Generate the getDescriptorForType() method. + void GenerateGetDescriptorForType(io::Printer* printer); + + // Generate a Java interface for the service. + void GenerateInterface(io::Printer* printer); + + // Generate newReflectiveService() method. + void GenerateNewReflectiveServiceMethod(io::Printer* printer); + + // Generate newReflectiveBlockingService() method. + void GenerateNewReflectiveBlockingServiceMethod(io::Printer* printer); + + // Generate abstract method declarations for all methods. + void GenerateAbstractMethods(io::Printer* printer); + + // Generate the implementation of Service.callMethod(). + void GenerateCallMethod(io::Printer* printer); + + // Generate the implementation of BlockingService.callBlockingMethod(). + void GenerateCallBlockingMethod(io::Printer* printer); + + // Generate the implementations of Service.get{Request,Response}Prototype(). + enum RequestOrResponse { REQUEST, RESPONSE }; + void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); + + // Generate a stub implementation of the service. + void GenerateStub(io::Printer* printer); + + // Generate a method signature, possibly abstract, without body or trailing + // semicolon. + enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; + void GenerateMethodSignature(io::Printer* printer, + const MethodDescriptor* method, + IsAbstract is_abstract); + + // Generate a blocking stub interface and implementation of the service. + void GenerateBlockingStub(io::Printer* printer); + + // Generate the method signature for one method of a blocking stub. + void GenerateBlockingMethodSignature(io::Printer* printer, + const MethodDescriptor* method); + + const ServiceDescriptor* descriptor_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +#endif // NET_PROTO2_COMPILER_JAVA_SERVICE_H__ +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.cc new file mode 100644 index 000000000..4815663b1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.cc @@ -0,0 +1,726 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + map* variables) { + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; + + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_init"] = ("= " + DefaultValue(descriptor)); + (*variables)["capitalized_type"] = "String"; + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated builders, one bit is used for whether the array is immutable. + (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); + + // For repeated fields, one bit is used for whether the array is immutable + // in the parsing constructor. + (*variables)["get_mutable_bit_parser"] = + GenerateGetBitMutableLocal(builderBitIndex); + (*variables)["set_mutable_bit_parser"] = + GenerateSetBitMutableLocal(builderBitIndex); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +StringFieldGenerator:: +StringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +StringFieldGenerator::~StringFieldGenerator() {} + +int StringFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int StringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +// A note about how strings are handled. This code used to just store a String +// in the Message. This had two issues: +// +// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// strings, but rather fields that were raw bytes incorrectly marked +// as strings in the proto file. This is common because in the proto1 +// syntax, string was the way to indicate bytes and C++ engineers can +// easily make this mistake without affecting the C++ API. By converting to +// strings immediately, some java code might corrupt these byte arrays as +// it passes through a java server even if the field was never accessed by +// application code. +// +// 2. There's a performance hit to converting between bytes and strings and +// it many cases, the field is never even read by the application code. This +// avoids unnecessary conversions in the common use cases. +// +// So now, the field for String is maintained as an Object reference which can +// either store a String or a ByteString. The code uses an instanceof check +// to see which one it has and converts to the other one if needed. It remembers +// the last value requested (in a thread safe manner) as this is most likely +// the one needed next. The thread safety is such that if two threads both +// convert the field because the changes made by each thread were not visible to +// the other, they may cause a conversion to happen more times than would +// otherwise be necessary. This was deemed better than adding synchronization +// overhead. It will not cause any corruption issues or affect the behavior of +// the API. The instanceof check is also highly optimized in the JVM and we +// decided it was better to reduce the memory overhead by not having two +// separate fields but rather use dynamic type checking. +// +// For single fields, the logic for this is done inside the generated code. For +// repeated fields, the logic is done in LazyStringArrayList and +// UnmodifiableLazyStringList. +void StringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes();\n"); +} + +void StringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n" + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n" + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_ $default_init$;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (!(ref instanceof java.lang.String)) {\n" + " java.lang.String s = ((com.google.protobuf.ByteString) ref)\n" + " .toStringUtf8();\n" + " $name$_ = s;\n" + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$;\n"); + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + printer->Print(variables_, + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void StringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void StringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); +} + +void StringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void StringFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_has_field_bit_message$;\n" + "$name$_ = input.readBytes();\n"); +} + +void StringFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for strings. +} + +void StringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void StringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string StringFieldGenerator::GetBoxedType() const { + return "java.lang.String"; +} + + +// =================================================================== + +RepeatedStringFieldGenerator:: +RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} + +int RepeatedStringFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedStringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List\n" + "get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index);\n"); +} + + +void RepeatedStringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_;\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } +} + +void RepeatedStringFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // One field is the list and the bit field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedStringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // The code below ensures that the result has an immutable list. If our + // list is immutable, we can just reuse it. If not, we make it immutable. + + printer->Print(variables_, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n" + " $name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(input.readBytes());\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " $name$.add(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_mutable_bit_parser$) {\n" + " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.getByteString(i));\n" + "}\n"); + } +} + +void RepeatedStringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + "}\n"); + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedStringFieldGenerator::GetBoxedType() const { + return "String"; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.h new file mode 100644 index 000000000..4f7532f44 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/java/java_string_field.h @@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class StringFieldGenerator : public FieldGenerator { + public: + explicit StringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~StringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); +}; + +class RepeatedStringFieldGenerator : public FieldGenerator { + public: + explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~RepeatedStringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/main.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/main.cc new file mode 100644 index 000000000..1afc5d611 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/main.cc @@ -0,0 +1,61 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include +#include +#include + + +int main(int argc, char* argv[]) { + + google::protobuf::compiler::CommandLineInterface cli; + cli.AllowPlugins("protoc-"); + + // Proto2 C++ + google::protobuf::compiler::cpp::CppGenerator cpp_generator; + cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator, + "Generate C++ header and source."); + + // Proto2 Java + google::protobuf::compiler::java::JavaGenerator java_generator; + cli.RegisterGenerator("--java_out", &java_generator, + "Generate Java source file."); + + + // Proto2 Python + google::protobuf::compiler::python::Generator py_generator; + cli.RegisterGenerator("--python_out", &py_generator, + "Generate Python source file."); + + return cli.Run(argc, argv); +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.cc new file mode 100644 index 000000000..0e35ed19c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.cc @@ -0,0 +1,241 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +// Returns the list of the names of files in all_files in the form of a +// comma-separated string. +string CommaSeparatedList(const vector all_files) { + vector names; + for (int i = 0; i < all_files.size(); i++) { + names.push_back(all_files[i]->name()); + } + return JoinStrings(names, ","); +} + +static const char* kFirstInsertionPointName = "first_mock_insertion_point"; +static const char* kSecondInsertionPointName = "second_mock_insertion_point"; +static const char* kFirstInsertionPoint = + "# @@protoc_insertion_point(first_mock_insertion_point) is here\n"; +static const char* kSecondInsertionPoint = + " # @@protoc_insertion_point(second_mock_insertion_point) is here\n"; + +MockCodeGenerator::MockCodeGenerator(const string& name) + : name_(name) {} + +MockCodeGenerator::~MockCodeGenerator() {} + +void MockCodeGenerator::ExpectGenerated( + const string& name, + const string& parameter, + const string& insertions, + const string& file, + const string& first_message_name, + const string& first_parsed_file_name, + const string& output_directory) { + string content; + ASSERT_TRUE(File::ReadFileToString( + output_directory + "/" + GetOutputFileName(name, file), &content)); + + vector lines; + SplitStringUsing(content, "\n", &lines); + + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } + for (int i = 0; i < lines.size(); i++) { + lines[i] += "\n"; + } + + vector insertion_list; + if (!insertions.empty()) { + SplitStringUsing(insertions, ",", &insertion_list); + } + + ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2); + EXPECT_EQ(GetOutputFileContent(name, parameter, file, + first_parsed_file_name, first_message_name), + lines[0]); + + EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); + EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]); + + for (int i = 0; i < insertion_list.size(); i++) { + EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", + file, file, first_message_name), + lines[1 + i]); + // Second insertion point is indented, so the inserted text should + // automatically be indented too. + EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert", + file, file, first_message_name), + lines[2 + insertion_list.size() + i]); + } +} + +bool MockCodeGenerator::Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + for (int i = 0; i < file->message_type_count(); i++) { + if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { + string command = StripPrefixString(file->message_type(i)->name(), + "MockCodeGenerator_"); + if (command == "Error") { + *error = "Saw message type MockCodeGenerator_Error."; + return false; + } else if (command == "Exit") { + cerr << "Saw message type MockCodeGenerator_Exit." << endl; + exit(123); + } else if (command == "Abort") { + cerr << "Saw message type MockCodeGenerator_Abort." << endl; + abort(); + } else if (command == "HasSourceCodeInfo") { + FileDescriptorProto file_descriptor_proto; + file->CopySourceCodeInfoTo(&file_descriptor_proto); + bool has_source_code_info = + file_descriptor_proto.has_source_code_info() && + file_descriptor_proto.source_code_info().location_size() > 0; + cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " + << has_source_code_info << "." << endl; + abort(); + } else { + GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command; + } + } + } + + if (HasPrefixString(parameter, "insert=")) { + vector insert_into; + SplitStringUsing(StripPrefixString(parameter, "insert="), + ",", &insert_into); + + for (int i = 0; i < insert_into.size(); i++) { + { + scoped_ptr output( + context->OpenForInsert( + GetOutputFileName(insert_into[i], file), + kFirstInsertionPointName)); + io::Printer printer(output.get(), '$'); + printer.PrintRaw(GetOutputFileContent(name_, "first_insert", + file, context)); + if (printer.failed()) { + *error = "MockCodeGenerator detected write error."; + return false; + } + } + + { + scoped_ptr output( + context->OpenForInsert( + GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName)); + io::Printer printer(output.get(), '$'); + printer.PrintRaw(GetOutputFileContent(name_, "second_insert", + file, context)); + if (printer.failed()) { + *error = "MockCodeGenerator detected write error."; + return false; + } + } + } + } else { + scoped_ptr output( + context->Open(GetOutputFileName(name_, file))); + + io::Printer printer(output.get(), '$'); + printer.PrintRaw(GetOutputFileContent(name_, parameter, + file, context)); + printer.PrintRaw(kFirstInsertionPoint); + printer.PrintRaw(kSecondInsertionPoint); + + if (printer.failed()) { + *error = "MockCodeGenerator detected write error."; + return false; + } + } + + return true; +} + +string MockCodeGenerator::GetOutputFileName(const string& generator_name, + const FileDescriptor* file) { + return GetOutputFileName(generator_name, file->name()); +} + +string MockCodeGenerator::GetOutputFileName(const string& generator_name, + const string& file) { + return file + ".MockCodeGenerator." + generator_name; +} + +string MockCodeGenerator::GetOutputFileContent( + const string& generator_name, + const string& parameter, + const FileDescriptor* file, + GeneratorContext *context) { + vector all_files; + context->ListParsedFiles(&all_files); + return GetOutputFileContent( + generator_name, parameter, file->name(), + CommaSeparatedList(all_files), + file->message_type_count() > 0 ? + file->message_type(0)->name() : "(none)"); +} + +string MockCodeGenerator::GetOutputFileContent( + const string& generator_name, + const string& parameter, + const string& file, + const string& parsed_file_list, + const string& first_message_name) { + return strings::Substitute("$0: $1, $2, $3, $4\n", + generator_name, parameter, file, + first_message_name, parsed_file_list); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.h new file mode 100644 index 000000000..506fd2070 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/mock_code_generator.h @@ -0,0 +1,117 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +// A mock CodeGenerator, used by command_line_interface_unittest. This is in +// its own file so that it can be used both directly and as a plugin. +// +// Generate() produces some output which can be checked by ExpectCalled(). The +// generator can run in a different process (e.g. a plugin). +// +// If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines +// into the files generated by other MockCodeGenerators instead of creating +// its own file. NAMES is a comma-separated list of the names of those other +// MockCodeGenerators. +// +// MockCodeGenerator will also modify its behavior slightly if the input file +// contains a message type with one of the following names: +// MockCodeGenerator_Error: Causes Generate() to return false and set the +// error message to "Saw message type MockCodeGenerator_Error." +// MockCodeGenerator_Exit: Generate() prints "Saw message type +// MockCodeGenerator_Exit." to stderr and then calls exit(123). +// MockCodeGenerator_Abort: Generate() prints "Saw message type +// MockCodeGenerator_Abort." to stderr and then calls abort(). +// MockCodeGenerator_HasSourceCodeInfo: Causes Generate() to abort after +// printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to +// stderr, where FOO is "1" if the supplied FileDescriptorProto has source +// code info, and "0" otherwise. +class MockCodeGenerator : public CodeGenerator { + public: + MockCodeGenerator(const string& name); + virtual ~MockCodeGenerator(); + + // Expect (via gTest) that a MockCodeGenerator with the given name was called + // with the given parameters by inspecting the output location. + // + // |insertions| is a comma-separated list of names of MockCodeGenerators which + // should have inserted lines into this file. + // |parsed_file_list| is a comma-separated list of names of the files + // that are being compiled together in this run. + static void ExpectGenerated(const string& name, + const string& parameter, + const string& insertions, + const string& file, + const string& first_message_name, + const string& parsed_file_list, + const string& output_directory); + + // Get the name of the file which would be written by the given generator. + static string GetOutputFileName(const string& generator_name, + const FileDescriptor* file); + static string GetOutputFileName(const string& generator_name, + const string& file); + + // implements CodeGenerator ---------------------------------------- + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const; + + private: + string name_; + + static string GetOutputFileContent(const string& generator_name, + const string& parameter, + const FileDescriptor* file, + GeneratorContext *context); + static string GetOutputFileContent(const string& generator_name, + const string& parameter, + const string& file, + const string& parsed_file_list, + const string& first_message_name); +}; + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/package_info.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/package_info.h new file mode 100644 index 000000000..b89712674 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/package_info.h @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 exists solely to document the google::protobuf::compiler namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +namespace google { + +namespace protobuf { + +// Implementation of the Protocol Buffer compiler. +// +// This package contains code for parsing .proto files and generating code +// based on them. There are two reasons you might be interested in this +// package: +// - You want to parse .proto files at runtime. In this case, you should +// look at importer.h. Since this functionality is widely useful, it is +// included in the libprotobuf base library; you do not have to link against +// libprotoc. +// - You want to write a custom protocol compiler which generates different +// kinds of code, e.g. code in a different language which is not supported +// by the official compiler. For this purpose, command_line_interface.h +// provides you with a complete compiler front-end, so all you need to do +// is write a custom implementation of CodeGenerator and a trivial main() +// function. You can even make your compiler support the official languages +// in addition to your own. Since this functionality is only useful to those +// writing custom compilers, it is in a separate library called "libprotoc" +// which you will have to link against. +namespace compiler {} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.cc new file mode 100644 index 000000000..23aa01ced --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.cc @@ -0,0 +1,1611 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Recursive descent FTW. + +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +using internal::WireFormat; + +namespace { + +typedef hash_map TypeNameMap; + +TypeNameMap MakeTypeNameTable() { + TypeNameMap result; + + result["double" ] = FieldDescriptorProto::TYPE_DOUBLE; + result["float" ] = FieldDescriptorProto::TYPE_FLOAT; + result["uint64" ] = FieldDescriptorProto::TYPE_UINT64; + result["fixed64" ] = FieldDescriptorProto::TYPE_FIXED64; + result["fixed32" ] = FieldDescriptorProto::TYPE_FIXED32; + result["bool" ] = FieldDescriptorProto::TYPE_BOOL; + result["string" ] = FieldDescriptorProto::TYPE_STRING; + result["group" ] = FieldDescriptorProto::TYPE_GROUP; + + result["bytes" ] = FieldDescriptorProto::TYPE_BYTES; + result["uint32" ] = FieldDescriptorProto::TYPE_UINT32; + result["sfixed32"] = FieldDescriptorProto::TYPE_SFIXED32; + result["sfixed64"] = FieldDescriptorProto::TYPE_SFIXED64; + result["int32" ] = FieldDescriptorProto::TYPE_INT32; + result["int64" ] = FieldDescriptorProto::TYPE_INT64; + result["sint32" ] = FieldDescriptorProto::TYPE_SINT32; + result["sint64" ] = FieldDescriptorProto::TYPE_SINT64; + + return result; +} + +const TypeNameMap kTypeNames = MakeTypeNameTable(); + +} // anonymous namespace + +// Makes code slightly more readable. The meaning of "DO(foo)" is +// "Execute foo and fail if it fails.", where failure is indicated by +// returning false. +#define DO(STATEMENT) if (STATEMENT) {} else return false + +// =================================================================== + +Parser::Parser() + : input_(NULL), + error_collector_(NULL), + source_location_table_(NULL), + had_errors_(false), + require_syntax_identifier_(false), + stop_after_syntax_identifier_(false) { +} + +Parser::~Parser() { +} + +// =================================================================== + +inline bool Parser::LookingAt(const char* text) { + return input_->current().text == text; +} + +inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) { + return input_->current().type == token_type; +} + +inline bool Parser::AtEnd() { + return LookingAtType(io::Tokenizer::TYPE_END); +} + +bool Parser::TryConsume(const char* text) { + if (LookingAt(text)) { + input_->Next(); + return true; + } else { + return false; + } +} + +bool Parser::Consume(const char* text, const char* error) { + if (TryConsume(text)) { + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::Consume(const char* text) { + if (TryConsume(text)) { + return true; + } else { + AddError("Expected \"" + string(text) + "\"."); + return false; + } +} + +bool Parser::ConsumeIdentifier(string* output, const char* error) { + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + *output = input_->current().text; + input_->Next(); + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::ConsumeInteger(int* output, const char* error) { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + uint64 value = 0; + if (!io::Tokenizer::ParseInteger(input_->current().text, + kint32max, &value)) { + AddError("Integer out of range."); + // We still return true because we did, in fact, parse an integer. + } + *output = value; + input_->Next(); + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::ConsumeSignedInteger(int* output, const char* error) { + bool is_negative = false; + uint64 max_value = kint32max; + if (TryConsume("-")) { + is_negative = true; + max_value += 1; + } + uint64 value = 0; + DO(ConsumeInteger64(max_value, &value, error)); + if (is_negative) value *= -1; + *output = value; + return true; +} + +bool Parser::ConsumeInteger64(uint64 max_value, uint64* output, + const char* error) { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + if (!io::Tokenizer::ParseInteger(input_->current().text, max_value, + output)) { + AddError("Integer out of range."); + // We still return true because we did, in fact, parse an integer. + *output = 0; + } + input_->Next(); + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::ConsumeNumber(double* output, const char* error) { + if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { + *output = io::Tokenizer::ParseFloat(input_->current().text); + input_->Next(); + return true; + } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + // Also accept integers. + uint64 value = 0; + if (!io::Tokenizer::ParseInteger(input_->current().text, + kuint64max, &value)) { + AddError("Integer out of range."); + // We still return true because we did, in fact, parse a number. + } + *output = value; + input_->Next(); + return true; + } else if (LookingAt("inf")) { + *output = numeric_limits::infinity(); + input_->Next(); + return true; + } else if (LookingAt("nan")) { + *output = numeric_limits::quiet_NaN(); + input_->Next(); + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::ConsumeString(string* output, const char* error) { + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + io::Tokenizer::ParseString(input_->current().text, output); + input_->Next(); + // Allow C++ like concatenation of adjacent string tokens. + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + io::Tokenizer::ParseStringAppend(input_->current().text, output); + input_->Next(); + } + return true; + } else { + AddError(error); + return false; + } +} + +bool Parser::TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { + if (LookingAt(text)) { + string leading, trailing; + input_->NextWithComments(&trailing, NULL, &leading); + + // Save the leading comments for next time, and recall the leading comments + // from last time. + leading.swap(upcoming_doc_comments_); + + if (location != NULL) { + location->AttachComments(&leading, &trailing); + } + return true; + } else { + return false; + } +} + +bool Parser::ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location) { + if (TryConsumeEndOfDeclaration(text, location)) { + return true; + } else { + AddError("Expected \"" + string(text) + "\"."); + return false; + } +} + +// ------------------------------------------------------------------- + +void Parser::AddError(int line, int column, const string& error) { + if (error_collector_ != NULL) { + error_collector_->AddError(line, column, error); + } + had_errors_ = true; +} + +void Parser::AddError(const string& error) { + AddError(input_->current().line, input_->current().column, error); +} + +// ------------------------------------------------------------------- + +Parser::LocationRecorder::LocationRecorder(Parser* parser) + : parser_(parser), + location_(parser_->source_code_info_->add_location()) { + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) { + Init(parent); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1) { + Init(parent); + AddPath(path1); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1, int path2) { + Init(parent); + AddPath(path1); + AddPath(path2); +} + +void Parser::LocationRecorder::Init(const LocationRecorder& parent) { + parser_ = parent.parser_; + location_ = parser_->source_code_info_->add_location(); + location_->mutable_path()->CopyFrom(parent.location_->path()); + + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::~LocationRecorder() { + if (location_->span_size() <= 2) { + EndAt(parser_->input_->previous()); + } +} + +void Parser::LocationRecorder::AddPath(int path_component) { + location_->add_path(path_component); +} + +void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { + location_->set_span(0, token.line); + location_->set_span(1, token.column); +} + +void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { + if (token.line != location_->span(0)) { + location_->add_span(token.line); + } + location_->add_span(token.end_column); +} + +void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location) { + if (parser_->source_location_table_ != NULL) { + parser_->source_location_table_->Add( + descriptor, location, location_->span(0), location_->span(1)); + } +} + +void Parser::LocationRecorder::AttachComments( + string* leading, string* trailing) const { + GOOGLE_CHECK(!location_->has_leading_comments()); + GOOGLE_CHECK(!location_->has_trailing_comments()); + + if (!leading->empty()) { + location_->mutable_leading_comments()->swap(*leading); + } + if (!trailing->empty()) { + location_->mutable_trailing_comments()->swap(*trailing); + } +} + +// ------------------------------------------------------------------- + +void Parser::SkipStatement() { + while (true) { + if (AtEnd()) { + return; + } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { + if (TryConsumeEndOfDeclaration(";", NULL)) { + return; + } else if (TryConsume("{")) { + SkipRestOfBlock(); + return; + } else if (LookingAt("}")) { + return; + } + } + input_->Next(); + } +} + +void Parser::SkipRestOfBlock() { + while (true) { + if (AtEnd()) { + return; + } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { + if (TryConsumeEndOfDeclaration("}", NULL)) { + return; + } else if (TryConsume("{")) { + SkipRestOfBlock(); + } + } + input_->Next(); + } +} + +// =================================================================== + +bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { + input_ = input; + had_errors_ = false; + syntax_identifier_.clear(); + + // Note that |file| could be NULL at this point if + // stop_after_syntax_identifier_ is true. So, we conservatively allocate + // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto + // later on. + SourceCodeInfo source_code_info; + source_code_info_ = &source_code_info; + + if (LookingAtType(io::Tokenizer::TYPE_START)) { + // Advance to first token. + input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + } + + { + LocationRecorder root_location(this); + + if (require_syntax_identifier_ || LookingAt("syntax")) { + if (!ParseSyntaxIdentifier()) { + // Don't attempt to parse the file if we didn't recognize the syntax + // identifier. + return false; + } + } else if (!stop_after_syntax_identifier_) { + syntax_identifier_ = "proto2"; + } + + if (stop_after_syntax_identifier_) return !had_errors_; + + // Repeatedly parse statements until we reach the end of the file. + while (!AtEnd()) { + if (!ParseTopLevelStatement(file, root_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + + if (LookingAt("}")) { + AddError("Unmatched \"}\"."); + input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + } + } + } + } + + input_ = NULL; + source_code_info_ = NULL; + source_code_info.Swap(file->mutable_source_code_info()); + return !had_errors_; +} + +bool Parser::ParseSyntaxIdentifier() { + DO(Consume("syntax", "File must begin with 'syntax = \"proto2\";'.")); + DO(Consume("=")); + io::Tokenizer::Token syntax_token = input_->current(); + string syntax; + DO(ConsumeString(&syntax, "Expected syntax identifier.")); + DO(ConsumeEndOfDeclaration(";", NULL)); + + syntax_identifier_ = syntax; + + if (syntax != "proto2" && !stop_after_syntax_identifier_) { + AddError(syntax_token.line, syntax_token.column, + "Unrecognized syntax identifier \"" + syntax + "\". This parser " + "only recognizes \"proto2\"."); + return false; + } + + return true; +} + +bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location) { + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + return true; + } else if (LookingAt("message")) { + LocationRecorder location(root_location, + FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); + return ParseMessageDefinition(file->add_message_type(), location); + } else if (LookingAt("enum")) { + LocationRecorder location(root_location, + FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); + return ParseEnumDefinition(file->add_enum_type(), location); + } else if (LookingAt("service")) { + LocationRecorder location(root_location, + FileDescriptorProto::kServiceFieldNumber, file->service_size()); + return ParseServiceDefinition(file->add_service(), location); + } else if (LookingAt("extend")) { + LocationRecorder location(root_location, + FileDescriptorProto::kExtensionFieldNumber); + return ParseExtend(file->mutable_extension(), + file->mutable_message_type(), + root_location, + FileDescriptorProto::kMessageTypeFieldNumber, + location); + } else if (LookingAt("import")) { + return ParseImport(file->mutable_dependency(), + file->mutable_public_dependency(), + file->mutable_weak_dependency(), + root_location); + } else if (LookingAt("package")) { + return ParsePackage(file, root_location); + } else if (LookingAt("option")) { + LocationRecorder location(root_location, + FileDescriptorProto::kOptionsFieldNumber); + return ParseOption(file->mutable_options(), location, OPTION_STATEMENT); + } else { + AddError("Expected top-level statement (e.g. \"message\")."); + return false; + } +} + +// ------------------------------------------------------------------- +// Messages + +bool Parser::ParseMessageDefinition(DescriptorProto* message, + const LocationRecorder& message_location) { + DO(Consume("message")); + { + LocationRecorder location(message_location, + DescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + message, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); + } + DO(ParseMessageBlock(message, message_location)); + return true; +} + +namespace { + +const int kMaxExtensionRangeSentinel = -1; + +bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { + const MessageOptions& options = message.options(); + for (int i = 0; i < options.uninterpreted_option_size(); ++i) { + const UninterpretedOption& uninterpreted = options.uninterpreted_option(i); + if (uninterpreted.name_size() == 1 && + uninterpreted.name(0).name_part() == "message_set_wire_format" && + uninterpreted.identifier_value() == "true") { + return true; + } + } + return false; +} + +// Modifies any extension ranges that specified 'max' as the end of the +// extension range, and sets them to the type-specific maximum. The actual max +// tag number can only be determined after all options have been parsed. +void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { + const bool is_message_set = IsMessageSetWireFormatMessage(*message); + const int max_extension_number = is_message_set ? + kint32max : + FieldDescriptor::kMaxNumber + 1; + for (int i = 0; i < message->extension_range_size(); ++i) { + if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) { + message->mutable_extension_range(i)->set_end(max_extension_number); + } + } +} + +} // namespace + +bool Parser::ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location) { + DO(ConsumeEndOfDeclaration("{", &message_location)); + + while (!TryConsumeEndOfDeclaration("}", NULL)) { + if (AtEnd()) { + AddError("Reached end of input in message definition (missing '}')."); + return false; + } + + if (!ParseMessageStatement(message, message_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } + + if (message->extension_range_size() > 0) { + AdjustExtensionRangesWithMaxEndNumber(message); + } + return true; +} + +bool Parser::ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location) { + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + return true; + } else if (LookingAt("message")) { + LocationRecorder location(message_location, + DescriptorProto::kNestedTypeFieldNumber, + message->nested_type_size()); + return ParseMessageDefinition(message->add_nested_type(), location); + } else if (LookingAt("enum")) { + LocationRecorder location(message_location, + DescriptorProto::kEnumTypeFieldNumber, + message->enum_type_size()); + return ParseEnumDefinition(message->add_enum_type(), location); + } else if (LookingAt("extensions")) { + LocationRecorder location(message_location, + DescriptorProto::kExtensionRangeFieldNumber); + return ParseExtensions(message, location); + } else if (LookingAt("extend")) { + LocationRecorder location(message_location, + DescriptorProto::kExtensionFieldNumber); + return ParseExtend(message->mutable_extension(), + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location); + } else if (LookingAt("option")) { + LocationRecorder location(message_location, + DescriptorProto::kOptionsFieldNumber); + return ParseOption(message->mutable_options(), location, OPTION_STATEMENT); + } else { + LocationRecorder location(message_location, + DescriptorProto::kFieldFieldNumber, + message->field_size()); + return ParseMessageField(message->add_field(), + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location); + } +} + +bool Parser::ParseMessageField(FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location) { + // Parse label and type. + io::Tokenizer::Token label_token = input_->current(); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kLabelFieldNumber); + FieldDescriptorProto::Label label; + DO(ParseLabel(&label)); + field->set_label(label); + } + + { + LocationRecorder location(field_location); // add path later + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); + + FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; + string type_name; + DO(ParseType(&type, &type_name)); + if (type_name.empty()) { + location.AddPath(FieldDescriptorProto::kTypeFieldNumber); + field->set_type(type); + } else { + location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber); + field->set_type_name(type_name); + } + } + + // Parse name and '='. + io::Tokenizer::Token name_token = input_->current(); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + } + DO(Consume("=", "Missing field number.")); + + // Parse field number. + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::NUMBER); + int number; + DO(ConsumeInteger(&number, "Expected field number.")); + field->set_number(number); + } + + // Parse options. + DO(ParseFieldOptions(field, field_location)); + + // Deal with groups. + if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { + // Awkward: Since a group declares both a message type and a field, we + // have to create overlapping locations. + LocationRecorder group_location(parent_location); + group_location.StartAt(label_token); + group_location.AddPath(location_field_number_for_nested_type); + group_location.AddPath(messages->size()); + + DescriptorProto* group = messages->Add(); + group->set_name(field->name()); + + // Record name location to match the field name's location. + { + LocationRecorder location(group_location, + DescriptorProto::kNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + location.RecordLegacyLocation( + group, DescriptorPool::ErrorCollector::NAME); + } + + // The field's type_name also comes from the name. Confusing! + { + LocationRecorder location(field_location, + FieldDescriptorProto::kTypeNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + } + + // As a hack for backwards-compatibility, we force the group name to start + // with a capital letter and lower-case the field name. New code should + // not use groups; it should use nested messages. + if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { + AddError(name_token.line, name_token.column, + "Group names must start with a capital letter."); + } + LowerString(field->mutable_name()); + + field->set_type_name(group->name()); + if (LookingAt("{")) { + DO(ParseMessageBlock(group, group_location)); + } else { + AddError("Missing group body."); + return false; + } + } else { + DO(ConsumeEndOfDeclaration(";", &field_location)); + } + + return true; +} + +bool Parser::ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location) { + if (!LookingAt("[")) return true; + + LocationRecorder location(field_location, + FieldDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); + + // Parse field options. + do { + if (LookingAt("default")) { + // We intentionally pass field_location rather than location here, since + // the default value is not actually an option. + DO(ParseDefaultAssignment(field, field_location)); + } else { + DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT)); + } + } while (TryConsume(",")); + + DO(Consume("]")); + return true; +} + +bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, + const LocationRecorder& field_location) { + if (field->has_default_value()) { + AddError("Already set option \"default\"."); + field->clear_default_value(); + } + + DO(Consume("default")); + DO(Consume("=")); + + LocationRecorder location(field_location, + FieldDescriptorProto::kDefaultValueFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); + string* default_value = field->mutable_default_value(); + + if (!field->has_type()) { + // The field has a type name, but we don't know if it is a message or an + // enum yet. Assume an enum for now. + DO(ConsumeIdentifier(default_value, "Expected identifier.")); + return true; + } + + switch (field->type()) { + case FieldDescriptorProto::TYPE_INT32: + case FieldDescriptorProto::TYPE_INT64: + case FieldDescriptorProto::TYPE_SINT32: + case FieldDescriptorProto::TYPE_SINT64: + case FieldDescriptorProto::TYPE_SFIXED32: + case FieldDescriptorProto::TYPE_SFIXED64: { + uint64 max_value = kint64max; + if (field->type() == FieldDescriptorProto::TYPE_INT32 || + field->type() == FieldDescriptorProto::TYPE_SINT32 || + field->type() == FieldDescriptorProto::TYPE_SFIXED32) { + max_value = kint32max; + } + + // These types can be negative. + if (TryConsume("-")) { + default_value->append("-"); + // Two's complement always has one more negative value than positive. + ++max_value; + } + // Parse the integer to verify that it is not out-of-range. + uint64 value; + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + // And stringify it again. + default_value->append(SimpleItoa(value)); + break; + } + + case FieldDescriptorProto::TYPE_UINT32: + case FieldDescriptorProto::TYPE_UINT64: + case FieldDescriptorProto::TYPE_FIXED32: + case FieldDescriptorProto::TYPE_FIXED64: { + uint64 max_value = kuint64max; + if (field->type() == FieldDescriptorProto::TYPE_UINT32 || + field->type() == FieldDescriptorProto::TYPE_FIXED32) { + max_value = kuint32max; + } + + // Numeric, not negative. + if (TryConsume("-")) { + AddError("Unsigned field can't have negative default value."); + } + // Parse the integer to verify that it is not out-of-range. + uint64 value; + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + // And stringify it again. + default_value->append(SimpleItoa(value)); + break; + } + + case FieldDescriptorProto::TYPE_FLOAT: + case FieldDescriptorProto::TYPE_DOUBLE: + // These types can be negative. + if (TryConsume("-")) { + default_value->append("-"); + } + // Parse the integer because we have to convert hex integers to decimal + // floats. + double value; + DO(ConsumeNumber(&value, "Expected number.")); + // And stringify it again. + default_value->append(SimpleDtoa(value)); + break; + + case FieldDescriptorProto::TYPE_BOOL: + if (TryConsume("true")) { + default_value->assign("true"); + } else if (TryConsume("false")) { + default_value->assign("false"); + } else { + AddError("Expected \"true\" or \"false\"."); + return false; + } + break; + + case FieldDescriptorProto::TYPE_STRING: + DO(ConsumeString(default_value, "Expected string.")); + break; + + case FieldDescriptorProto::TYPE_BYTES: + DO(ConsumeString(default_value, "Expected string.")); + *default_value = CEscape(*default_value); + break; + + case FieldDescriptorProto::TYPE_ENUM: + DO(ConsumeIdentifier(default_value, "Expected identifier.")); + break; + + case FieldDescriptorProto::TYPE_MESSAGE: + case FieldDescriptorProto::TYPE_GROUP: + AddError("Messages can't have default values."); + return false; + } + + return true; +} + +bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location) { + UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); + string identifier; // We parse identifiers into this string. + if (LookingAt("(")) { // This is an extension. + DO(Consume("(")); + + { + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); + // An extension name consists of dot-separated identifiers, and may begin + // with a dot. + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } + while (LookingAt(".")) { + DO(Consume(".")); + name->mutable_name_part()->append("."); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } + } + + DO(Consume(")")); + name->set_is_extension(true); + } else { // This is a regular field. + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + name->set_is_extension(false); + } + return true; +} + +bool Parser::ParseUninterpretedBlock(string* value) { + // Note that enclosing braces are not added to *value. + // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting + // an expression, not a block of statements. + DO(Consume("{")); + int brace_depth = 1; + while (!AtEnd()) { + if (LookingAt("{")) { + brace_depth++; + } else if (LookingAt("}")) { + brace_depth--; + if (brace_depth == 0) { + input_->Next(); + return true; + } + } + // TODO(sanjay): Interpret line/column numbers to preserve formatting + if (!value->empty()) value->push_back(' '); + value->append(input_->current().text); + input_->Next(); + } + AddError("Unexpected end of stream while parsing aggregate value."); + return false; +} + +// We don't interpret the option here. Instead we store it in an +// UninterpretedOption, to be interpreted later. +bool Parser::ParseOption(Message* options, + const LocationRecorder& options_location, + OptionStyle style) { + // Create an entry in the uninterpreted_option field. + const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> + FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(uninterpreted_option_field != NULL) + << "No field named \"uninterpreted_option\" in the Options proto."; + + const Reflection* reflection = options->GetReflection(); + + LocationRecorder location( + options_location, uninterpreted_option_field->number(), + reflection->FieldSize(*options, uninterpreted_option_field)); + + if (style == OPTION_STATEMENT) { + DO(Consume("option")); + } + + UninterpretedOption* uninterpreted_option = down_cast( + options->GetReflection()->AddMessage(options, + uninterpreted_option_field)); + + // Parse dot-separated name. + { + LocationRecorder name_location(location, + UninterpretedOption::kNameFieldNumber); + name_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); + + { + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location)); + } + + while (LookingAt(".")) { + DO(Consume(".")); + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location)); + } + } + + DO(Consume("=")); + + { + LocationRecorder value_location(location); + value_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); + + // All values are a single token, except for negative numbers, which consist + // of a single '-' symbol, followed by a positive number. + bool is_negative = TryConsume("-"); + + switch (input_->current().type) { + case io::Tokenizer::TYPE_START: + GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; + return false; + + case io::Tokenizer::TYPE_END: + AddError("Unexpected end of stream while parsing option value."); + return false; + + case io::Tokenizer::TYPE_IDENTIFIER: { + value_location.AddPath( + UninterpretedOption::kIdentifierValueFieldNumber); + if (is_negative) { + AddError("Invalid '-' symbol before identifier."); + return false; + } + string value; + DO(ConsumeIdentifier(&value, "Expected identifier.")); + uninterpreted_option->set_identifier_value(value); + break; + } + + case io::Tokenizer::TYPE_INTEGER: { + uint64 value; + uint64 max_value = + is_negative ? static_cast(kint64max) + 1 : kuint64max; + DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + if (is_negative) { + value_location.AddPath( + UninterpretedOption::kNegativeIntValueFieldNumber); + uninterpreted_option->set_negative_int_value( + -static_cast(value)); + } else { + value_location.AddPath( + UninterpretedOption::kPositiveIntValueFieldNumber); + uninterpreted_option->set_positive_int_value(value); + } + break; + } + + case io::Tokenizer::TYPE_FLOAT: { + value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); + double value; + DO(ConsumeNumber(&value, "Expected number.")); + uninterpreted_option->set_double_value(is_negative ? -value : value); + break; + } + + case io::Tokenizer::TYPE_STRING: { + value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); + if (is_negative) { + AddError("Invalid '-' symbol before string."); + return false; + } + string value; + DO(ConsumeString(&value, "Expected string.")); + uninterpreted_option->set_string_value(value); + break; + } + + case io::Tokenizer::TYPE_SYMBOL: + if (LookingAt("{")) { + value_location.AddPath( + UninterpretedOption::kAggregateValueFieldNumber); + DO(ParseUninterpretedBlock( + uninterpreted_option->mutable_aggregate_value())); + } else { + AddError("Expected option value."); + return false; + } + break; + } + } + + if (style == OPTION_STATEMENT) { + DO(ConsumeEndOfDeclaration(";", &location)); + } + + return true; +} + +bool Parser::ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location) { + // Parse the declaration. + DO(Consume("extensions")); + + do { + // Note that kExtensionRangeFieldNumber was already pushed by the parent. + LocationRecorder location(extensions_location, + message->extension_range_size()); + + DescriptorProto::ExtensionRange* range = message->add_extension_range(); + location.RecordLegacyLocation( + range, DescriptorPool::ErrorCollector::NUMBER); + + int start, end; + io::Tokenizer::Token start_token; + + { + LocationRecorder start_location( + location, DescriptorProto::ExtensionRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeInteger(&start, "Expected field number range.")); + } + + if (TryConsume("to")) { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); + if (TryConsume("max")) { + // Set to the sentinel value - 1 since we increment the value below. + // The actual value of the end of the range should be set with + // AdjustExtensionRangesWithMaxEndNumber. + end = kMaxExtensionRangeSentinel - 1; + } else { + DO(ConsumeInteger(&end, "Expected integer.")); + } + } else { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); + end = start; + } + + // Users like to specify inclusive ranges, but in code we like the end + // number to be exclusive. + ++end; + + range->set_start(start); + range->set_end(end); + } while (TryConsume(",")); + + DO(ConsumeEndOfDeclaration(";", &extensions_location)); + return true; +} + +bool Parser::ParseExtend(RepeatedPtrField* extensions, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location) { + DO(Consume("extend")); + + // Parse the extendee type. + io::Tokenizer::Token extendee_start = input_->current(); + string extendee; + DO(ParseUserDefinedType(&extendee)); + io::Tokenizer::Token extendee_end = input_->previous(); + + // Parse the block. + DO(ConsumeEndOfDeclaration("{", &extend_location)); + + bool is_first = true; + + do { + if (AtEnd()) { + AddError("Reached end of input in extend definition (missing '}')."); + return false; + } + + // Note that kExtensionFieldNumber was already pushed by the parent. + LocationRecorder location(extend_location, extensions->size()); + + FieldDescriptorProto* field = extensions->Add(); + + { + LocationRecorder extendee_location( + location, FieldDescriptorProto::kExtendeeFieldNumber); + extendee_location.StartAt(extendee_start); + extendee_location.EndAt(extendee_end); + + if (is_first) { + extendee_location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::EXTENDEE); + is_first = false; + } + } + + field->set_extendee(extendee); + + if (!ParseMessageField(field, messages, parent_location, + location_field_number_for_nested_type, + location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } while (!TryConsumeEndOfDeclaration("}", NULL)); + + return true; +} + +// ------------------------------------------------------------------- +// Enums + +bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { + DO(Consume("enum")); + + { + LocationRecorder location(enum_location, + EnumDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_type, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); + } + + DO(ParseEnumBlock(enum_type, enum_location)); + return true; +} + +bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { + DO(ConsumeEndOfDeclaration("{", &enum_location)); + + while (!TryConsumeEndOfDeclaration("}", NULL)) { + if (AtEnd()) { + AddError("Reached end of input in enum definition (missing '}')."); + return false; + } + + if (!ParseEnumStatement(enum_type, enum_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } + + return true; +} + +bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + return true; + } else if (LookingAt("option")) { + LocationRecorder location(enum_location, + EnumDescriptorProto::kOptionsFieldNumber); + return ParseOption(enum_type->mutable_options(), location, + OPTION_STATEMENT); + } else { + LocationRecorder location(enum_location, + EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); + return ParseEnumConstant(enum_type->add_value(), location); + } +} + +bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location) { + // Parse name. + { + LocationRecorder location(enum_value_location, + EnumValueDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_value->mutable_name(), + "Expected enum constant name.")); + } + + DO(Consume("=", "Missing numeric value for enum constant.")); + + // Parse value. + { + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NUMBER); + + int number; + DO(ConsumeSignedInteger(&number, "Expected integer.")); + enum_value->set_number(number); + } + + DO(ParseEnumConstantOptions(enum_value, enum_value_location)); + + DO(ConsumeEndOfDeclaration(";", &enum_value_location)); + + return true; +} + +bool Parser::ParseEnumConstantOptions( + EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location) { + if (!LookingAt("[")) return true; + + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); + + do { + DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT)); + } while (TryConsume(",")); + + DO(Consume("]")); + return true; +} + +// ------------------------------------------------------------------- +// Services + +bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { + DO(Consume("service")); + + { + LocationRecorder location(service_location, + ServiceDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + service, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); + } + + DO(ParseServiceBlock(service, service_location)); + return true; +} + +bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { + DO(ConsumeEndOfDeclaration("{", &service_location)); + + while (!TryConsumeEndOfDeclaration("}", NULL)) { + if (AtEnd()) { + AddError("Reached end of input in service definition (missing '}')."); + return false; + } + + if (!ParseServiceStatement(service, service_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } + + return true; +} + +bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + return true; + } else if (LookingAt("option")) { + LocationRecorder location( + service_location, ServiceDescriptorProto::kOptionsFieldNumber); + return ParseOption(service->mutable_options(), location, OPTION_STATEMENT); + } else { + LocationRecorder location(service_location, + ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); + return ParseServiceMethod(service->add_method(), location); + } +} + +bool Parser::ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location) { + DO(Consume("rpc")); + + { + LocationRecorder location(method_location, + MethodDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); + } + + // Parse input type. + DO(Consume("(")); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kInputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::INPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_input_type())); + } + DO(Consume(")")); + + // Parse output type. + DO(Consume("returns")); + DO(Consume("(")); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kOutputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_output_type())); + } + DO(Consume(")")); + + if (LookingAt("{")) { + // Options! + DO(ParseOptions(method_location, + MethodDescriptorProto::kOptionsFieldNumber, + method->mutable_options())); + } else { + DO(ConsumeEndOfDeclaration(";", &method_location)); + } + + return true; +} + + +bool Parser::ParseOptions(const LocationRecorder& parent_location, + const int optionsFieldNumber, + Message* mutable_options) { + // Options! + ConsumeEndOfDeclaration("{", &parent_location); + while (!TryConsumeEndOfDeclaration("}", NULL)) { + if (AtEnd()) { + AddError("Reached end of input in method options (missing '}')."); + return false; + } + + if (TryConsumeEndOfDeclaration(";", NULL)) { + // empty statement; ignore + } else { + LocationRecorder location(parent_location, + optionsFieldNumber); + if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) { + // This statement failed to parse. Skip it, but keep looping to + // parse other statements. + SkipStatement(); + } + } + } + + return true; +} + +// ------------------------------------------------------------------- + +bool Parser::ParseLabel(FieldDescriptorProto::Label* label) { + if (TryConsume("optional")) { + *label = FieldDescriptorProto::LABEL_OPTIONAL; + return true; + } else if (TryConsume("repeated")) { + *label = FieldDescriptorProto::LABEL_REPEATED; + return true; + } else if (TryConsume("required")) { + *label = FieldDescriptorProto::LABEL_REQUIRED; + return true; + } else { + AddError("Expected \"required\", \"optional\", or \"repeated\"."); + // We can actually reasonably recover here by just assuming the user + // forgot the label altogether. + *label = FieldDescriptorProto::LABEL_OPTIONAL; + return true; + } +} + +bool Parser::ParseType(FieldDescriptorProto::Type* type, + string* type_name) { + TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); + if (iter != kTypeNames.end()) { + *type = iter->second; + input_->Next(); + } else { + DO(ParseUserDefinedType(type_name)); + } + return true; +} + +bool Parser::ParseUserDefinedType(string* type_name) { + type_name->clear(); + + TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); + if (iter != kTypeNames.end()) { + // Note: The only place enum types are allowed is for field types, but + // if we are parsing a field type then we would not get here because + // primitives are allowed there as well. So this error message doesn't + // need to account for enums. + AddError("Expected message type."); + + // Pretend to accept this type so that we can go on parsing. + *type_name = input_->current().text; + input_->Next(); + return true; + } + + // A leading "." means the name is fully-qualified. + if (TryConsume(".")) type_name->append("."); + + // Consume the first part of the name. + string identifier; + DO(ConsumeIdentifier(&identifier, "Expected type name.")); + type_name->append(identifier); + + // Consume more parts. + while (TryConsume(".")) { + type_name->append("."); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + type_name->append(identifier); + } + + return true; +} + +// =================================================================== + +bool Parser::ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location) { + if (file->has_package()) { + AddError("Multiple package definitions."); + // Don't append the new package to the old one. Just replace it. Not + // that it really matters since this is an error anyway. + file->clear_package(); + } + + DO(Consume("package")); + + { + LocationRecorder location(root_location, + FileDescriptorProto::kPackageFieldNumber); + location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); + + while (true) { + string identifier; + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + file->mutable_package()->append(identifier); + if (!TryConsume(".")) break; + file->mutable_package()->append("."); + } + + location.EndAt(input_->previous()); + + DO(ConsumeEndOfDeclaration(";", &location)); + } + + return true; +} + +bool Parser::ParseImport(RepeatedPtrField* dependency, + RepeatedField* public_dependency, + RepeatedField* weak_dependency, + const LocationRecorder& root_location) { + DO(Consume("import")); + if (LookingAt("public")) { + LocationRecorder location( + root_location, FileDescriptorProto::kPublicDependencyFieldNumber, + public_dependency->size()); + DO(Consume("public")); + *public_dependency->Add() = dependency->size(); + } else if (LookingAt("weak")) { + LocationRecorder location( + root_location, FileDescriptorProto::kWeakDependencyFieldNumber, + weak_dependency->size()); + DO(Consume("weak")); + *weak_dependency->Add() = dependency->size(); + } + { + LocationRecorder location(root_location, + FileDescriptorProto::kDependencyFieldNumber, + dependency->size()); + DO(ConsumeString(dependency->Add(), + "Expected a string naming the file to import.")); + + location.EndAt(input_->previous()); + + DO(ConsumeEndOfDeclaration(";", &location)); + } + return true; +} + +// =================================================================== + +SourceLocationTable::SourceLocationTable() {} +SourceLocationTable::~SourceLocationTable() {} + +bool SourceLocationTable::Find( + const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int* line, int* column) const { + const pair* result = + FindOrNull(location_map_, make_pair(descriptor, location)); + if (result == NULL) { + *line = -1; + *column = 0; + return false; + } else { + *line = result->first; + *column = result->second; + return true; + } +} + +void SourceLocationTable::Add( + const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int line, int column) { + location_map_[make_pair(descriptor, location)] = make_pair(line, column); +} + +void SourceLocationTable::Clear() { + location_map_.clear(); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.h new file mode 100644 index 000000000..cfd3649be --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser.h @@ -0,0 +1,477 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Implements parsing of .proto files to FileDescriptorProtos. + +#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__ +#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { class Message; } + +namespace protobuf { +namespace compiler { + +// Defined in this file. +class Parser; +class SourceLocationTable; + +// Implements parsing of protocol definitions (such as .proto files). +// +// Note that most users will be more interested in the Importer class. +// Parser is a lower-level class which simply converts a single .proto file +// to a FileDescriptorProto. It does not resolve import directives or perform +// many other kinds of validation needed to construct a complete +// FileDescriptor. +class LIBPROTOBUF_EXPORT Parser { + public: + Parser(); + ~Parser(); + + // Parse the entire input and construct a FileDescriptorProto representing + // it. Returns true if no errors occurred, false otherwise. + bool Parse(io::Tokenizer* input, FileDescriptorProto* file); + + // Optional fetaures: + + // DEPRECATED: New code should use the SourceCodeInfo embedded in the + // FileDescriptorProto. + // + // Requests that locations of certain definitions be recorded to the given + // SourceLocationTable while parsing. This can be used to look up exact line + // and column numbers for errors reported by DescriptorPool during validation. + // Set to NULL (the default) to discard source location information. + void RecordSourceLocationsTo(SourceLocationTable* location_table) { + source_location_table_ = location_table; + } + + // Requests that errors be recorded to the given ErrorCollector while + // parsing. Set to NULL (the default) to discard error messages. + void RecordErrorsTo(io::ErrorCollector* error_collector) { + error_collector_ = error_collector; + } + + // Returns the identifier used in the "syntax = " declaration, if one was + // seen during the last call to Parse(), or the empty string otherwise. + const string& GetSyntaxIdentifier() { return syntax_identifier_; } + + // If set true, input files will be required to begin with a syntax + // identifier. Otherwise, files may omit this. If a syntax identifier + // is provided, it must be 'syntax = "proto2";' and must appear at the + // top of this file regardless of whether or not it was required. + void SetRequireSyntaxIdentifier(bool value) { + require_syntax_identifier_ = value; + } + + // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop + // parsing as soon as it has seen the syntax identifier, or lack thereof. + // This is useful for quickly identifying the syntax of the file without + // parsing the whole thing. If this is enabled, no error will be recorded + // if the syntax identifier is something other than "proto2" (since + // presumably the caller intends to deal with that), but other kinds of + // errors (e.g. parse errors) will still be reported. When this is enabled, + // you may pass a NULL FileDescriptorProto to Parse(). + void SetStopAfterSyntaxIdentifier(bool value) { + stop_after_syntax_identifier_ = value; + } + + private: + class LocationRecorder; + + // ================================================================= + // Error recovery helpers + + // Consume the rest of the current statement. This consumes tokens + // until it sees one of: + // ';' Consumes the token and returns. + // '{' Consumes the brace then calls SkipRestOfBlock(). + // '}' Returns without consuming. + // EOF Returns (can't consume). + // The Parser often calls SkipStatement() after encountering a syntax + // error. This allows it to go on parsing the following lines, allowing + // it to report more than just one error in the file. + void SkipStatement(); + + // Consume the rest of the current block, including nested blocks, + // ending after the closing '}' is encountered and consumed, or at EOF. + void SkipRestOfBlock(); + + // ----------------------------------------------------------------- + // Single-token consuming helpers + // + // These make parsing code more readable. + + // True if the current token is TYPE_END. + inline bool AtEnd(); + + // True if the next token matches the given text. + inline bool LookingAt(const char* text); + // True if the next token is of the given type. + inline bool LookingAtType(io::Tokenizer::TokenType token_type); + + // If the next token exactly matches the text given, consume it and return + // true. Otherwise, return false without logging an error. + bool TryConsume(const char* text); + + // These attempt to read some kind of token from the input. If successful, + // they return true. Otherwise they return false and add the given error + // to the error list. + + // Consume a token with the exact text given. + bool Consume(const char* text, const char* error); + // Same as above, but automatically generates the error "Expected \"text\".", + // where "text" is the expected token text. + bool Consume(const char* text); + // Consume a token of type IDENTIFIER and store its text in "output". + bool ConsumeIdentifier(string* output, const char* error); + // Consume an integer and store its value in "output". + bool ConsumeInteger(int* output, const char* error); + // Consume a signed integer and store its value in "output". + bool ConsumeSignedInteger(int* output, const char* error); + // Consume a 64-bit integer and store its value in "output". If the value + // is greater than max_value, an error will be reported. + bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error); + // Consume a number and store its value in "output". This will accept + // tokens of either INTEGER or FLOAT type. + bool ConsumeNumber(double* output, const char* error); + // Consume a string literal and store its (unescaped) value in "output". + bool ConsumeString(string* output, const char* error); + + // Consume a token representing the end of the statement. Comments between + // this token and the next will be harvested for documentation. The given + // LocationRecorder should refer to the declaration that was just parsed; + // it will be populated with these comments. + // + // TODO(kenton): The LocationRecorder is const because historically locations + // have been passed around by const reference, for no particularly good + // reason. We should probably go through and change them all to mutable + // pointer to make this more intuitive. + bool TryConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); + bool ConsumeEndOfDeclaration(const char* text, + const LocationRecorder* location); + + // ----------------------------------------------------------------- + // Error logging helpers + + // Invokes error_collector_->AddError(), if error_collector_ is not NULL. + void AddError(int line, int column, const string& error); + + // Invokes error_collector_->AddError() with the line and column number + // of the current token. + void AddError(const string& error); + + // Records a location in the SourceCodeInfo.location table (see + // descriptor.proto). We use RAII to ensure that the start and end locations + // are recorded -- the constructor records the start location and the + // destructor records the end location. Since the parser is + // recursive-descent, this works out beautifully. + class LIBPROTOBUF_EXPORT LocationRecorder { + public: + // Construct the file's "root" location. + LocationRecorder(Parser* parser); + + // Construct a location that represents a declaration nested within the + // given parent. E.g. a field's location is nested within the location + // for a message type. The parent's path will be copied, so you should + // call AddPath() only to add the path components leading from the parent + // to the child (as opposed to leading from the root to the child). + LocationRecorder(const LocationRecorder& parent); + + // Convenience constructors that call AddPath() one or two times. + LocationRecorder(const LocationRecorder& parent, int path1); + LocationRecorder(const LocationRecorder& parent, int path1, int path2); + + ~LocationRecorder(); + + // Add a path component. See SourceCodeInfo.Location.path in + // descriptor.proto. + void AddPath(int path_component); + + // By default the location is considered to start at the current token at + // the time the LocationRecorder is created. StartAt() sets the start + // location to the given token instead. + void StartAt(const io::Tokenizer::Token& token); + + // By default the location is considered to end at the previous token at + // the time the LocationRecorder is destroyed. EndAt() sets the end + // location to the given token instead. + void EndAt(const io::Tokenizer::Token& token); + + // Records the start point of this location to the SourceLocationTable that + // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable + // is an older way of keeping track of source locations which is still + // used in some places. + void RecordLegacyLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location); + + // Attaches leading and trailing comments to the location. The two strings + // will be swapped into place, so after this is called *leading and + // *trailing will be empty. + // + // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for + // why this is const. + void AttachComments(string* leading, string* trailing) const; + + private: + Parser* parser_; + SourceCodeInfo::Location* location_; + + void Init(const LocationRecorder& parent); + }; + + // ================================================================= + // Parsers for various language constructs + + // Parses the "syntax = \"proto2\";" line at the top of the file. Returns + // false if it failed to parse or if the syntax identifier was not + // recognized. + bool ParseSyntaxIdentifier(); + + // These methods parse various individual bits of code. They return + // false if they completely fail to parse the construct. In this case, + // it is probably necessary to skip the rest of the statement to recover. + // However, if these methods return true, it does NOT mean that there + // were no errors; only that there were no *syntax* errors. For instance, + // if a service method is defined using proper syntax but uses a primitive + // type as its input or output, ParseMethodField() still returns true + // and only reports the error by calling AddError(). In practice, this + // makes logic much simpler for the caller. + + // Parse a top-level message, enum, service, etc. + bool ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location); + + // Parse various language high-level language construrcts. + bool ParseMessageDefinition(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location); + bool ParseServiceDefinition(ServiceDescriptorProto* service, + const LocationRecorder& service_location); + bool ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location); + bool ParseImport(RepeatedPtrField* dependency, + RepeatedField* public_dependency, + RepeatedField* weak_dependency, + const LocationRecorder& root_location); + bool ParseOption(Message* options, + const LocationRecorder& options_location); + + // These methods parse the contents of a message, enum, or service type and + // add them to the given object. They consume the entire block including + // the beginning and ending brace. + bool ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location); + bool ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location); + + // Parse one statement within a message, enum, or service block, inclunding + // final semicolon. + bool ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumStatement(EnumDescriptorProto* message, + const LocationRecorder& enum_location); + bool ParseServiceStatement(ServiceDescriptorProto* message, + const LocationRecorder& service_location); + + // Parse a field of a message. If the field is a group, its type will be + // added to "messages". + // + // parent_location and location_field_number_for_nested_type are needed when + // parsing groups -- we need to generate a nested message type within the + // parent and record its location accordingly. Since the parent could be + // either a FileDescriptorProto or a DescriptorProto, we must pass in the + // correct field number to use. + bool ParseMessageField(FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location); + + // Parse an "extensions" declaration. + bool ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location); + + // Parse an "extend" declaration. (See also comments for + // ParseMessageField().) + bool ParseExtend(RepeatedPtrField* extensions, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location); + + // Parse a single enum value within an enum block. + bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location); + + // Parse enum constant options, i.e. the list in square brackets at the end + // of the enum constant value definition. + bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location); + + // Parse a single method within a service definition. + bool ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location); + + + // Parse options of a single method or stream. + bool ParseOptions(const LocationRecorder& parent_location, + const int optionsFieldNumber, + Message* mutable_options); + + // Parse "required", "optional", or "repeated" and fill in "label" + // with the value. + bool ParseLabel(FieldDescriptorProto::Label* label); + + // Parse a type name and fill in "type" (if it is a primitive) or + // "type_name" (if it is not) with the type parsed. + bool ParseType(FieldDescriptorProto::Type* type, + string* type_name); + // Parse a user-defined type and fill in "type_name" with the name. + // If a primitive type is named, it is treated as an error. + bool ParseUserDefinedType(string* type_name); + + // Parses field options, i.e. the stuff in square brackets at the end + // of a field definition. Also parses default value. + bool ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location); + + // Parse the "default" option. This needs special handling because its + // type is the field's type. + bool ParseDefaultAssignment(FieldDescriptorProto* field, + const LocationRecorder& field_location); + + enum OptionStyle { + OPTION_ASSIGNMENT, // just "name = value" + OPTION_STATEMENT // "option name = value;" + }; + + // Parse a single option name/value pair, e.g. "ctype = CORD". The name + // identifies a field of the given Message, and the value of that field + // is set to the parsed value. + bool ParseOption(Message* options, + const LocationRecorder& options_location, + OptionStyle style); + + // Parses a single part of a multipart option name. A multipart name consists + // of names separated by dots. Each name is either an identifier or a series + // of identifiers separated by dots and enclosed in parentheses. E.g., + // "foo.(bar.baz).qux". + bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location); + + // Parses a string surrounded by balanced braces. Strips off the outer + // braces and stores the enclosed string in *value. + // E.g., + // { foo } *value gets 'foo' + // { foo { bar: box } } *value gets 'foo { bar: box }' + // {} *value gets '' + // + // REQUIRES: LookingAt("{") + // When finished successfully, we are looking at the first token past + // the ending brace. + bool ParseUninterpretedBlock(string* value); + + // ================================================================= + + io::Tokenizer* input_; + io::ErrorCollector* error_collector_; + SourceCodeInfo* source_code_info_; + SourceLocationTable* source_location_table_; // legacy + bool had_errors_; + bool require_syntax_identifier_; + bool stop_after_syntax_identifier_; + string syntax_identifier_; + + // Leading doc comments for the next declaration. These are not complete + // yet; use ConsumeEndOfDeclaration() to get the complete comments. + string upcoming_doc_comments_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); +}; + +// A table mapping (descriptor, ErrorLocation) pairs -- as reported by +// DescriptorPool when validating descriptors -- to line and column numbers +// within the original source code. +// +// This is semi-obsolete: FileDescriptorProto.source_code_info now contains +// far more complete information about source locations. However, as of this +// writing you still need to use SourceLocationTable when integrating with +// DescriptorPool. +class LIBPROTOBUF_EXPORT SourceLocationTable { + public: + SourceLocationTable(); + ~SourceLocationTable(); + + // Finds the precise location of the given error and fills in *line and + // *column with the line and column numbers. If not found, sets *line to + // -1 and *column to 0 (since line = -1 is used to mean "error has no exact + // location" in the ErrorCollector interface). Returns true if found, false + // otherwise. + bool Find(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int* line, int* column) const; + + // Adds a location to the table. + void Add(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + int line, int column); + + // Clears the contents of the table. + void Clear(); + + private: + typedef map< + pair, + pair > LocationMap; + LocationMap location_map_; +}; + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser_unittest.cc new file mode 100644 index 000000000..c61ac60ec --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/parser_unittest.cc @@ -0,0 +1,2374 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { + +class MockErrorCollector : public io::ErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(int line, int column, const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", + line, column, message); + } +}; + +class MockValidationErrorCollector : public DescriptorPool::ErrorCollector { + public: + MockValidationErrorCollector(const SourceLocationTable& source_locations, + io::ErrorCollector* wrapped_collector) + : source_locations_(source_locations), + wrapped_collector_(wrapped_collector) {} + ~MockValidationErrorCollector() {} + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, + const string& element_name, + const Message* descriptor, + ErrorLocation location, + const string& message) { + int line, column; + source_locations_.Find(descriptor, location, &line, &column); + wrapped_collector_->AddError(line, column, message); + } + + private: + const SourceLocationTable& source_locations_; + io::ErrorCollector* wrapped_collector_; +}; + +class ParserTest : public testing::Test { + protected: + ParserTest() + : require_syntax_identifier_(false) {} + + // Set up the parser to parse the given text. + void SetupParser(const char* text) { + raw_input_.reset(new io::ArrayInputStream(text, strlen(text))); + input_.reset(new io::Tokenizer(raw_input_.get(), &error_collector_)); + parser_.reset(new Parser()); + parser_->RecordErrorsTo(&error_collector_); + parser_->SetRequireSyntaxIdentifier(require_syntax_identifier_); + } + + // Parse the input and expect that the resulting FileDescriptorProto matches + // the given output. The output is a FileDescriptorProto in protocol buffer + // text format. + void ExpectParsesTo(const char* input, const char* output) { + SetupParser(input); + FileDescriptorProto actual, expected; + + parser_->Parse(input_.get(), &actual); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + ASSERT_EQ("", error_collector_.text_); + + // We don't cover SourceCodeInfo in these tests. + actual.clear_source_code_info(); + + // Parse the ASCII representation in order to canonicalize it. We could + // just compare directly to actual.DebugString(), but that would require + // that the caller precisely match the formatting that DebugString() + // produces. + ASSERT_TRUE(TextFormat::ParseFromString(output, &expected)); + + // Compare by comparing debug strings. + // TODO(kenton): Use differencer, once it is available. + EXPECT_EQ(expected.DebugString(), actual.DebugString()); + } + + // Parse the text and expect that the given errors are reported. + void ExpectHasErrors(const char* text, const char* expected_errors) { + ExpectHasEarlyExitErrors(text, expected_errors); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + } + + // Same as above but does not expect that the parser parses the complete + // input. + void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) { + SetupParser(text); + FileDescriptorProto file; + parser_->Parse(input_.get(), &file); + EXPECT_EQ(expected_errors, error_collector_.text_); + } + + // Parse the text as a file and validate it (with a DescriptorPool), and + // expect that the validation step reports the given errors. + void ExpectHasValidationErrors(const char* text, + const char* expected_errors) { + SetupParser(text); + SourceLocationTable source_locations; + parser_->RecordSourceLocationsTo(&source_locations); + + FileDescriptorProto file; + file.set_name("foo.proto"); + parser_->Parse(input_.get(), &file); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + ASSERT_EQ("", error_collector_.text_); + + MockValidationErrorCollector validation_error_collector( + source_locations, &error_collector_); + EXPECT_TRUE(pool_.BuildFileCollectingErrors( + file, &validation_error_collector) == NULL); + EXPECT_EQ(expected_errors, error_collector_.text_); + } + + MockErrorCollector error_collector_; + DescriptorPool pool_; + + scoped_ptr raw_input_; + scoped_ptr input_; + scoped_ptr parser_; + bool require_syntax_identifier_; +}; + +// =================================================================== + +TEST_F(ParserTest, StopAfterSyntaxIdentifier) { + SetupParser( + "// blah\n" + "syntax = \"foobar\";\n" + "this line will not be parsed\n"); + parser_->SetStopAfterSyntaxIdentifier(true); + EXPECT_TRUE(parser_->Parse(input_.get(), NULL)); + EXPECT_EQ("", error_collector_.text_); + EXPECT_EQ("foobar", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParserTest, StopAfterOmittedSyntaxIdentifier) { + SetupParser( + "// blah\n" + "this line will not be parsed\n"); + parser_->SetStopAfterSyntaxIdentifier(true); + EXPECT_TRUE(parser_->Parse(input_.get(), NULL)); + EXPECT_EQ("", error_collector_.text_); + EXPECT_EQ("", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParserTest, StopAfterSyntaxIdentifierWithErrors) { + SetupParser( + "// blah\n" + "syntax = error;\n"); + parser_->SetStopAfterSyntaxIdentifier(true); + EXPECT_FALSE(parser_->Parse(input_.get(), NULL)); + EXPECT_EQ("1:9: Expected syntax identifier.\n", error_collector_.text_); +} + +// =================================================================== + +typedef ParserTest ParseMessageTest; + +TEST_F(ParseMessageTest, SimpleMessage) { + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); +} + +TEST_F(ParseMessageTest, ImplicitSyntaxIdentifier) { + require_syntax_identifier_ = false; + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); + EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) { + ExpectParsesTo( + "syntax = \"proto2\";\n" + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); + EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) { + require_syntax_identifier_ = true; + ExpectParsesTo( + "syntax = \"proto2\";\n" + "message TestMessage {\n" + " required int32 foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + "}"); + EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseMessageTest, SimpleFields) { + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 15;\n" + " optional int32 bar = 34;\n" + " repeated int32 baz = 3;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:15 }" + " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:34 }" + " field { name:\"baz\" label:LABEL_REPEATED type:TYPE_INT32 number:3 }" + "}"); +} + +TEST_F(ParseMessageTest, PrimitiveFieldTypes) { + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 1;\n" + " required int64 foo = 1;\n" + " required uint32 foo = 1;\n" + " required uint64 foo = 1;\n" + " required sint32 foo = 1;\n" + " required sint64 foo = 1;\n" + " required fixed32 foo = 1;\n" + " required fixed64 foo = 1;\n" + " required sfixed32 foo = 1;\n" + " required sfixed64 foo = 1;\n" + " required float foo = 1;\n" + " required double foo = 1;\n" + " required string foo = 1;\n" + " required bytes foo = 1;\n" + " required bool foo = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT64 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT32 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_UINT64 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT32 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SINT64 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED32 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FIXED64 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED32 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_SFIXED64 number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_FLOAT number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_DOUBLE number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_STRING number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BYTES number:1 }" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_BOOL number:1 }" + "}"); +} + +TEST_F(ParseMessageTest, FieldDefaults) { + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 1 [default= 1 ];\n" + " required int32 foo = 1 [default= -2 ];\n" + " required int64 foo = 1 [default= 3 ];\n" + " required int64 foo = 1 [default= -4 ];\n" + " required uint32 foo = 1 [default= 5 ];\n" + " required uint64 foo = 1 [default= 6 ];\n" + " required float foo = 1 [default= 7.5];\n" + " required float foo = 1 [default= -8.5];\n" + " required float foo = 1 [default= 9 ];\n" + " required double foo = 1 [default= 10.5];\n" + " required double foo = 1 [default=-11.5];\n" + " required double foo = 1 [default= 12 ];\n" + " required double foo = 1 [default= inf ];\n" + " required double foo = 1 [default=-inf ];\n" + " required double foo = 1 [default= nan ];\n" + " required string foo = 1 [default='13\\001'];\n" + " required string foo = 1 [default='a' \"b\" \n \"c\"];\n" + " required bytes foo = 1 [default='14\\002'];\n" + " required bytes foo = 1 [default='a' \"b\" \n 'c'];\n" + " required bool foo = 1 [default=true ];\n" + " required Foo foo = 1 [default=FOO ];\n" + + " required int32 foo = 1 [default= 0x7FFFFFFF];\n" + " required int32 foo = 1 [default=-0x80000000];\n" + " required uint32 foo = 1 [default= 0xFFFFFFFF];\n" + " required int64 foo = 1 [default= 0x7FFFFFFFFFFFFFFF];\n" + " required int64 foo = 1 [default=-0x8000000000000000];\n" + " required uint64 foo = 1 [default= 0xFFFFFFFFFFFFFFFF];\n" + " required double foo = 1 [default= 0xabcd];\n" + "}\n", + +#define ETC "name:\"foo\" label:LABEL_REQUIRED number:1" + "message_type {" + " name: \"TestMessage\"" + " field { type:TYPE_INT32 default_value:\"1\" "ETC" }" + " field { type:TYPE_INT32 default_value:\"-2\" "ETC" }" + " field { type:TYPE_INT64 default_value:\"3\" "ETC" }" + " field { type:TYPE_INT64 default_value:\"-4\" "ETC" }" + " field { type:TYPE_UINT32 default_value:\"5\" "ETC" }" + " field { type:TYPE_UINT64 default_value:\"6\" "ETC" }" + " field { type:TYPE_FLOAT default_value:\"7.5\" "ETC" }" + " field { type:TYPE_FLOAT default_value:\"-8.5\" "ETC" }" + " field { type:TYPE_FLOAT default_value:\"9\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"10.5\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"-11.5\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"12\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"inf\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"-inf\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"nan\" "ETC" }" + " field { type:TYPE_STRING default_value:\"13\\001\" "ETC" }" + " field { type:TYPE_STRING default_value:\"abc\" "ETC" }" + " field { type:TYPE_BYTES default_value:\"14\\\\002\" "ETC" }" + " field { type:TYPE_BYTES default_value:\"abc\" "ETC" }" + " field { type:TYPE_BOOL default_value:\"true\" "ETC" }" + " field { type_name:\"Foo\" default_value:\"FOO\" "ETC" }" + + " field { type:TYPE_INT32 default_value:\"2147483647\" "ETC" }" + " field { type:TYPE_INT32 default_value:\"-2147483648\" "ETC" }" + " field { type:TYPE_UINT32 default_value:\"4294967295\" "ETC" }" + " field { type:TYPE_INT64 default_value:\"9223372036854775807\" "ETC" }" + " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" "ETC" }" + " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" "ETC" }" + " field { type:TYPE_DOUBLE default_value:\"43981\" "ETC" }" + "}"); +#undef ETC +} + +TEST_F(ParseMessageTest, FieldOptions) { + ExpectParsesTo( + "message TestMessage {\n" + " optional string foo = 1\n" + " [ctype=CORD, (foo)=7, foo.(.bar.baz).qux.quux.(corge)=-33, \n" + " (quux)=\"x\040y\", (baz.qux)=hey];\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name: \"foo\" label: LABEL_OPTIONAL type: TYPE_STRING number: 1" + " options { uninterpreted_option: { name { name_part: \"ctype\" " + " is_extension: false } " + " identifier_value: \"CORD\" }" + " uninterpreted_option: { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 7 }" + " uninterpreted_option: { name { name_part: \"foo\" " + " is_extension: false } " + " name { name_part: \".bar.baz\"" + " is_extension: true } " + " name { name_part: \"qux\" " + " is_extension: false } " + " name { name_part: \"quux\" " + " is_extension: false } " + " name { name_part: \"corge\" " + " is_extension: true } " + " negative_int_value: -33 }" + " uninterpreted_option: { name { name_part: \"quux\" " + " is_extension: true } " + " string_value: \"x y\" }" + " uninterpreted_option: { name { name_part: \"baz.qux\" " + " is_extension: true } " + " identifier_value: \"hey\" }" + " }" + " }" + "}"); +} + +TEST_F(ParseMessageTest, Group) { + ExpectParsesTo( + "message TestMessage {\n" + " optional group TestGroup = 1 {};\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " nested_type { name: \"TestGroup\" }" + " field { name:\"testgroup\" label:LABEL_OPTIONAL number:1" + " type:TYPE_GROUP type_name: \"TestGroup\" }" + "}"); +} + +TEST_F(ParseMessageTest, NestedMessage) { + ExpectParsesTo( + "message TestMessage {\n" + " message Nested {}\n" + " optional Nested test_nested = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " nested_type { name: \"Nested\" }" + " field { name:\"test_nested\" label:LABEL_OPTIONAL number:1" + " type_name: \"Nested\" }" + "}"); +} + +TEST_F(ParseMessageTest, NestedEnum) { + ExpectParsesTo( + "message TestMessage {\n" + " enum NestedEnum {}\n" + " optional NestedEnum test_enum = 1;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " enum_type { name: \"NestedEnum\" }" + " field { name:\"test_enum\" label:LABEL_OPTIONAL number:1" + " type_name: \"NestedEnum\" }" + "}"); +} + +TEST_F(ParseMessageTest, ExtensionRange) { + ExpectParsesTo( + "message TestMessage {\n" + " extensions 10 to 19;\n" + " extensions 30 to max;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:10 end:20 }" + " extension_range { start:30 end:536870912 }" + "}"); +} + +TEST_F(ParseMessageTest, CompoundExtensionRange) { + ExpectParsesTo( + "message TestMessage {\n" + " extensions 2, 15, 9 to 11, 100 to max, 3;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:2 end:3 }" + " extension_range { start:15 end:16 }" + " extension_range { start:9 end:12 }" + " extension_range { start:100 end:536870912 }" + " extension_range { start:3 end:4 }" + "}"); +} + +TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) { + // Messages using the message_set_wire_format option can accept larger + // extension numbers, as the numbers are not encoded as int32 field values + // rather than tags. + ExpectParsesTo( + "message TestMessage {\n" + " extensions 4 to max;\n" + " option message_set_wire_format = true;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension_range { start:4 end: 0x7fffffff }" + " options {\n" + " uninterpreted_option { \n" + " name {\n" + " name_part: \"message_set_wire_format\"\n" + " is_extension: false\n" + " }\n" + " identifier_value: \"true\"\n" + " }\n" + " }\n" + "}"); +} + +TEST_F(ParseMessageTest, Extensions) { + ExpectParsesTo( + "extend Extendee1 { optional int32 foo = 12; }\n" + "extend Extendee2 { repeated TestMessage bar = 22; }\n", + + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" + " extendee: \"Extendee1\" } " + "extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee2\" }"); +} + +TEST_F(ParseMessageTest, ExtensionsInMessageScope) { + ExpectParsesTo( + "message TestMessage {\n" + " extend Extendee1 { optional int32 foo = 12; }\n" + " extend Extendee2 { repeated TestMessage bar = 22; }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" + " extendee: \"Extendee1\" }" + " extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee2\" }" + "}"); +} + +TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { + ExpectParsesTo( + "extend Extendee1 {\n" + " optional int32 foo = 12;\n" + " repeated TestMessage bar = 22;\n" + "}\n", + + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:12" + " extendee: \"Extendee1\" } " + "extension { name:\"bar\" label:LABEL_REPEATED number:22" + " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); +} + +// =================================================================== + +typedef ParserTest ParseEnumTest; + +TEST_F(ParseEnumTest, SimpleEnum) { + ExpectParsesTo( + "enum TestEnum {\n" + " FOO = 0;\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:0 }" + "}"); +} + +TEST_F(ParseEnumTest, Values) { + ExpectParsesTo( + "enum TestEnum {\n" + " FOO = 13;\n" + " BAR = -10;\n" + " BAZ = 500;\n" + " HEX_MAX = 0x7FFFFFFF;\n" + " HEX_MIN = -0x80000000;\n" + " INT_MAX = 2147483647;\n" + " INT_MIN = -2147483648;\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"FOO\" number:13 }" + " value { name:\"BAR\" number:-10 }" + " value { name:\"BAZ\" number:500 }" + " value { name:\"HEX_MAX\" number:2147483647 }" + " value { name:\"HEX_MIN\" number:-2147483648 }" + " value { name:\"INT_MAX\" number:2147483647 }" + " value { name:\"INT_MIN\" number:-2147483648 }" + "}"); +} + +TEST_F(ParseEnumTest, ValueOptions) { + ExpectParsesTo( + "enum TestEnum {\n" + " FOO = 13;\n" + " BAR = -10 [ (something.text) = 'abc' ];\n" + " BAZ = 500 [ (something.text) = 'def', other = 1 ];\n" + "}\n", + + "enum_type {" + " name: \"TestEnum\"" + " value { name: \"FOO\" number: 13 }" + " value { name: \"BAR\" number: -10 " + " options { " + " uninterpreted_option { " + " name { name_part: \"something.text\" is_extension: true } " + " string_value: \"abc\" " + " } " + " } " + " } " + " value { name: \"BAZ\" number: 500 " + " options { " + " uninterpreted_option { " + " name { name_part: \"something.text\" is_extension: true } " + " string_value: \"def\" " + " } " + " uninterpreted_option { " + " name { name_part: \"other\" is_extension: false } " + " positive_int_value: 1 " + " } " + " } " + " } " + "}"); +} + +// =================================================================== + +typedef ParserTest ParseServiceTest; + +TEST_F(ParseServiceTest, SimpleService) { + ExpectParsesTo( + "service TestService {\n" + " rpc Foo(In) returns (Out);\n" + "}\n", + + "service {" + " name: \"TestService\"" + " method { name:\"Foo\" input_type:\"In\" output_type:\"Out\" }" + "}"); +} + +TEST_F(ParseServiceTest, MethodsAndStreams) { + ExpectParsesTo( + "service TestService {\n" + " rpc Foo(In1) returns (Out1);\n" + " rpc Bar(In2) returns (Out2);\n" + " rpc Baz(In3) returns (Out3);\n" + "}\n", + + "service {" + " name: \"TestService\"" + " method { name:\"Foo\" input_type:\"In1\" output_type:\"Out1\" }" + " method { name:\"Bar\" input_type:\"In2\" output_type:\"Out2\" }" + " method { name:\"Baz\" input_type:\"In3\" output_type:\"Out3\" }" + "}"); +} + +// =================================================================== +// imports and packages + +typedef ParserTest ParseMiscTest; + +TEST_F(ParseMiscTest, ParseImport) { + ExpectParsesTo( + "import \"foo/bar/baz.proto\";\n", + "dependency: \"foo/bar/baz.proto\""); +} + +TEST_F(ParseMiscTest, ParseMultipleImports) { + ExpectParsesTo( + "import \"foo.proto\";\n" + "import \"bar.proto\";\n" + "import \"baz.proto\";\n", + "dependency: \"foo.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\""); +} + +TEST_F(ParseMiscTest, ParsePublicImports) { + ExpectParsesTo( + "import \"foo.proto\";\n" + "import public \"bar.proto\";\n" + "import \"baz.proto\";\n" + "import public \"qux.proto\";\n", + "dependency: \"foo.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"qux.proto\"" + "public_dependency: 1 " + "public_dependency: 3 "); +} + +TEST_F(ParseMiscTest, ParsePackage) { + ExpectParsesTo( + "package foo.bar.baz;\n", + "package: \"foo.bar.baz\""); +} + +TEST_F(ParseMiscTest, ParsePackageWithSpaces) { + ExpectParsesTo( + "package foo . bar. \n" + " baz;\n", + "package: \"foo.bar.baz\""); +} + +// =================================================================== +// options + +TEST_F(ParseMiscTest, ParseFileOptions) { + ExpectParsesTo( + "option java_package = \"com.google.foo\";\n" + "option optimize_for = CODE_SIZE;", + + "options {" + "uninterpreted_option { name { name_part: \"java_package\" " + " is_extension: false }" + " string_value: \"com.google.foo\"} " + "uninterpreted_option { name { name_part: \"optimize_for\" " + " is_extension: false }" + " identifier_value: \"CODE_SIZE\" } " + "}"); +} + +// =================================================================== +// Error tests +// +// There are a very large number of possible errors that the parser could +// report, so it's infeasible to test every single one of them. Instead, +// we test each unique call to AddError() in parser.h. This does not mean +// we are testing every possible error that Parser can generate because +// each variant of the Consume() helper only counts as one unique call to +// AddError(). + +typedef ParserTest ParseErrorTest; + +TEST_F(ParseErrorTest, MissingSyntaxIdentifier) { + require_syntax_identifier_ = true; + ExpectHasEarlyExitErrors( + "message TestMessage {}", + "0:0: File must begin with 'syntax = \"proto2\";'.\n"); + EXPECT_EQ("", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) { + ExpectHasEarlyExitErrors( + "syntax = \"no_such_syntax\";", + "0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser " + "only recognizes \"proto2\".\n"); + EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseErrorTest, SimpleSyntaxError) { + ExpectHasErrors( + "message TestMessage @#$ { blah }", + "0:20: Expected \"{\".\n"); + EXPECT_EQ("proto2", parser_->GetSyntaxIdentifier()); +} + +TEST_F(ParseErrorTest, ExpectedTopLevel) { + ExpectHasErrors( + "blah;", + "0:0: Expected top-level statement (e.g. \"message\").\n"); +} + +TEST_F(ParseErrorTest, UnmatchedCloseBrace) { + // This used to cause an infinite loop. Doh. + ExpectHasErrors( + "}", + "0:0: Expected top-level statement (e.g. \"message\").\n" + "0:0: Unmatched \"}\".\n"); +} + +// ------------------------------------------------------------------- +// Message errors + +TEST_F(ParseErrorTest, MessageMissingName) { + ExpectHasErrors( + "message {}", + "0:8: Expected message name.\n"); +} + +TEST_F(ParseErrorTest, MessageMissingBody) { + ExpectHasErrors( + "message TestMessage;", + "0:19: Expected \"{\".\n"); +} + +TEST_F(ParseErrorTest, EofInMessage) { + ExpectHasErrors( + "message TestMessage {", + "0:21: Reached end of input in message definition (missing '}').\n"); +} + +TEST_F(ParseErrorTest, MissingFieldNumber) { + ExpectHasErrors( + "message TestMessage {\n" + " optional int32 foo;\n" + "}\n", + "1:20: Missing field number.\n"); +} + +TEST_F(ParseErrorTest, ExpectedFieldNumber) { + ExpectHasErrors( + "message TestMessage {\n" + " optional int32 foo = ;\n" + "}\n", + "1:23: Expected field number.\n"); +} + +TEST_F(ParseErrorTest, FieldNumberOutOfRange) { + ExpectHasErrors( + "message TestMessage {\n" + " optional int32 foo = 0x100000000;\n" + "}\n", + "1:23: Integer out of range.\n"); +} + +TEST_F(ParseErrorTest, MissingLabel) { + ExpectHasErrors( + "message TestMessage {\n" + " int32 foo = 1;\n" + "}\n", + "1:2: Expected \"required\", \"optional\", or \"repeated\".\n"); +} + +TEST_F(ParseErrorTest, ExpectedOptionName) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [];\n" + "}\n", + "1:27: Expected identifier.\n"); +} + +TEST_F(ParseErrorTest, NonExtensionOptionNameBeginningWithDot) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [.foo=1];\n" + "}\n", + "1:27: Expected identifier.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [default=true];\n" + "}\n", + "1:35: Expected integer.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueNotBoolean) { + ExpectHasErrors( + "message TestMessage {\n" + " optional bool foo = 1 [default=blah];\n" + "}\n", + "1:33: Expected \"true\" or \"false\".\n"); +} + +TEST_F(ParseErrorTest, DefaultValueNotString) { + ExpectHasErrors( + "message TestMessage {\n" + " optional string foo = 1 [default=1];\n" + "}\n", + "1:35: Expected string.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [default=-1];\n" + "}\n", + "1:36: Unsigned field can't have negative default value.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueTooLarge) { + ExpectHasErrors( + "message TestMessage {\n" + " optional int32 foo = 1 [default= 0x80000000];\n" + " optional int32 foo = 1 [default=-0x80000001];\n" + " optional uint32 foo = 1 [default= 0x100000000];\n" + " optional int64 foo = 1 [default= 0x80000000000000000];\n" + " optional int64 foo = 1 [default=-0x80000000000000001];\n" + " optional uint64 foo = 1 [default= 0x100000000000000000];\n" + "}\n", + "1:36: Integer out of range.\n" + "2:36: Integer out of range.\n" + "3:36: Integer out of range.\n" + "4:36: Integer out of range.\n" + "5:36: Integer out of range.\n" + "6:36: Integer out of range.\n"); +} + +TEST_F(ParseErrorTest, EnumValueOutOfRange) { + ExpectHasErrors( + "enum TestEnum {\n" + " HEX_TOO_BIG = 0x80000000;\n" + " HEX_TOO_SMALL = -0x80000001;\n" + " INT_TOO_BIG = 2147483648;\n" + " INT_TOO_SMALL = -2147483649;\n" + "}\n", + "1:19: Integer out of range.\n" + "2:19: Integer out of range.\n" + "3:19: Integer out of range.\n" + "4:19: Integer out of range.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueMissing) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [default=];\n" + "}\n", + "1:35: Expected integer.\n"); +} + +TEST_F(ParseErrorTest, DefaultValueForGroup) { + ExpectHasErrors( + "message TestMessage {\n" + " optional group Foo = 1 [default=blah] {}\n" + "}\n", + "1:34: Messages can't have default values.\n"); +} + +TEST_F(ParseErrorTest, DuplicateDefaultValue) { + ExpectHasErrors( + "message TestMessage {\n" + " optional uint32 foo = 1 [default=1,default=2];\n" + "}\n", + "1:37: Already set option \"default\".\n"); +} + +TEST_F(ParseErrorTest, GroupNotCapitalized) { + ExpectHasErrors( + "message TestMessage {\n" + " optional group foo = 1 {}\n" + "}\n", + "1:17: Group names must start with a capital letter.\n"); +} + +TEST_F(ParseErrorTest, GroupMissingBody) { + ExpectHasErrors( + "message TestMessage {\n" + " optional group Foo = 1;\n" + "}\n", + "1:24: Missing group body.\n"); +} + +TEST_F(ParseErrorTest, ExtendingPrimitive) { + ExpectHasErrors( + "extend int32 { optional string foo = 4; }\n", + "0:7: Expected message type.\n"); +} + +TEST_F(ParseErrorTest, ErrorInExtension) { + ExpectHasErrors( + "message Foo { extensions 100 to 199; }\n" + "extend Foo { optional string foo; }\n", + "1:32: Missing field number.\n"); +} + +TEST_F(ParseErrorTest, MultipleParseErrors) { + // When a statement has a parse error, the parser should be able to continue + // parsing at the next statement. + ExpectHasErrors( + "message TestMessage {\n" + " optional int32 foo;\n" + " !invalid statement ending in a block { blah blah { blah } blah }\n" + " optional int32 bar = 3 {}\n" + "}\n", + "1:20: Missing field number.\n" + "2:2: Expected \"required\", \"optional\", or \"repeated\".\n" + "2:2: Expected type name.\n" + "3:25: Expected \";\".\n"); +} + +TEST_F(ParseErrorTest, EofInAggregateValue) { + ExpectHasErrors( + "option (fileopt) = { i:100\n", + "1:0: Unexpected end of stream while parsing aggregate value.\n"); +} + +// ------------------------------------------------------------------- +// Enum errors + +TEST_F(ParseErrorTest, EofInEnum) { + ExpectHasErrors( + "enum TestEnum {", + "0:15: Reached end of input in enum definition (missing '}').\n"); +} + +TEST_F(ParseErrorTest, EnumValueMissingNumber) { + ExpectHasErrors( + "enum TestEnum {\n" + " FOO;\n" + "}\n", + "1:5: Missing numeric value for enum constant.\n"); +} + +// ------------------------------------------------------------------- +// Service errors + +TEST_F(ParseErrorTest, EofInService) { + ExpectHasErrors( + "service TestService {", + "0:21: Reached end of input in service definition (missing '}').\n"); +} + +TEST_F(ParseErrorTest, ServiceMethodPrimitiveParams) { + ExpectHasErrors( + "service TestService {\n" + " rpc Foo(int32) returns (string);\n" + "}\n", + "1:10: Expected message type.\n" + "1:26: Expected message type.\n"); +} + + +TEST_F(ParseErrorTest, EofInMethodOptions) { + ExpectHasErrors( + "service TestService {\n" + " rpc Foo(Bar) returns(Bar) {", + "1:29: Reached end of input in method options (missing '}').\n" + "1:29: Reached end of input in service definition (missing '}').\n"); +} + + +TEST_F(ParseErrorTest, PrimitiveMethodInput) { + ExpectHasErrors( + "service TestService {\n" + " rpc Foo(int32) returns(Bar);\n" + "}\n", + "1:10: Expected message type.\n"); +} + + +TEST_F(ParseErrorTest, MethodOptionTypeError) { + // This used to cause an infinite loop. + ExpectHasErrors( + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Baz) { option invalid syntax; }\n" + "}\n", + "2:45: Expected \"=\".\n"); +} + + +// ------------------------------------------------------------------- +// Import and package errors + +TEST_F(ParseErrorTest, ImportNotQuoted) { + ExpectHasErrors( + "import foo;\n", + "0:7: Expected a string naming the file to import.\n"); +} + +TEST_F(ParseErrorTest, MultiplePackagesInFile) { + ExpectHasErrors( + "package foo;\n" + "package bar;\n", + "1:0: Multiple package definitions.\n"); +} + +// =================================================================== +// Test that errors detected by DescriptorPool correctly report line and +// column numbers. We have one test for every call to RecordLocation() in +// parser.cc. + +typedef ParserTest ParserValidationErrorTest; + +TEST_F(ParserValidationErrorTest, PackageNameError) { + // Create another file which defines symbol "foo". + FileDescriptorProto other_file; + other_file.set_name("bar.proto"); + other_file.add_message_type()->set_name("foo"); + EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); + + // Now try to define it as a package. + ExpectHasValidationErrors( + "package foo.bar;", + "0:8: \"foo\" is already defined (as something other than a package) " + "in file \"bar.proto\".\n"); +} + +TEST_F(ParserValidationErrorTest, MessageNameError) { + ExpectHasValidationErrors( + "message Foo {}\n" + "message Foo {}\n", + "1:8: \"Foo\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, FieldNameError) { + ExpectHasValidationErrors( + "message Foo {\n" + " optional int32 bar = 1;\n" + " optional int32 bar = 2;\n" + "}\n", + "2:17: \"bar\" is already defined in \"Foo\".\n"); +} + +TEST_F(ParserValidationErrorTest, FieldTypeError) { + ExpectHasValidationErrors( + "message Foo {\n" + " optional Baz bar = 1;\n" + "}\n", + "1:11: \"Baz\" is not defined.\n"); +} + +TEST_F(ParserValidationErrorTest, FieldNumberError) { + ExpectHasValidationErrors( + "message Foo {\n" + " optional int32 bar = 0;\n" + "}\n", + "1:23: Field numbers must be positive integers.\n"); +} + +TEST_F(ParserValidationErrorTest, FieldExtendeeError) { + ExpectHasValidationErrors( + "extend Baz { optional int32 bar = 1; }\n", + "0:7: \"Baz\" is not defined.\n"); +} + +TEST_F(ParserValidationErrorTest, FieldDefaultValueError) { + ExpectHasValidationErrors( + "enum Baz { QUX = 1; }\n" + "message Foo {\n" + " optional Baz bar = 1 [default=NO_SUCH_VALUE];\n" + "}\n", + "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n"); +} + +TEST_F(ParserValidationErrorTest, FileOptionNameError) { + ExpectHasValidationErrors( + "option foo = 5;", + "0:7: Option \"foo\" unknown.\n"); +} + +TEST_F(ParserValidationErrorTest, FileOptionValueError) { + ExpectHasValidationErrors( + "option java_outer_classname = 5;", + "0:30: Value must be quoted string for string option " + "\"google.protobuf.FileOptions.java_outer_classname\".\n"); +} + +TEST_F(ParserValidationErrorTest, FieldOptionNameError) { + ExpectHasValidationErrors( + "message Foo {\n" + " optional bool bar = 1 [foo=1];\n" + "}\n", + "1:25: Option \"foo\" unknown.\n"); +} + +TEST_F(ParserValidationErrorTest, FieldOptionValueError) { + ExpectHasValidationErrors( + "message Foo {\n" + " optional int32 bar = 1 [ctype=1];\n" + "}\n", + "1:32: Value must be identifier for enum-valued option " + "\"google.protobuf.FieldOptions.ctype\".\n"); +} + +TEST_F(ParserValidationErrorTest, ExtensionRangeNumberError) { + ExpectHasValidationErrors( + "message Foo {\n" + " extensions 0;\n" + "}\n", + "1:13: Extension numbers must be positive integers.\n"); +} + +TEST_F(ParserValidationErrorTest, EnumNameError) { + ExpectHasValidationErrors( + "enum Foo {A = 1;}\n" + "enum Foo {B = 1;}\n", + "1:5: \"Foo\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, EnumValueNameError) { + ExpectHasValidationErrors( + "enum Foo {\n" + " BAR = 1;\n" + " BAR = 1;\n" + "}\n", + "2:2: \"BAR\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, ServiceNameError) { + ExpectHasValidationErrors( + "service Foo {}\n" + "service Foo {}\n", + "1:8: \"Foo\" is already defined.\n"); +} + +TEST_F(ParserValidationErrorTest, MethodNameError) { + ExpectHasValidationErrors( + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Baz);\n" + " rpc Bar(Baz) returns(Baz);\n" + "}\n", + "3:6: \"Bar\" is already defined in \"Foo\".\n"); +} + + +TEST_F(ParserValidationErrorTest, MethodInputTypeError) { + ExpectHasValidationErrors( + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Qux) returns(Baz);\n" + "}\n", + "2:10: \"Qux\" is not defined.\n"); +} + + +TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { + ExpectHasValidationErrors( + "message Baz {}\n" + "service Foo {\n" + " rpc Bar(Baz) returns(Qux);\n" + "}\n", + "2:23: \"Qux\" is not defined.\n"); +} + + +// =================================================================== +// Test that the output from FileDescriptor::DebugString() (and all other +// descriptor types) is parseable, and results in the same Descriptor +// definitions again afoter parsing (not, however, that the order of messages +// cannot be guaranteed to be the same) + +typedef ParserTest ParseDecriptorDebugTest; + +class CompareDescriptorNames { + public: + bool operator()(const DescriptorProto* left, const DescriptorProto* right) { + return left->name() < right->name(); + } +}; + +// Sorts nested DescriptorProtos of a DescriptoProto, by name. +void SortMessages(DescriptorProto *descriptor_proto) { + int size = descriptor_proto->nested_type_size(); + // recursively sort; we can't guarantee the order of nested messages either + for (int i = 0; i < size; ++i) { + SortMessages(descriptor_proto->mutable_nested_type(i)); + } + DescriptorProto **data = + descriptor_proto->mutable_nested_type()->mutable_data(); + sort(data, data + size, CompareDescriptorNames()); +} + +// Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. +void SortMessages(FileDescriptorProto *file_descriptor_proto) { + int size = file_descriptor_proto->message_type_size(); + // recursively sort; we can't guarantee the order of nested messages either + for (int i = 0; i < size; ++i) { + SortMessages(file_descriptor_proto->mutable_message_type(i)); + } + DescriptorProto **data = + file_descriptor_proto->mutable_message_type()->mutable_data(); + sort(data, data + size, CompareDescriptorNames()); +} + +TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { + const FileDescriptor* original_file = + protobuf_unittest::TestAllTypes::descriptor()->file(); + FileDescriptorProto expected; + original_file->CopyTo(&expected); + + // Get the DebugString of the unittest.proto FileDecriptor, which includes + // all other descriptor types + string debug_string = original_file->DebugString(); + + // Parse the debug string + SetupParser(debug_string.c_str()); + FileDescriptorProto parsed; + parser_->Parse(input_.get(), &parsed); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + ASSERT_EQ("", error_collector_.text_); + + // We now have a FileDescriptorProto, but to compare with the expected we + // need to link to a FileDecriptor, then output back to a proto. We'll + // also need to give it the same name as the original. + parsed.set_name("google/protobuf/unittest.proto"); + // We need the imported dependency before we can build our parsed proto + const FileDescriptor* public_import = + protobuf_unittest_import::PublicImportMessage::descriptor()->file(); + FileDescriptorProto public_import_proto; + public_import->CopyTo(&public_import_proto); + ASSERT_TRUE(pool_.BuildFile(public_import_proto) != NULL); + const FileDescriptor* import = + protobuf_unittest_import::ImportMessage::descriptor()->file(); + FileDescriptorProto import_proto; + import->CopyTo(&import_proto); + ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); + const FileDescriptor* actual = pool_.BuildFile(parsed); + parsed.Clear(); + actual->CopyTo(&parsed); + ASSERT_TRUE(actual != NULL); + + // The messages might be in different orders, making them hard to compare. + // So, sort the messages in the descriptor protos (including nested messages, + // recursively). + SortMessages(&expected); + SortMessages(&parsed); + + // I really wanted to use StringDiff here for the debug output on fail, + // but the strings are too long for it, and if I increase its max size, + // we get a memory allocation failure :( + EXPECT_EQ(expected.DebugString(), parsed.DebugString()); +} + +TEST_F(ParseDecriptorDebugTest, TestCustomOptions) { + const FileDescriptor* original_file = + protobuf_unittest::AggregateMessage::descriptor()->file(); + FileDescriptorProto expected; + original_file->CopyTo(&expected); + + string debug_string = original_file->DebugString(); + + // Parse the debug string + SetupParser(debug_string.c_str()); + FileDescriptorProto parsed; + parser_->Parse(input_.get(), &parsed); + EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); + ASSERT_EQ("", error_collector_.text_); + + // We now have a FileDescriptorProto, but to compare with the expected we + // need to link to a FileDecriptor, then output back to a proto. We'll + // also need to give it the same name as the original. + parsed.set_name(original_file->name()); + + // unittest_custom_options.proto depends on descriptor.proto. + const FileDescriptor* import = FileDescriptorProto::descriptor()->file(); + FileDescriptorProto import_proto; + import->CopyTo(&import_proto); + ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); + const FileDescriptor* actual = pool_.BuildFile(parsed); + ASSERT_TRUE(actual != NULL); + parsed.Clear(); + actual->CopyTo(&parsed); + + // The messages might be in different orders, making them hard to compare. + // So, sort the messages in the descriptor protos (including nested messages, + // recursively). + SortMessages(&expected); + SortMessages(&parsed); + + EXPECT_EQ(expected.DebugString(), parsed.DebugString()); +} + +// =================================================================== +// SourceCodeInfo tests. + +// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a +// message to a particular sub-field. +// * If the target is itself a message, sets *output_message to point at it, +// *output_field to NULL, and *output_index to -1. +// * Otherwise, if the target is an element of a repeated field, sets +// *output_message to the containing message, *output_field to the descriptor +// of the field, and *output_index to the index of the element. +// * Otherwise, the target is a field (possibly a repeated field, but not any +// one element). Sets *output_message to the containing message, +// *output_field to the descriptor of the field, and *output_index to -1. +// Returns true if the path was valid, false otherwise. A gTest failure is +// recorded before returning false. +bool FollowPath(const Message& root, + const int* path_begin, const int* path_end, + const Message** output_message, + const FieldDescriptor** output_field, + int* output_index) { + if (path_begin == path_end) { + // Path refers to this whole message. + *output_message = &root; + *output_field = NULL; + *output_index = -1; + return true; + } + + const Descriptor* descriptor = root.GetDescriptor(); + const Reflection* reflection = root.GetReflection(); + + const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin); + + if (field == NULL) { + ADD_FAILURE() << descriptor->name() << " has no field number: " + << *path_begin; + return false; + } + + ++path_begin; + + if (field->is_repeated()) { + if (path_begin == path_end) { + // Path refers to the whole repeated field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } + + int index = *path_begin++; + int size = reflection->FieldSize(root, field); + + if (index >= size) { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " has size " << size << ", but path contained index: " + << index; + return false; + } + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Descend into child message. + const Message& child = reflection->GetRepeatedMessage(root, field, index); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this element. + *output_message = &root; + *output_field = field; + *output_index = index; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Message& child = reflection->GetMessage(root, field); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } +} + +// Check if two spans are equal. +bool CompareSpans(const RepeatedField& span1, + const RepeatedField& span2) { + if (span1.size() != span2.size()) return false; + for (int i = 0; i < span1.size(); i++) { + if (span1.Get(i) != span2.Get(i)) return false; + } + return true; +} + +// Test fixture for source info tests, which check that source locations are +// recorded correctly in FileDescriptorProto.source_code_info.location. +class SourceInfoTest : public ParserTest { + protected: + // The parsed file (initialized by Parse()). + FileDescriptorProto file_; + + // Parse the given text as a .proto file and populate the spans_ map with + // all the source location spans in its SourceCodeInfo table. + bool Parse(const char* text) { + ExtractMarkers(text); + SetupParser(text_without_markers_.c_str()); + if (!parser_->Parse(input_.get(), &file_)) { + return false; + } + + const SourceCodeInfo& source_info = file_.source_code_info(); + for (int i = 0; i < source_info.location_size(); i++) { + const SourceCodeInfo::Location& location = source_info.location(i); + const Message* descriptor_proto = NULL; + const FieldDescriptor* field = NULL; + int index = 0; + if (!FollowPath(file_, location.path().begin(), location.path().end(), + &descriptor_proto, &field, &index)) { + return false; + } + + spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), + &location)); + } + + return true; + } + + virtual void TearDown() { + EXPECT_TRUE(spans_.empty()) + << "Forgot to call HasSpan() for:\n" + << spans_.begin()->second->DebugString(); + } + + // ----------------------------------------------------------------- + // HasSpan() checks that the span of source code delimited by the given + // tags (comments) correspond via the SourceCodeInfo table to the given + // part of the FileDescriptorProto. (If unclear, look at the actual tests; + // it should quickly become obvious.) + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto) { + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); + } + + bool HasSpanWithComment(char start_marker, char end_marker, + const Message& descriptor_proto, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, NULL, -1, + expected_leading_comments, expected_trailing_comments); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, const string& field_name) { + return HasSpan(start_marker, end_marker, descriptor_proto, field_name, -1); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, const string& field_name, + int index) { + return HasSpan(start_marker, end_marker, descriptor_proto, + field_name, index, NULL, NULL); + } + + bool HasSpan(char start_marker, char end_marker, + const Message& descriptor_proto, + const string& field_name, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + const FieldDescriptor* field = + descriptor_proto.GetDescriptor()->FindFieldByName(field_name); + if (field == NULL) { + ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() + << " has no such field: " << field_name; + return false; + } + + return HasSpanWithComment( + start_marker, end_marker, descriptor_proto, field, index, + expected_leading_comments, expected_trailing_comments); + } + + bool HasSpan(const Message& descriptor_proto) { + return HasSpanWithComment( + '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name) { + return HasSpan('\0', '\0', descriptor_proto, field_name, -1); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name, + int index) { + return HasSpan('\0', '\0', descriptor_proto, field_name, index); + } + + bool HasSpanWithComment(char start_marker, char end_marker, + const Message& descriptor_proto, + const FieldDescriptor* field, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments) { + pair range = + spans_.equal_range(SpanKey(descriptor_proto, field, index)); + + if (start_marker == '\0') { + if (range.first == range.second) { + return false; + } else { + spans_.erase(range.first); + return true; + } + } else { + pair start_pos = FindOrDie(markers_, start_marker); + pair end_pos = FindOrDie(markers_, end_marker); + + RepeatedField expected_span; + expected_span.Add(start_pos.first); + expected_span.Add(start_pos.second); + if (end_pos.first != start_pos.first) { + expected_span.Add(end_pos.first); + } + expected_span.Add(end_pos.second); + + for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) { + if (CompareSpans(expected_span, iter->second->span())) { + if (expected_leading_comments == NULL) { + EXPECT_FALSE(iter->second->has_leading_comments()); + } else { + EXPECT_TRUE(iter->second->has_leading_comments()); + EXPECT_EQ(expected_leading_comments, + iter->second->leading_comments()); + } + if (expected_trailing_comments == NULL) { + EXPECT_FALSE(iter->second->has_trailing_comments()); + } else { + EXPECT_TRUE(iter->second->has_trailing_comments()); + EXPECT_EQ(expected_trailing_comments, + iter->second->trailing_comments()); + } + + spans_.erase(iter); + return true; + } + } + + return false; + } + } + + private: + struct SpanKey { + const Message* descriptor_proto; + const FieldDescriptor* field; + int index; + + inline SpanKey() {} + inline SpanKey(const Message& descriptor_proto_param, + const FieldDescriptor* field_param, + int index_param) + : descriptor_proto(&descriptor_proto_param), field(field_param), + index(index_param) {} + + inline bool operator<(const SpanKey& other) const { + if (descriptor_proto < other.descriptor_proto) return true; + if (descriptor_proto > other.descriptor_proto) return false; + if (field < other.field) return true; + if (field > other.field) return false; + return index < other.index; + } + }; + + typedef multimap SpanMap; + SpanMap spans_; + map > markers_; + string text_without_markers_; + + void ExtractMarkers(const char* text) { + markers_.clear(); + text_without_markers_.clear(); + int line = 0; + int column = 0; + while (*text != '\0') { + if (*text == '$') { + ++text; + GOOGLE_CHECK_NE('\0', *text); + if (*text == '$') { + text_without_markers_ += '$'; + ++column; + } else { + markers_[*text] = make_pair(line, column); + ++text; + GOOGLE_CHECK_EQ('$', *text); + } + } else if (*text == '\n') { + ++line; + column = 0; + text_without_markers_ += *text; + } else { + text_without_markers_ += *text; + ++column; + } + ++text; + } + } +}; + +TEST_F(SourceInfoTest, BasicFileDecls) { + EXPECT_TRUE(Parse( + "$a$syntax = \"proto2\";\n" + "package $b$foo.bar$c$;\n" + "import $d$\"baz.proto\"$e$;\n" + "import $f$\"qux.proto\"$g$;$h$\n" + "\n" + "// comment ignored\n")); + + EXPECT_TRUE(HasSpan('a', 'h', file_)); + EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); + EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); + EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); +} + +TEST_F(SourceInfoTest, Messages) { + EXPECT_TRUE(Parse( + "$a$message $b$Foo$c$ {}$d$\n" + "$e$message $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.message_type(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.message_type(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.message_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, Fields) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$optional$b$ $c$int32$d$ $e$bar$f$ = $g$1$h$;$i$\n" + " $j$repeated$k$ $l$X.Y$m$ $n$baz$o$ = $p$2$q$;$r$\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).field(0); + const FieldDescriptorProto& field2 = file_.message_type(0).field(1); + + EXPECT_TRUE(HasSpan('a', 'i', field1)); + EXPECT_TRUE(HasSpan('a', 'b', field1, "label")); + EXPECT_TRUE(HasSpan('c', 'd', field1, "type")); + EXPECT_TRUE(HasSpan('e', 'f', field1, "name")); + EXPECT_TRUE(HasSpan('g', 'h', field1, "number")); + + EXPECT_TRUE(HasSpan('j', 'r', field2)); + EXPECT_TRUE(HasSpan('j', 'k', field2, "label")); + EXPECT_TRUE(HasSpan('l', 'm', field2, "type_name")); + EXPECT_TRUE(HasSpan('n', 'o', field2, "name")); + EXPECT_TRUE(HasSpan('p', 'q', field2, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Extensions) { + EXPECT_TRUE(Parse( + "$a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + "}$j$\n" + "$k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + "}$p$\n")); + + const FieldDescriptorProto& field1 = file_.extension(0); + const FieldDescriptorProto& field2 = file_.extension(1); + const FieldDescriptorProto& field3 = file_.extension(2); + + EXPECT_TRUE(HasSpan('a', 'j', file_, "extension")); + EXPECT_TRUE(HasSpan('k', 'p', file_, "extension")); + + EXPECT_TRUE(HasSpan('d', 'f', field1)); + EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); + + EXPECT_TRUE(HasSpan('g', 'i', field2)); + EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); + + EXPECT_TRUE(HasSpan('n', 'o', field3)); + EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, NestedExtensions) { + EXPECT_TRUE(Parse( + "message Message {\n" + " $a$extend $b$Foo$c$ {\n" + " $d$optional$e$ int32 bar = 1;$f$\n" + " $g$repeated$h$ X.Y baz = 2;$i$\n" + " }$j$\n" + " $k$extend $l$Bar$m$ {\n" + " $n$optional int32 qux = 1;$o$\n" + " }$p$\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).extension(0); + const FieldDescriptorProto& field2 = file_.message_type(0).extension(1); + const FieldDescriptorProto& field3 = file_.message_type(0).extension(2); + + EXPECT_TRUE(HasSpan('a', 'j', file_.message_type(0), "extension")); + EXPECT_TRUE(HasSpan('k', 'p', file_.message_type(0), "extension")); + + EXPECT_TRUE(HasSpan('d', 'f', field1)); + EXPECT_TRUE(HasSpan('d', 'e', field1, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field1, "extendee")); + + EXPECT_TRUE(HasSpan('g', 'i', field2)); + EXPECT_TRUE(HasSpan('g', 'h', field2, "label")); + EXPECT_TRUE(HasSpan('b', 'c', field2, "extendee")); + + EXPECT_TRUE(HasSpan('n', 'o', field3)); + EXPECT_TRUE(HasSpan('l', 'm', field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, ExtensionRanges) { + EXPECT_TRUE(Parse( + "message Message {\n" + " $a$extensions $b$1$c$ to $d$4$e$, $f$6$g$;$h$\n" + " $i$extensions $j$8$k$ to $l$max$m$;$n$\n" + "}\n")); + + const DescriptorProto::ExtensionRange& range1 = + file_.message_type(0).extension_range(0); + const DescriptorProto::ExtensionRange& range2 = + file_.message_type(0).extension_range(1); + const DescriptorProto::ExtensionRange& range3 = + file_.message_type(0).extension_range(2); + + EXPECT_TRUE(HasSpan('a', 'h', file_.message_type(0), "extension_range")); + EXPECT_TRUE(HasSpan('i', 'n', file_.message_type(0), "extension_range")); + + EXPECT_TRUE(HasSpan('b', 'e', range1)); + EXPECT_TRUE(HasSpan('b', 'c', range1, "start")); + EXPECT_TRUE(HasSpan('d', 'e', range1, "end")); + + EXPECT_TRUE(HasSpan('f', 'g', range2)); + EXPECT_TRUE(HasSpan('f', 'g', range2, "start")); + EXPECT_TRUE(HasSpan('f', 'g', range2, "end")); + + EXPECT_TRUE(HasSpan('j', 'm', range3)); + EXPECT_TRUE(HasSpan('j', 'k', range3, "start")); + EXPECT_TRUE(HasSpan('l', 'm', range3, "end")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, NestedMessages) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$message $b$Bar$c$ {\n" + " $d$message $e$Baz$f$ {}$g$\n" + " }$h$\n" + " $i$message $j$Qux$k$ {}$l$\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = bar.nested_type(0); + const DescriptorProto& qux = file_.message_type(0).nested_type(1); + + EXPECT_TRUE(HasSpan('a', 'h', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('d', 'g', baz)); + EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); + EXPECT_TRUE(HasSpan('i', 'l', qux)); + EXPECT_TRUE(HasSpan('j', 'k', qux, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Groups) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " message Bar {}\n" + " $a$optional$b$ $c$group$d$ $e$Baz$f$ = $g$1$h$ {\n" + " $i$message Qux {}$j$\n" + " }$k$\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = file_.message_type(0).nested_type(1); + const DescriptorProto& qux = baz.nested_type(0); + const FieldDescriptorProto& field = file_.message_type(0).field(0); + + EXPECT_TRUE(HasSpan('a', 'k', field)); + EXPECT_TRUE(HasSpan('a', 'b', field, "label")); + EXPECT_TRUE(HasSpan('c', 'd', field, "type")); + EXPECT_TRUE(HasSpan('e', 'f', field, "name")); + EXPECT_TRUE(HasSpan('e', 'f', field, "type_name")); + EXPECT_TRUE(HasSpan('g', 'h', field, "number")); + + EXPECT_TRUE(HasSpan('a', 'k', baz)); + EXPECT_TRUE(HasSpan('e', 'f', baz, "name")); + EXPECT_TRUE(HasSpan('i', 'j', qux)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(bar)); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(qux, "name")); +} + +TEST_F(SourceInfoTest, Enums) { + EXPECT_TRUE(Parse( + "$a$enum $b$Foo$c$ {}$d$\n" + "$e$enum $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.enum_type(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.enum_type(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.enum_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, EnumValues) { + EXPECT_TRUE(Parse( + "enum Foo {\n" + " $a$BAR$b$ = $c$1$d$;$e$\n" + " $f$BAZ$g$ = $h$2$i$;$j$\n" + "}")); + + const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0); + const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1); + + EXPECT_TRUE(HasSpan('a', 'e', bar)); + EXPECT_TRUE(HasSpan('a', 'b', bar, "name")); + EXPECT_TRUE(HasSpan('c', 'd', bar, "number")); + EXPECT_TRUE(HasSpan('f', 'j', baz)); + EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); + EXPECT_TRUE(HasSpan('h', 'i', baz, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); +} + +TEST_F(SourceInfoTest, NestedEnums) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$enum $b$Bar$c$ {}$d$\n" + " $e$enum $f$Baz$g$ {}$h$\n" + "}\n")); + + const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0); + const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1); + + EXPECT_TRUE(HasSpan('a', 'd', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('e', 'h', baz)); + EXPECT_TRUE(HasSpan('f', 'g', baz, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Services) { + EXPECT_TRUE(Parse( + "$a$service $b$Foo$c$ {}$d$\n" + "$e$service $f$Bar$g$ {}$h$\n")); + + EXPECT_TRUE(HasSpan('a', 'd', file_.service(0))); + EXPECT_TRUE(HasSpan('b', 'c', file_.service(0), "name")); + EXPECT_TRUE(HasSpan('e', 'h', file_.service(1))); + EXPECT_TRUE(HasSpan('f', 'g', file_.service(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, MethodsAndStreams) { + EXPECT_TRUE(Parse( + "service Foo {\n" + " $a$rpc $b$Bar$c$($d$X$e$) returns($f$Y$g$);$h$" + " $i$rpc $j$Baz$k$($l$Z$m$) returns($n$W$o$);$p$" + "}")); + + const MethodDescriptorProto& bar = file_.service(0).method(0); + const MethodDescriptorProto& baz = file_.service(0).method(1); + + EXPECT_TRUE(HasSpan('a', 'h', bar)); + EXPECT_TRUE(HasSpan('b', 'c', bar, "name")); + EXPECT_TRUE(HasSpan('d', 'e', bar, "input_type")); + EXPECT_TRUE(HasSpan('f', 'g', bar, "output_type")); + + EXPECT_TRUE(HasSpan('i', 'p', baz)); + EXPECT_TRUE(HasSpan('j', 'k', baz, "name")); + EXPECT_TRUE(HasSpan('l', 'm', baz, "input_type")); + EXPECT_TRUE(HasSpan('n', 'o', baz, "output_type")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.service(0))); + EXPECT_TRUE(HasSpan(file_.service(0), "name")); +} + +TEST_F(SourceInfoTest, Options) { + EXPECT_TRUE(Parse( + "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " + "$h$123$i$;$j$\n" + "$k$option qux = $l$-123$m$;$n$\n" + "$o$option corge = $p$abc$q$;$r$\n" + "$s$option grault = $t$'blah'$u$;$v$\n" + "$w$option garply = $x${ yadda yadda }$y$;$z$\n" + "$0$option waldo = $1$123.0$2$;$3$\n" + )); + + const UninterpretedOption& option1 = file_.options().uninterpreted_option(0); + const UninterpretedOption& option2 = file_.options().uninterpreted_option(1); + const UninterpretedOption& option3 = file_.options().uninterpreted_option(2); + const UninterpretedOption& option4 = file_.options().uninterpreted_option(3); + const UninterpretedOption& option5 = file_.options().uninterpreted_option(4); + const UninterpretedOption& option6 = file_.options().uninterpreted_option(5); + + EXPECT_TRUE(HasSpan('a', 'j', file_.options())); + EXPECT_TRUE(HasSpan('a', 'j', option1)); + EXPECT_TRUE(HasSpan('b', 'g', option1, "name")); + EXPECT_TRUE(HasSpan('b', 'c', option1.name(0))); + EXPECT_TRUE(HasSpan('b', 'c', option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan('d', 'g', option1.name(1))); + EXPECT_TRUE(HasSpan('e', 'f', option1.name(1), "name_part")); + EXPECT_TRUE(HasSpan('h', 'i', option1, "positive_int_value")); + + EXPECT_TRUE(HasSpan('k', 'n', file_.options())); + EXPECT_TRUE(HasSpan('l', 'm', option2, "negative_int_value")); + + EXPECT_TRUE(HasSpan('o', 'r', file_.options())); + EXPECT_TRUE(HasSpan('p', 'q', option3, "identifier_value")); + + EXPECT_TRUE(HasSpan('s', 'v', file_.options())); + EXPECT_TRUE(HasSpan('t', 'u', option4, "string_value")); + + EXPECT_TRUE(HasSpan('w', 'z', file_.options())); + EXPECT_TRUE(HasSpan('x', 'y', option5, "aggregate_value")); + + EXPECT_TRUE(HasSpan('0', '3', file_.options())); + EXPECT_TRUE(HasSpan('1', '2', option6, "double_value")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(option2)); + EXPECT_TRUE(HasSpan(option3)); + EXPECT_TRUE(HasSpan(option4)); + EXPECT_TRUE(HasSpan(option5)); + EXPECT_TRUE(HasSpan(option6)); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option3, "name")); + EXPECT_TRUE(HasSpan(option4, "name")); + EXPECT_TRUE(HasSpan(option5, "name")); + EXPECT_TRUE(HasSpan(option6, "name")); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option3.name(0))); + EXPECT_TRUE(HasSpan(option4.name(0))); + EXPECT_TRUE(HasSpan(option5.name(0))); + EXPECT_TRUE(HasSpan(option6.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option3.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option4.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option5.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option6.name(0), "name_part")); +} + +TEST_F(SourceInfoTest, ScopedOptions) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$option mopt = 1;$b$\n" + "}\n" + "enum Bar {\n" + " $c$option eopt = 1;$d$\n" + "}\n" + "service Baz {\n" + " $e$option sopt = 1;$f$\n" + " rpc M(X) returns(Y) {\n" + " $g$option mopt = 1;$h$\n" + " }\n" + "}\n")); + + EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); + EXPECT_TRUE(HasSpan('c', 'd', file_.enum_type(0).options())); + EXPECT_TRUE(HasSpan('e', 'f', file_.service(0).options())); + EXPECT_TRUE(HasSpan('g', 'h', file_.service(0).method(0).options())); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0))); + EXPECT_TRUE(HasSpan(file_.service(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "positive_int_value")); +} + +TEST_F(SourceInfoTest, FieldOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for field options is understood. + EXPECT_TRUE(Parse( + "message Foo {" + " optional int32 bar = 1 " + "$a$[default=$b$123$c$,$d$opt1=123$e$," + "$f$opt2='hi'$g$]$h$;" + "}\n" + )); + + const FieldDescriptorProto& field = file_.message_type(0).field(0); + const UninterpretedOption& option1 = field.options().uninterpreted_option(0); + const UninterpretedOption& option2 = field.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan('a', 'h', field.options())); + EXPECT_TRUE(HasSpan('b', 'c', field, "default_value")); + EXPECT_TRUE(HasSpan('d', 'e', option1)); + EXPECT_TRUE(HasSpan('f', 'g', option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field)); + EXPECT_TRUE(HasSpan(field, "label")); + EXPECT_TRUE(HasSpan(field, "type")); + EXPECT_TRUE(HasSpan(field, "name")); + EXPECT_TRUE(HasSpan(field, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + +TEST_F(SourceInfoTest, EnumValueOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for enum options is understood. + EXPECT_TRUE(Parse( + "enum Foo {" + " BAR = 1 $a$[$b$opt1=123$c$,$d$opt2='hi'$e$]$f$;" + "}\n" + )); + + const EnumValueDescriptorProto& value = file_.enum_type(0).value(0); + const UninterpretedOption& option1 = value.options().uninterpreted_option(0); + const UninterpretedOption& option2 = value.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan('a', 'f', value.options())); + EXPECT_TRUE(HasSpan('b', 'c', option1)); + EXPECT_TRUE(HasSpan('d', 'e', option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(value)); + EXPECT_TRUE(HasSpan(value, "name")); + EXPECT_TRUE(HasSpan(value, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + +TEST_F(SourceInfoTest, DocComments) { + EXPECT_TRUE(Parse( + "// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " // Foo trailing\n" + " // line 2\n" + "\n" + " // ignored\n" + "\n" + " // bar leading\n" + " $b$optional int32 bar = 1;$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, + " Foo leading\n line 2\n", + " Foo trailing\n line 2\n")); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); +} + +TEST_F(SourceInfoTest, DocComments2) { + EXPECT_TRUE(Parse( + "// ignored\n" + "syntax = \"proto2\";\n" + "// Foo leading\n" + "// line 2\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " * line 2 */\n" + " // ignored\n" + " /* bar leading\n" + " */" + " $b$optional int32 bar = 1;$c$ // bar trailing\n" + " // ignored\n" + "}$d$\n" + "// ignored\n" + "\n" + "// option leading\n" + "$e$option baz = 123;$f$\n" + "// option trailing\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + const UninterpretedOption& baz = file_.options().uninterpreted_option(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, + " Foo leading\n line 2\n", + " Foo trailing\n line 2 ")); + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, + " option leading\n", + " option trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); + EXPECT_TRUE(HasSpan(file_.options())); + EXPECT_TRUE(HasSpan(baz, "name")); + EXPECT_TRUE(HasSpan(baz.name(0))); + EXPECT_TRUE(HasSpan(baz.name(0), "name_part")); + EXPECT_TRUE(HasSpan(baz, "positive_int_value")); +} + +TEST_F(SourceInfoTest, DocComments3) { + EXPECT_TRUE(Parse( + "$a$message Foo {\n" + " // bar leading\n" + " $b$optional int32 bar = 1 [(baz.qux) = {}];$c$\n" + " // bar trailing\n" + "}$d$\n" + "// ignored\n" + )); + + const DescriptorProto& foo = file_.message_type(0); + const FieldDescriptorProto& bar = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, + " bar leading\n", + " bar trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "label")); + EXPECT_TRUE(HasSpan(bar, "type")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar, "number")); + EXPECT_TRUE(HasSpan(bar.options())); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(bar.options().uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan( + bar.options().uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan( + bar.options().uninterpreted_option(0), "aggregate_value")); +} + +// =================================================================== + +} // anonymous namespace + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.cc new file mode 100644 index 000000000..727f94216 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.cc @@ -0,0 +1,163 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include + +#include +#include + +#ifdef _WIN32 +#include +#include +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#else +#include +#endif + +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace compiler { + +class GeneratorResponseContext : public GeneratorContext { + public: + GeneratorResponseContext(CodeGeneratorResponse* response, + const vector& parsed_files) + : response_(response), + parsed_files_(parsed_files) {} + virtual ~GeneratorResponseContext() {} + + // implements GeneratorContext -------------------------------------- + + virtual io::ZeroCopyOutputStream* Open(const string& filename) { + CodeGeneratorResponse::File* file = response_->add_file(); + file->set_name(filename); + return new io::StringOutputStream(file->mutable_content()); + } + + virtual io::ZeroCopyOutputStream* OpenForInsert( + const string& filename, const string& insertion_point) { + CodeGeneratorResponse::File* file = response_->add_file(); + file->set_name(filename); + file->set_insertion_point(insertion_point); + return new io::StringOutputStream(file->mutable_content()); + } + + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } + + private: + CodeGeneratorResponse* response_; + const vector& parsed_files_; +}; + +int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { + + if (argc > 1) { + cerr << argv[0] << ": Unknown option: " << argv[1] << endl; + return 1; + } + +#ifdef _WIN32 + _setmode(STDIN_FILENO, _O_BINARY); + _setmode(STDOUT_FILENO, _O_BINARY); +#endif + + CodeGeneratorRequest request; + if (!request.ParseFromFileDescriptor(STDIN_FILENO)) { + cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl; + return 1; + } + + DescriptorPool pool; + for (int i = 0; i < request.proto_file_size(); i++) { + const FileDescriptor* file = pool.BuildFile(request.proto_file(i)); + if (file == NULL) { + // BuildFile() already wrote an error message. + return 1; + } + } + + vector parsed_files; + for (int i = 0; i < request.file_to_generate_size(); i++) { + parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); + if (parsed_files.back() == NULL) { + cerr << argv[0] << ": protoc asked plugin to generate a file but " + "did not provide a descriptor for the file: " + << request.file_to_generate(i) << endl; + return 1; + } + } + + CodeGeneratorResponse response; + GeneratorResponseContext context(&response, parsed_files); + + for (int i = 0; i < parsed_files.size(); i++) { + const FileDescriptor* file = parsed_files[i]; + + string error; + bool succeeded = generator->Generate( + file, request.parameter(), &context, &error); + + if (!succeeded && error.empty()) { + error = "Code generator returned false but provided no error " + "description."; + } + if (!error.empty()) { + response.set_error(file->name() + ": " + error); + break; + } + } + + if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) { + cerr << argv[0] << ": Error writing to stdout." << endl; + return 1; + } + + return 0; +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.h new file mode 100644 index 000000000..6fa2de127 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.h @@ -0,0 +1,72 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// Front-end for protoc code generator plugins written in C++. +// +// To implement a protoc plugin in C++, simply write an implementation of +// CodeGenerator, then create a main() function like: +// int main(int argc, char* argv[]) { +// MyCodeGenerator generator; +// return google::protobuf::compiler::PluginMain(argc, argv, &generator); +// } +// You must link your plugin against libprotobuf and libprotoc. +// +// To get protoc to use the plugin, do one of the following: +// * Place the plugin binary somewhere in the PATH and give it the name +// "protoc-gen-NAME" (replacing "NAME" with the name of your plugin). If you +// then invoke protoc with the parameter --NAME_out=OUT_DIR (again, replace +// "NAME" with your plugin's name), protoc will invoke your plugin to generate +// the output, which will be placed in OUT_DIR. +// * Place the plugin binary anywhere, with any name, and pass the --plugin +// parameter to protoc to direct it to your plugin like so: +// protoc --plugin=protoc-gen-NAME=path/to/mybinary --NAME_out=OUT_DIR +// On Windows, make sure to include the .exe suffix: +// protoc --plugin=protoc-gen-NAME=path/to/mybinary.exe --NAME_out=OUT_DIR + +#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ +#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ + +#include +namespace google { +namespace protobuf { +namespace compiler { + +class CodeGenerator; // code_generator.h + +// Implements main() for a protoc plugin exposing the given code generator. +LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator); + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.cc new file mode 100644 index 000000000..ee14dcf72 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.cc @@ -0,0 +1,1090 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/compiler/plugin.proto + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "google/protobuf/compiler/plugin.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { + +const ::google::protobuf::Descriptor* CodeGeneratorRequest_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + CodeGeneratorRequest_reflection_ = NULL; +const ::google::protobuf::Descriptor* CodeGeneratorResponse_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + CodeGeneratorResponse_reflection_ = NULL; +const ::google::protobuf::Descriptor* CodeGeneratorResponse_File_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + CodeGeneratorResponse_File_reflection_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "google/protobuf/compiler/plugin.proto"); + GOOGLE_CHECK(file != NULL); + CodeGeneratorRequest_descriptor_ = file->message_type(0); + static const int CodeGeneratorRequest_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_), + }; + CodeGeneratorRequest_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + CodeGeneratorRequest_descriptor_, + CodeGeneratorRequest::default_instance_, + CodeGeneratorRequest_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(CodeGeneratorRequest)); + CodeGeneratorResponse_descriptor_ = file->message_type(1); + static const int CodeGeneratorResponse_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_), + }; + CodeGeneratorResponse_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + CodeGeneratorResponse_descriptor_, + CodeGeneratorResponse::default_instance_, + CodeGeneratorResponse_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(CodeGeneratorResponse)); + CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0); + static const int CodeGeneratorResponse_File_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_), + }; + CodeGeneratorResponse_File_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + CodeGeneratorResponse_File_descriptor_, + CodeGeneratorResponse_File::default_instance_, + CodeGeneratorResponse_File_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(CodeGeneratorResponse_File)); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + delete CodeGeneratorRequest::default_instance_; + delete CodeGeneratorRequest_reflection_; + delete CodeGeneratorResponse::default_instance_; + delete CodeGeneratorResponse_reflection_; + delete CodeGeneratorResponse_File::default_instance_; + delete CodeGeneratorResponse_File_reflection_; +} + +void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n%google/protobuf/compiler/plugin.proto\022" + "\030google.protobuf.compiler\032 google/protob" + "uf/descriptor.proto\"}\n\024CodeGeneratorRequ" + "est\022\030\n\020file_to_generate\030\001 \003(\t\022\021\n\tparamet" + "er\030\002 \001(\t\0228\n\nproto_file\030\017 \003(\0132$.google.pr" + "otobuf.FileDescriptorProto\"\252\001\n\025CodeGener" + "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003(" + "\01324.google.protobuf.compiler.CodeGenerat" + "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n" + "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB" + ",\n\034com.google.protobuf.compilerB\014PluginP" + "rotos", 445); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); + CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest(); + CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse(); + CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File(); + CodeGeneratorRequest::default_instance_->InitAsDefaultInstance(); + CodeGeneratorResponse::default_instance_->InitAsDefaultInstance(); + CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto { + StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + } +} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_; + +// =================================================================== + +#ifndef _MSC_VER +const int CodeGeneratorRequest::kFileToGenerateFieldNumber; +const int CodeGeneratorRequest::kParameterFieldNumber; +const int CodeGeneratorRequest::kProtoFileFieldNumber; +#endif // !_MSC_VER + +CodeGeneratorRequest::CodeGeneratorRequest() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void CodeGeneratorRequest::InitAsDefaultInstance() { +} + +CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void CodeGeneratorRequest::SharedCtor() { + _cached_size_ = 0; + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +CodeGeneratorRequest::~CodeGeneratorRequest() { + SharedDtor(); +} + +void CodeGeneratorRequest::SharedDtor() { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { + delete parameter_; + } + if (this != default_instance_) { + } +} + +void CodeGeneratorRequest::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() { + protobuf_AssignDescriptorsOnce(); + return CodeGeneratorRequest_descriptor_; +} + +const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; +} + +CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL; + +CodeGeneratorRequest* CodeGeneratorRequest::New() const { + return new CodeGeneratorRequest; +} + +void CodeGeneratorRequest::Clear() { + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { + if (has_parameter()) { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { + parameter_->clear(); + } + } + } + file_to_generate_.Clear(); + proto_file_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool CodeGeneratorRequest::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated string file_to_generate = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_file_to_generate: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_file_to_generate())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->file_to_generate(this->file_to_generate_size() - 1).data(), + this->file_to_generate(this->file_to_generate_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_file_to_generate; + if (input->ExpectTag(18)) goto parse_parameter; + break; + } + + // optional string parameter = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_parameter: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_parameter())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->parameter().data(), this->parameter().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(122)) goto parse_proto_file; + break; + } + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + case 15: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_proto_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_proto_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(122)) goto parse_proto_file; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void CodeGeneratorRequest::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated string file_to_generate = 1; + for (int i = 0; i < this->file_to_generate_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->file_to_generate(i).data(), this->file_to_generate(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->file_to_generate(i), output); + } + + // optional string parameter = 2; + if (has_parameter()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->parameter().data(), this->parameter().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->parameter(), output); + } + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + for (int i = 0; i < this->proto_file_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 15, this->proto_file(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated string file_to_generate = 1; + for (int i = 0; i < this->file_to_generate_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->file_to_generate(i).data(), this->file_to_generate(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(1, this->file_to_generate(i), target); + } + + // optional string parameter = 2; + if (has_parameter()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->parameter().data(), this->parameter().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->parameter(), target); + } + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + for (int i = 0; i < this->proto_file_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 15, this->proto_file(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int CodeGeneratorRequest::ByteSize() const { + int total_size = 0; + + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { + // optional string parameter = 2; + if (has_parameter()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->parameter()); + } + + } + // repeated string file_to_generate = 1; + total_size += 1 * this->file_to_generate_size(); + for (int i = 0; i < this->file_to_generate_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->file_to_generate(i)); + } + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + total_size += 1 * this->proto_file_size(); + for (int i = 0; i < this->proto_file_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->proto_file(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const CodeGeneratorRequest* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { + GOOGLE_CHECK_NE(&from, this); + file_to_generate_.MergeFrom(from.file_to_generate_); + proto_file_.MergeFrom(from.proto_file_); + if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { + if (from.has_parameter()) { + set_parameter(from.parameter()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool CodeGeneratorRequest::IsInitialized() const { + + for (int i = 0; i < proto_file_size(); i++) { + if (!this->proto_file(i).IsInitialized()) return false; + } + return true; +} + +void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { + if (other != this) { + file_to_generate_.Swap(&other->file_to_generate_); + std::swap(parameter_, other->parameter_); + proto_file_.Swap(&other->proto_file_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = CodeGeneratorRequest_descriptor_; + metadata.reflection = CodeGeneratorRequest_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int CodeGeneratorResponse_File::kNameFieldNumber; +const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; +const int CodeGeneratorResponse_File::kContentFieldNumber; +#endif // !_MSC_VER + +CodeGeneratorResponse_File::CodeGeneratorResponse_File() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void CodeGeneratorResponse_File::InitAsDefaultInstance() { +} + +CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void CodeGeneratorResponse_File::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { + SharedDtor(); +} + +void CodeGeneratorResponse_File::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { + delete insertion_point_; + } + if (content_ != &::google::protobuf::internal::kEmptyString) { + delete content_; + } + if (this != default_instance_) { + } +} + +void CodeGeneratorResponse_File::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() { + protobuf_AssignDescriptorsOnce(); + return CodeGeneratorResponse_File_descriptor_; +} + +const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; +} + +CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL; + +CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const { + return new CodeGeneratorResponse_File; +} + +void CodeGeneratorResponse_File::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_insertion_point()) { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { + insertion_point_->clear(); + } + } + if (has_content()) { + if (content_ != &::google::protobuf::internal::kEmptyString) { + content_->clear(); + } + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool CodeGeneratorResponse_File::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_insertion_point; + break; + } + + // optional string insertion_point = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_insertion_point: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_insertion_point())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->insertion_point().data(), this->insertion_point().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(122)) goto parse_content; + break; + } + + // optional string content = 15; + case 15: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_content: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_content())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->content().data(), this->content().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void CodeGeneratorResponse_File::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // optional string insertion_point = 2; + if (has_insertion_point()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->insertion_point().data(), this->insertion_point().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->insertion_point(), output); + } + + // optional string content = 15; + if (has_content()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->content().data(), this->content().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 15, this->content(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // optional string insertion_point = 2; + if (has_insertion_point()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->insertion_point().data(), this->insertion_point().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->insertion_point(), target); + } + + // optional string content = 15; + if (has_content()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->content().data(), this->content().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 15, this->content(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int CodeGeneratorResponse_File::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional string insertion_point = 2; + if (has_insertion_point()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->insertion_point()); + } + + // optional string content = 15; + if (has_content()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->content()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const CodeGeneratorResponse_File* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_insertion_point()) { + set_insertion_point(from.insertion_point()); + } + if (from.has_content()) { + set_content(from.content()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool CodeGeneratorResponse_File::IsInitialized() const { + + return true; +} + +void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(insertion_point_, other->insertion_point_); + std::swap(content_, other->content_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = CodeGeneratorResponse_File_descriptor_; + metadata.reflection = CodeGeneratorResponse_File_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int CodeGeneratorResponse::kErrorFieldNumber; +const int CodeGeneratorResponse::kFileFieldNumber; +#endif // !_MSC_VER + +CodeGeneratorResponse::CodeGeneratorResponse() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void CodeGeneratorResponse::InitAsDefaultInstance() { +} + +CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void CodeGeneratorResponse::SharedCtor() { + _cached_size_ = 0; + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +CodeGeneratorResponse::~CodeGeneratorResponse() { + SharedDtor(); +} + +void CodeGeneratorResponse::SharedDtor() { + if (error_ != &::google::protobuf::internal::kEmptyString) { + delete error_; + } + if (this != default_instance_) { + } +} + +void CodeGeneratorResponse::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() { + protobuf_AssignDescriptorsOnce(); + return CodeGeneratorResponse_descriptor_; +} + +const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + return *default_instance_; +} + +CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL; + +CodeGeneratorResponse* CodeGeneratorResponse::New() const { + return new CodeGeneratorResponse; +} + +void CodeGeneratorResponse::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_error()) { + if (error_ != &::google::protobuf::internal::kEmptyString) { + error_->clear(); + } + } + } + file_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool CodeGeneratorResponse::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string error = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_error())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->error().data(), this->error().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(122)) goto parse_file; + break; + } + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + case 15: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(122)) goto parse_file; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void CodeGeneratorResponse::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string error = 1; + if (has_error()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->error().data(), this->error().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->error(), output); + } + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + for (int i = 0; i < this->file_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 15, this->file(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string error = 1; + if (has_error()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->error().data(), this->error().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->error(), target); + } + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + for (int i = 0; i < this->file_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 15, this->file(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int CodeGeneratorResponse::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string error = 1; + if (has_error()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->error()); + } + + } + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + total_size += 1 * this->file_size(); + for (int i = 0; i < this->file_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->file(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const CodeGeneratorResponse* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { + GOOGLE_CHECK_NE(&from, this); + file_.MergeFrom(from.file_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_error()) { + set_error(from.error()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool CodeGeneratorResponse::IsInitialized() const { + + return true; +} + +void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) { + if (other != this) { + std::swap(error_, other->error_); + file_.Swap(&other->file_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = CodeGeneratorResponse_descriptor_; + metadata.reflection = CodeGeneratorResponse_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace compiler +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.h new file mode 100644 index 000000000..68cc21c7f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.pb.h @@ -0,0 +1,856 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/compiler/plugin.proto + +#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED +#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2005000 +#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 2005000 < 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 "google/protobuf/descriptor.pb.h" +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { +namespace compiler { + +// Internal implementation detail -- do not call these. +void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); +void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); +void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + +class CodeGeneratorRequest; +class CodeGeneratorResponse; +class CodeGeneratorResponse_File; + +// =================================================================== + +class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message { + public: + CodeGeneratorRequest(); + virtual ~CodeGeneratorRequest(); + + CodeGeneratorRequest(const CodeGeneratorRequest& from); + + inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const CodeGeneratorRequest& default_instance(); + + void Swap(CodeGeneratorRequest* other); + + // implements Message ---------------------------------------------- + + CodeGeneratorRequest* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const CodeGeneratorRequest& from); + void MergeFrom(const CodeGeneratorRequest& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated string file_to_generate = 1; + inline int file_to_generate_size() const; + inline void clear_file_to_generate(); + static const int kFileToGenerateFieldNumber = 1; + inline const ::std::string& file_to_generate(int index) const; + inline ::std::string* mutable_file_to_generate(int index); + inline void set_file_to_generate(int index, const ::std::string& value); + inline void set_file_to_generate(int index, const char* value); + inline void set_file_to_generate(int index, const char* value, size_t size); + inline ::std::string* add_file_to_generate(); + inline void add_file_to_generate(const ::std::string& value); + inline void add_file_to_generate(const char* value); + inline void add_file_to_generate(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); + + // optional string parameter = 2; + inline bool has_parameter() const; + inline void clear_parameter(); + static const int kParameterFieldNumber = 2; + inline const ::std::string& parameter() const; + inline void set_parameter(const ::std::string& value); + inline void set_parameter(const char* value); + inline void set_parameter(const char* value, size_t size); + inline ::std::string* mutable_parameter(); + inline ::std::string* release_parameter(); + inline void set_allocated_parameter(::std::string* parameter); + + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + inline int proto_file_size() const; + inline void clear_proto_file(); + static const int kProtoFileFieldNumber = 15; + inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; + inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); + inline ::google::protobuf::FileDescriptorProto* add_proto_file(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + proto_file() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + mutable_proto_file(); + + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) + private: + inline void set_has_parameter(); + inline void clear_has_parameter(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; + ::std::string* parameter_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + + void InitAsDefaultInstance(); + static CodeGeneratorRequest* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message { + public: + CodeGeneratorResponse_File(); + virtual ~CodeGeneratorResponse_File(); + + CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from); + + inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const CodeGeneratorResponse_File& default_instance(); + + void Swap(CodeGeneratorResponse_File* other); + + // implements Message ---------------------------------------------- + + CodeGeneratorResponse_File* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const CodeGeneratorResponse_File& from); + void MergeFrom(const CodeGeneratorResponse_File& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // optional string insertion_point = 2; + inline bool has_insertion_point() const; + inline void clear_insertion_point(); + static const int kInsertionPointFieldNumber = 2; + inline const ::std::string& insertion_point() const; + inline void set_insertion_point(const ::std::string& value); + inline void set_insertion_point(const char* value); + inline void set_insertion_point(const char* value, size_t size); + inline ::std::string* mutable_insertion_point(); + inline ::std::string* release_insertion_point(); + inline void set_allocated_insertion_point(::std::string* insertion_point); + + // optional string content = 15; + inline bool has_content() const; + inline void clear_content(); + static const int kContentFieldNumber = 15; + inline const ::std::string& content() const; + inline void set_content(const ::std::string& value); + inline void set_content(const char* value); + inline void set_content(const char* value, size_t size); + inline ::std::string* mutable_content(); + inline ::std::string* release_content(); + inline void set_allocated_content(::std::string* content); + + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_insertion_point(); + inline void clear_has_insertion_point(); + inline void set_has_content(); + inline void clear_has_content(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::std::string* insertion_point_; + ::std::string* content_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + + void InitAsDefaultInstance(); + static CodeGeneratorResponse_File* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message { + public: + CodeGeneratorResponse(); + virtual ~CodeGeneratorResponse(); + + CodeGeneratorResponse(const CodeGeneratorResponse& from); + + inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const CodeGeneratorResponse& default_instance(); + + void Swap(CodeGeneratorResponse* other); + + // implements Message ---------------------------------------------- + + CodeGeneratorResponse* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const CodeGeneratorResponse& from); + void MergeFrom(const CodeGeneratorResponse& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef CodeGeneratorResponse_File File; + + // accessors ------------------------------------------------------- + + // optional string error = 1; + inline bool has_error() const; + inline void clear_error(); + static const int kErrorFieldNumber = 1; + inline const ::std::string& error() const; + inline void set_error(const ::std::string& value); + inline void set_error(const char* value); + inline void set_error(const char* value, size_t size); + inline ::std::string* mutable_error(); + inline ::std::string* release_error(); + inline void set_allocated_error(::std::string* error); + + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + inline int file_size() const; + inline void clear_file(); + static const int kFileFieldNumber = 15; + inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; + inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); + inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& + file() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* + mutable_file(); + + // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) + private: + inline void set_has_error(); + inline void clear_has_error(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* error_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); + + void InitAsDefaultInstance(); + static CodeGeneratorResponse* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// CodeGeneratorRequest + +// repeated string file_to_generate = 1; +inline int CodeGeneratorRequest::file_to_generate_size() const { + return file_to_generate_.size(); +} +inline void CodeGeneratorRequest::clear_file_to_generate() { + file_to_generate_.Clear(); +} +inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { + return file_to_generate_.Get(index); +} +inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { + return file_to_generate_.Mutable(index); +} +inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { + file_to_generate_.Mutable(index)->assign(value); +} +inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { + file_to_generate_.Mutable(index)->assign(value); +} +inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { + file_to_generate_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorRequest::add_file_to_generate() { + return file_to_generate_.Add(); +} +inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { + file_to_generate_.Add()->assign(value); +} +inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { + file_to_generate_.Add()->assign(value); +} +inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { + file_to_generate_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +CodeGeneratorRequest::file_to_generate() const { + return file_to_generate_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +CodeGeneratorRequest::mutable_file_to_generate() { + return &file_to_generate_; +} + +// optional string parameter = 2; +inline bool CodeGeneratorRequest::has_parameter() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorRequest::set_has_parameter() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorRequest::clear_has_parameter() { + _has_bits_[0] &= ~0x00000002u; +} +inline void CodeGeneratorRequest::clear_parameter() { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { + parameter_->clear(); + } + clear_has_parameter(); +} +inline const ::std::string& CodeGeneratorRequest::parameter() const { + return *parameter_; +} +inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + parameter_ = new ::std::string; + } + parameter_->assign(value); +} +inline void CodeGeneratorRequest::set_parameter(const char* value) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + parameter_ = new ::std::string; + } + parameter_->assign(value); +} +inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + parameter_ = new ::std::string; + } + parameter_->assign(reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorRequest::mutable_parameter() { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + parameter_ = new ::std::string; + } + return parameter_; +} +inline ::std::string* CodeGeneratorRequest::release_parameter() { + clear_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = parameter_; + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { + delete parameter_; + } + if (parameter) { + set_has_parameter(); + parameter_ = parameter; + } else { + clear_has_parameter(); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated .google.protobuf.FileDescriptorProto proto_file = 15; +inline int CodeGeneratorRequest::proto_file_size() const { + return proto_file_.size(); +} +inline void CodeGeneratorRequest::clear_proto_file() { + proto_file_.Clear(); +} +inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + return proto_file_.Get(index); +} +inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { + return proto_file_.Mutable(index); +} +inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + return proto_file_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +CodeGeneratorRequest::proto_file() const { + return proto_file_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +CodeGeneratorRequest::mutable_proto_file() { + return &proto_file_; +} + +// ------------------------------------------------------------------- + +// CodeGeneratorResponse_File + +// optional string name = 1; +inline bool CodeGeneratorResponse_File::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse_File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void CodeGeneratorResponse_File::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& CodeGeneratorResponse_File::name() const { + return *name_; +} +inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void CodeGeneratorResponse_File::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorResponse_File::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* CodeGeneratorResponse_File::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string insertion_point = 2; +inline bool CodeGeneratorResponse_File::has_insertion_point() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_insertion_point() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorResponse_File::clear_has_insertion_point() { + _has_bits_[0] &= ~0x00000002u; +} +inline void CodeGeneratorResponse_File::clear_insertion_point() { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { + insertion_point_->clear(); + } + clear_has_insertion_point(); +} +inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { + return *insertion_point_; +} +inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + insertion_point_ = new ::std::string; + } + insertion_point_->assign(value); +} +inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + insertion_point_ = new ::std::string; + } + insertion_point_->assign(value); +} +inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + insertion_point_ = new ::std::string; + } + insertion_point_->assign(reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + insertion_point_ = new ::std::string; + } + return insertion_point_; +} +inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { + clear_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = insertion_point_; + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { + delete insertion_point_; + } + if (insertion_point) { + set_has_insertion_point(); + insertion_point_ = insertion_point; + } else { + clear_has_insertion_point(); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string content = 15; +inline bool CodeGeneratorResponse_File::has_content() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_content() { + _has_bits_[0] |= 0x00000004u; +} +inline void CodeGeneratorResponse_File::clear_has_content() { + _has_bits_[0] &= ~0x00000004u; +} +inline void CodeGeneratorResponse_File::clear_content() { + if (content_ != &::google::protobuf::internal::kEmptyString) { + content_->clear(); + } + clear_has_content(); +} +inline const ::std::string& CodeGeneratorResponse_File::content() const { + return *content_; +} +inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + content_ = new ::std::string; + } + content_->assign(value); +} +inline void CodeGeneratorResponse_File::set_content(const char* value) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + content_ = new ::std::string; + } + content_->assign(value); +} +inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + content_ = new ::std::string; + } + content_->assign(reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorResponse_File::mutable_content() { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + content_ = new ::std::string; + } + return content_; +} +inline ::std::string* CodeGeneratorResponse_File::release_content() { + clear_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = content_; + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { + if (content_ != &::google::protobuf::internal::kEmptyString) { + delete content_; + } + if (content) { + set_has_content(); + content_ = content; + } else { + clear_has_content(); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// ------------------------------------------------------------------- + +// CodeGeneratorResponse + +// optional string error = 1; +inline bool CodeGeneratorResponse::has_error() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse::set_has_error() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse::clear_has_error() { + _has_bits_[0] &= ~0x00000001u; +} +inline void CodeGeneratorResponse::clear_error() { + if (error_ != &::google::protobuf::internal::kEmptyString) { + error_->clear(); + } + clear_has_error(); +} +inline const ::std::string& CodeGeneratorResponse::error() const { + return *error_; +} +inline void CodeGeneratorResponse::set_error(const ::std::string& value) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + error_ = new ::std::string; + } + error_->assign(value); +} +inline void CodeGeneratorResponse::set_error(const char* value) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + error_ = new ::std::string; + } + error_->assign(value); +} +inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + error_ = new ::std::string; + } + error_->assign(reinterpret_cast(value), size); +} +inline ::std::string* CodeGeneratorResponse::mutable_error() { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + error_ = new ::std::string; + } + return error_; +} +inline ::std::string* CodeGeneratorResponse::release_error() { + clear_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = error_; + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { + if (error_ != &::google::protobuf::internal::kEmptyString) { + delete error_; + } + if (error) { + set_has_error(); + error_ = error; + } else { + clear_has_error(); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; +inline int CodeGeneratorResponse::file_size() const { + return file_.size(); +} +inline void CodeGeneratorResponse::clear_file() { + file_.Clear(); +} +inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + return file_.Get(index); +} +inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { + return file_.Mutable(index); +} +inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + return file_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +CodeGeneratorResponse::file() const { + return file_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* +CodeGeneratorResponse::mutable_file() { + return &file_; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#ifndef SWIG +namespace google { +namespace protobuf { + + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.proto b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.proto new file mode 100644 index 000000000..77b888f37 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/plugin.proto @@ -0,0 +1,147 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to +// change. +// +// protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is +// just a program that reads a CodeGeneratorRequest from stdin and writes a +// CodeGeneratorResponse to stdout. +// +// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead +// of dealing with the raw protocol defined here. +// +// A plugin executable needs only to be placed somewhere in the path. The +// plugin should be named "protoc-gen-$NAME", and will then be used when the +// flag "--${NAME}_out" is passed to protoc. + +package google.protobuf.compiler; +option java_package = "com.google.protobuf.compiler"; +option java_outer_classname = "PluginProtos"; + +import "google/protobuf/descriptor.proto"; + +// An encoded CodeGeneratorRequest is written to the plugin's stdin. +message CodeGeneratorRequest { + // The .proto files that were explicitly listed on the command-line. The + // code generator should generate code only for these files. Each file's + // descriptor will be included in proto_file, below. + repeated string file_to_generate = 1; + + // The generator parameter passed on the command-line. + optional string parameter = 2; + + // FileDescriptorProtos for all files in files_to_generate and everything + // they import. The files will appear in topological order, so each file + // appears before any file that imports it. + // + // protoc guarantees that all proto_files will be written after + // the fields above, even though this is not technically guaranteed by the + // protobuf wire format. This theoretically could allow a plugin to stream + // in the FileDescriptorProtos and handle them one by one rather than read + // the entire set into memory at once. However, as of this writing, this + // is not similarly optimized on protoc's end -- it will store all fields in + // memory at once before sending them to the plugin. + repeated FileDescriptorProto proto_file = 15; +} + +// The plugin writes an encoded CodeGeneratorResponse to stdout. +message CodeGeneratorResponse { + // Error message. If non-empty, code generation failed. The plugin process + // should exit with status code zero even if it reports an error in this way. + // + // This should be used to indicate errors in .proto files which prevent the + // code generator from generating correct code. Errors which indicate a + // problem in protoc itself -- such as the input CodeGeneratorRequest being + // unparseable -- should be reported by writing a message to stderr and + // exiting with a non-zero status code. + optional string error = 1; + + // Represents a single generated file. + message File { + // The file name, relative to the output directory. The name must not + // contain "." or ".." components and must be relative, not be absolute (so, + // the file cannot lie outside the output directory). "/" must be used as + // the path separator, not "\". + // + // If the name is omitted, the content will be appended to the previous + // file. This allows the generator to break large files into small chunks, + // and allows the generated text to be streamed back to protoc so that large + // files need not reside completely in memory at one time. Note that as of + // this writing protoc does not optimize for this -- it will read the entire + // CodeGeneratorResponse before writing files to disk. + optional string name = 1; + + // If non-empty, indicates that the named file should already exist, and the + // content here is to be inserted into that file at a defined insertion + // point. This feature allows a code generator to extend the output + // produced by another code generator. The original generator may provide + // insertion points by placing special annotations in the file that look + // like: + // @@protoc_insertion_point(NAME) + // The annotation can have arbitrary text before and after it on the line, + // which allows it to be placed in a comment. NAME should be replaced with + // an identifier naming the point -- this is what other generators will use + // as the insertion_point. Code inserted at this point will be placed + // immediately above the line containing the insertion point (thus multiple + // insertions to the same point will come out in the order they were added). + // The double-@ is intended to make it unlikely that the generated code + // could contain things that look like insertion points by accident. + // + // For example, the C++ code generator places the following line in the + // .pb.h files that it generates: + // // @@protoc_insertion_point(namespace_scope) + // This line appears within the scope of the file's package namespace, but + // outside of any particular class. Another plugin can then specify the + // insertion_point "namespace_scope" to generate additional classes or + // other declarations that should be placed in this scope. + // + // Note that if the line containing the insertion point begins with + // whitespace, the same whitespace will be added to every line of the + // inserted text. This is useful for languages like Python, where + // indentation matters. In these languages, the insertion point comment + // should be indented the same amount as any inserted code will need to be + // in order to work correctly in that context. + // + // The code generator that generates the initial file and the one which + // inserts into it must both run as part of a single invocation of protoc. + // Code generators are executed in the order in which they appear on the + // command line. + // + // If |insertion_point| is present, |name| must also be present. + optional string insertion_point = 2; + + // The file contents. + optional string content = 15; + } + repeated File file = 15; +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.cc new file mode 100644 index 000000000..211ac70c0 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.cc @@ -0,0 +1,1157 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: robinson@google.com (Will Robinson) +// +// This module outputs pure-Python protocol message classes that will +// largely be constructed at runtime via the metaclass in reflection.py. +// In other words, our job is basically to output a Python equivalent +// of the C++ *Descriptor objects, and fix up all circular references +// within these objects. +// +// Note that the runtime performance of protocol message classes created in +// this way is expected to be lousy. The plan is to create an alternate +// generator that outputs a Python/C extension module that lets +// performance-minded Python code leverage the fast C++ implementation +// directly. + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace python { + +namespace { + +// Returns a copy of |filename| with any trailing ".protodevel" or ".proto +// suffix stripped. +// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc. +string StripProto(const string& filename) { + const char* suffix = HasSuffixString(filename, ".protodevel") + ? ".protodevel" : ".proto"; + return StripSuffixString(filename, suffix); +} + + +// Returns the Python module name expected for a given .proto filename. +string ModuleName(const string& filename) { + string basename = StripProto(filename); + StripString(&basename, "-", '_'); + StripString(&basename, "/", '.'); + return basename + "_pb2"; +} + + +// Returns the name of all containing types for descriptor, +// in order from outermost to innermost, followed by descriptor's +// own name. Each name is separated by |separator|. +template +string NamePrefixedWithNestedTypes(const DescriptorT& descriptor, + const string& separator) { + string name = descriptor.name(); + for (const Descriptor* current = descriptor.containing_type(); + current != NULL; current = current->containing_type()) { + name = current->name() + separator + name; + } + return name; +} + + +// Name of the class attribute where we store the Python +// descriptor.Descriptor instance for the generated class. +// Must stay consistent with the _DESCRIPTOR_KEY constant +// in proto2/public/reflection.py. +const char kDescriptorKey[] = "DESCRIPTOR"; + + +// Does the file have top-level enums? +inline bool HasTopLevelEnums(const FileDescriptor *file) { + return file->enum_type_count() > 0; +} + + +// Should we generate generic services for this file? +inline bool HasGenericServices(const FileDescriptor *file) { + return file->service_count() > 0 && + file->options().py_generic_services(); +} + + +// Prints the common boilerplate needed at the top of every .py +// file output by this generator. +void PrintTopBoilerplate( + io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) { + // TODO(robinson): Allow parameterization of Python version? + printer->Print( + "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "# source: $filename$\n" + "\n", + "filename", file->name()); + if (HasTopLevelEnums(file)) { + printer->Print( + "from google.protobuf.internal import enum_type_wrapper\n"); + } + printer->Print( + "from google.protobuf import descriptor as _descriptor\n" + "from google.protobuf import message as _message\n" + "from google.protobuf import reflection as _reflection\n" + ); + if (HasGenericServices(file)) { + printer->Print( + "from google.protobuf import service as _service\n" + "from google.protobuf import service_reflection\n"); + } + + // Avoid circular imports if this module is descriptor_pb2. + if (!descriptor_proto) { + printer->Print( + "from google.protobuf import descriptor_pb2\n"); + } + printer->Print( + "# @@protoc_insertion_point(imports)\n"); + printer->Print("\n\n"); +} + + +// Returns a Python literal giving the default value for a field. +// If the field specifies no explicit default value, we'll return +// the default default value for the field type (zero for numbers, +// empty string for strings, empty list for repeated fields, and +// None for non-repeated, composite fields). +// +// TODO(robinson): Unify with code from +// //compiler/cpp/internal/primitive_field.cc +// //compiler/cpp/internal/enum_field.cc +// //compiler/cpp/internal/string_field.cc +string StringifyDefaultValue(const FieldDescriptor& field) { + if (field.is_repeated()) { + return "[]"; + } + + switch (field.cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return SimpleItoa(field.default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + return SimpleItoa(field.default_value_uint32()); + case FieldDescriptor::CPPTYPE_INT64: + return SimpleItoa(field.default_value_int64()); + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(field.default_value_uint64()); + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value = field.default_value_double(); + if (value == numeric_limits::infinity()) { + // Python pre-2.6 on Windows does not parse "inf" correctly. However, + // a numeric literal that is too big for a double will become infinity. + return "1e10000"; + } else if (value == -numeric_limits::infinity()) { + // See above. + return "-1e10000"; + } else if (value != value) { + // infinity * 0 = nan + return "(1e10000 * 0)"; + } else { + return SimpleDtoa(value); + } + } + case FieldDescriptor::CPPTYPE_FLOAT: { + float value = field.default_value_float(); + if (value == numeric_limits::infinity()) { + // Python pre-2.6 on Windows does not parse "inf" correctly. However, + // a numeric literal that is too big for a double will become infinity. + return "1e10000"; + } else if (value == -numeric_limits::infinity()) { + // See above. + return "-1e10000"; + } else if (value != value) { + // infinity - infinity = nan + return "(1e10000 * 0)"; + } else { + return SimpleFtoa(value); + } + } + case FieldDescriptor::CPPTYPE_BOOL: + return field.default_value_bool() ? "True" : "False"; + case FieldDescriptor::CPPTYPE_ENUM: + return SimpleItoa(field.default_value_enum()->number()); + case FieldDescriptor::CPPTYPE_STRING: + if (field.type() == FieldDescriptor::TYPE_STRING) { + return "unicode(\"" + CEscape(field.default_value_string()) + + "\", \"utf-8\")"; + } else { + return "\"" + CEscape(field.default_value_string()) + "\""; + } + case FieldDescriptor::CPPTYPE_MESSAGE: + return "None"; + } + // (We could add a default case above but then we wouldn't get the nice + // compiler warning when a new type is added.) + GOOGLE_LOG(FATAL) << "Not reached."; + return ""; +} + + + +} // namespace + + +Generator::Generator() : file_(NULL) { +} + +Generator::~Generator() { +} + +bool Generator::Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + + // Completely serialize all Generate() calls on this instance. The + // thread-safety constraints of the CodeGenerator interface aren't clear so + // just be as conservative as possible. It's easier to relax this later if + // we need to, but I doubt it will be an issue. + // TODO(kenton): The proper thing to do would be to allocate any state on + // the stack and use that, so that the Generator class itself does not need + // to have any mutable members. Then it is implicitly thread-safe. + MutexLock lock(&mutex_); + file_ = file; + string module_name = ModuleName(file->name()); + string filename = module_name; + StripString(&filename, ".", '/'); + filename += ".py"; + + FileDescriptorProto fdp; + file_->CopyTo(&fdp); + fdp.SerializeToString(&file_descriptor_serialized_); + + + scoped_ptr output(context->Open(filename)); + GOOGLE_CHECK(output.get()); + io::Printer printer(output.get(), '$'); + printer_ = &printer; + + PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); + PrintImports(); + PrintFileDescriptor(); + PrintTopLevelEnums(); + PrintTopLevelExtensions(); + PrintAllNestedEnumsInFile(); + PrintMessageDescriptors(); + FixForeignFieldsInDescriptors(); + PrintMessages(); + // We have to fix up the extensions after the message classes themselves, + // since they need to call static RegisterExtension() methods on these + // classes. + FixForeignFieldsInExtensions(); + // Descriptor options may have custom extensions. These custom options + // can only be successfully parsed after we register corresponding + // extensions. Therefore we parse all options again here to recognize + // custom options that may be unknown when we define the descriptors. + FixAllDescriptorOptions(); + if (HasGenericServices(file)) { + PrintServices(); + } + + printer.Print( + "# @@protoc_insertion_point(module_scope)\n"); + + return !printer.failed(); +} + +// Prints Python imports for all modules imported by |file|. +void Generator::PrintImports() const { + for (int i = 0; i < file_->dependency_count(); ++i) { + string module_name = ModuleName(file_->dependency(i)->name()); + printer_->Print("import $module$\n", "module", + module_name); + } + printer_->Print("\n"); + + // Print public imports. + for (int i = 0; i < file_->public_dependency_count(); ++i) { + string module_name = ModuleName(file_->public_dependency(i)->name()); + printer_->Print("from $module$ import *\n", "module", module_name); + } + printer_->Print("\n"); +} + +// Prints the single file descriptor for this file. +void Generator::PrintFileDescriptor() const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["name"] = file_->name(); + m["package"] = file_->package(); + const char file_descriptor_template[] = + "$descriptor_name$ = _descriptor.FileDescriptor(\n" + " name='$name$',\n" + " package='$package$',\n"; + printer_->Print(m, file_descriptor_template); + printer_->Indent(); + printer_->Print( + "serialized_pb='$value$'", + "value", strings::CHexEscape(file_descriptor_serialized_)); + + // TODO(falk): Also print options and fix the message_type, enum_type, + // service and extension later in the generation. + + printer_->Outdent(); + printer_->Print(")\n"); + printer_->Print("\n"); +} + +// Prints descriptors and module-level constants for all top-level +// enums defined in |file|. +void Generator::PrintTopLevelEnums() const { + vector > top_level_enum_values; + for (int i = 0; i < file_->enum_type_count(); ++i) { + const EnumDescriptor& enum_descriptor = *file_->enum_type(i); + PrintEnum(enum_descriptor); + printer_->Print("$name$ = " + "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)", + "name", enum_descriptor.name(), + "descriptor_name", + ModuleLevelDescriptorName(enum_descriptor)); + printer_->Print("\n"); + + for (int j = 0; j < enum_descriptor.value_count(); ++j) { + const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j); + top_level_enum_values.push_back( + make_pair(value_descriptor.name(), value_descriptor.number())); + } + } + + for (int i = 0; i < top_level_enum_values.size(); ++i) { + printer_->Print("$name$ = $value$\n", + "name", top_level_enum_values[i].first, + "value", SimpleItoa(top_level_enum_values[i].second)); + } + printer_->Print("\n"); +} + +// Prints all enums contained in all message types in |file|. +void Generator::PrintAllNestedEnumsInFile() const { + for (int i = 0; i < file_->message_type_count(); ++i) { + PrintNestedEnums(*file_->message_type(i)); + } +} + +// Prints a Python statement assigning the appropriate module-level +// enum name to a Python EnumDescriptor object equivalent to +// enum_descriptor. +void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { + map m; + m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); + m["name"] = enum_descriptor.name(); + m["full_name"] = enum_descriptor.full_name(); + m["file"] = kDescriptorKey; + const char enum_descriptor_template[] = + "$descriptor_name$ = _descriptor.EnumDescriptor(\n" + " name='$name$',\n" + " full_name='$full_name$',\n" + " filename=None,\n" + " file=$file$,\n" + " values=[\n"; + string options_string; + enum_descriptor.options().SerializeToString(&options_string); + printer_->Print(m, enum_descriptor_template); + printer_->Indent(); + printer_->Indent(); + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + PrintEnumValueDescriptor(*enum_descriptor.value(i)); + printer_->Print(",\n"); + } + printer_->Outdent(); + printer_->Print("],\n"); + printer_->Print("containing_type=None,\n"); + printer_->Print("options=$options_value$,\n", + "options_value", + OptionsValue("EnumOptions", options_string)); + EnumDescriptorProto edp; + PrintSerializedPbInterval(enum_descriptor, edp); + printer_->Outdent(); + printer_->Print(")\n"); + printer_->Print("\n"); +} + +// Recursively prints enums in nested types within descriptor, then +// prints enums contained at the top level in descriptor. +void Generator::PrintNestedEnums(const Descriptor& descriptor) const { + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + PrintNestedEnums(*descriptor.nested_type(i)); + } + + for (int i = 0; i < descriptor.enum_type_count(); ++i) { + PrintEnum(*descriptor.enum_type(i)); + } +} + +void Generator::PrintTopLevelExtensions() const { + const bool is_extension = true; + for (int i = 0; i < file_->extension_count(); ++i) { + const FieldDescriptor& extension_field = *file_->extension(i); + string constant_name = extension_field.name() + "_FIELD_NUMBER"; + UpperString(&constant_name); + printer_->Print("$constant_name$ = $number$\n", + "constant_name", constant_name, + "number", SimpleItoa(extension_field.number())); + printer_->Print("$name$ = ", "name", extension_field.name()); + PrintFieldDescriptor(extension_field, is_extension); + printer_->Print("\n"); + } + printer_->Print("\n"); +} + +// Prints Python equivalents of all Descriptors in |file|. +void Generator::PrintMessageDescriptors() const { + for (int i = 0; i < file_->message_type_count(); ++i) { + PrintDescriptor(*file_->message_type(i)); + printer_->Print("\n"); + } +} + +void Generator::PrintServices() const { + for (int i = 0; i < file_->service_count(); ++i) { + PrintServiceDescriptor(*file_->service(i)); + PrintServiceClass(*file_->service(i)); + PrintServiceStub(*file_->service(i)); + printer_->Print("\n"); + } +} + +void Generator::PrintServiceDescriptor( + const ServiceDescriptor& descriptor) const { + printer_->Print("\n"); + string service_name = ModuleLevelServiceDescriptorName(descriptor); + string options_string; + descriptor.options().SerializeToString(&options_string); + + printer_->Print( + "$service_name$ = _descriptor.ServiceDescriptor(\n", + "service_name", service_name); + printer_->Indent(); + map m; + m["name"] = descriptor.name(); + m["full_name"] = descriptor.full_name(); + m["file"] = kDescriptorKey; + m["index"] = SimpleItoa(descriptor.index()); + m["options_value"] = OptionsValue("ServiceOptions", options_string); + const char required_function_arguments[] = + "name='$name$',\n" + "full_name='$full_name$',\n" + "file=$file$,\n" + "index=$index$,\n" + "options=$options_value$,\n"; + printer_->Print(m, required_function_arguments); + + ServiceDescriptorProto sdp; + PrintSerializedPbInterval(descriptor, sdp); + + printer_->Print("methods=[\n"); + for (int i = 0; i < descriptor.method_count(); ++i) { + const MethodDescriptor* method = descriptor.method(i); + method->options().SerializeToString(&options_string); + + m.clear(); + m["name"] = method->name(); + m["full_name"] = method->full_name(); + m["index"] = SimpleItoa(method->index()); + m["serialized_options"] = CEscape(options_string); + m["input_type"] = ModuleLevelDescriptorName(*(method->input_type())); + m["output_type"] = ModuleLevelDescriptorName(*(method->output_type())); + m["options_value"] = OptionsValue("MethodOptions", options_string); + printer_->Print("_descriptor.MethodDescriptor(\n"); + printer_->Indent(); + printer_->Print( + m, + "name='$name$',\n" + "full_name='$full_name$',\n" + "index=$index$,\n" + "containing_service=None,\n" + "input_type=$input_type$,\n" + "output_type=$output_type$,\n" + "options=$options_value$,\n"); + printer_->Outdent(); + printer_->Print("),\n"); + } + + printer_->Outdent(); + printer_->Print("])\n\n"); +} + +void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { + // Print the service. + printer_->Print("class $class_name$(_service.Service):\n", + "class_name", descriptor.name()); + printer_->Indent(); + printer_->Print( + "__metaclass__ = service_reflection.GeneratedServiceType\n" + "$descriptor_key$ = $descriptor_name$\n", + "descriptor_key", kDescriptorKey, + "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Outdent(); +} + +void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { + // Print the service stub. + printer_->Print("class $class_name$_Stub($class_name$):\n", + "class_name", descriptor.name()); + printer_->Indent(); + printer_->Print( + "__metaclass__ = service_reflection.GeneratedServiceStubType\n" + "$descriptor_key$ = $descriptor_name$\n", + "descriptor_key", kDescriptorKey, + "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Outdent(); +} + +// Prints statement assigning ModuleLevelDescriptorName(message_descriptor) +// to a Python Descriptor object for message_descriptor. +// +// Mutually recursive with PrintNestedDescriptors(). +void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { + PrintNestedDescriptors(message_descriptor); + + printer_->Print("\n"); + printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n", + "descriptor_name", + ModuleLevelDescriptorName(message_descriptor)); + printer_->Indent(); + map m; + m["name"] = message_descriptor.name(); + m["full_name"] = message_descriptor.full_name(); + m["file"] = kDescriptorKey; + const char required_function_arguments[] = + "name='$name$',\n" + "full_name='$full_name$',\n" + "filename=None,\n" + "file=$file$,\n" + "containing_type=None,\n"; + printer_->Print(m, required_function_arguments); + PrintFieldsInDescriptor(message_descriptor); + PrintExtensionsInDescriptor(message_descriptor); + + // Nested types + printer_->Print("nested_types=["); + for (int i = 0; i < message_descriptor.nested_type_count(); ++i) { + const string nested_name = ModuleLevelDescriptorName( + *message_descriptor.nested_type(i)); + printer_->Print("$name$, ", "name", nested_name); + } + printer_->Print("],\n"); + + // Enum types + printer_->Print("enum_types=[\n"); + printer_->Indent(); + for (int i = 0; i < message_descriptor.enum_type_count(); ++i) { + const string descriptor_name = ModuleLevelDescriptorName( + *message_descriptor.enum_type(i)); + printer_->Print(descriptor_name.c_str()); + printer_->Print(",\n"); + } + printer_->Outdent(); + printer_->Print("],\n"); + string options_string; + message_descriptor.options().SerializeToString(&options_string); + printer_->Print( + "options=$options_value$,\n" + "is_extendable=$extendable$", + "options_value", OptionsValue("MessageOptions", options_string), + "extendable", message_descriptor.extension_range_count() > 0 ? + "True" : "False"); + printer_->Print(",\n"); + + // Extension ranges + printer_->Print("extension_ranges=["); + for (int i = 0; i < message_descriptor.extension_range_count(); ++i) { + const Descriptor::ExtensionRange* range = + message_descriptor.extension_range(i); + printer_->Print("($start$, $end$), ", + "start", SimpleItoa(range->start), + "end", SimpleItoa(range->end)); + } + printer_->Print("],\n"); + + // Serialization of proto + DescriptorProto edp; + PrintSerializedPbInterval(message_descriptor, edp); + + printer_->Outdent(); + printer_->Print(")\n"); +} + +// Prints Python Descriptor objects for all nested types contained in +// message_descriptor. +// +// Mutually recursive with PrintDescriptor(). +void Generator::PrintNestedDescriptors( + const Descriptor& containing_descriptor) const { + for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { + PrintDescriptor(*containing_descriptor.nested_type(i)); + } +} + +// Prints all messages in |file|. +void Generator::PrintMessages() const { + for (int i = 0; i < file_->message_type_count(); ++i) { + PrintMessage(*file_->message_type(i)); + printer_->Print("\n"); + } +} + +// Prints a Python class for the given message descriptor. We defer to the +// metaclass to do almost all of the work of actually creating a useful class. +// The purpose of this function and its many helper functions above is merely +// to output a Python version of the descriptors, which the metaclass in +// reflection.py will use to construct the meat of the class itself. +// +// Mutually recursive with PrintNestedMessages(). +void Generator::PrintMessage( + const Descriptor& message_descriptor) const { + printer_->Print("class $name$(_message.Message):\n", "name", + message_descriptor.name()); + printer_->Indent(); + printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n"); + PrintNestedMessages(message_descriptor); + map m; + m["descriptor_key"] = kDescriptorKey; + m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); + printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); + + printer_->Print( + "\n" + "# @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", message_descriptor.full_name()); + + printer_->Outdent(); +} + +// Prints all nested messages within |containing_descriptor|. +// Mutually recursive with PrintMessage(). +void Generator::PrintNestedMessages( + const Descriptor& containing_descriptor) const { + for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { + printer_->Print("\n"); + PrintMessage(*containing_descriptor.nested_type(i)); + } +} + +// Recursively fixes foreign fields in all nested types in |descriptor|, then +// sets the message_type and enum_type of all message and enum fields to point +// to their respective descriptors. +// Args: +// descriptor: descriptor to print fields for. +// containing_descriptor: if descriptor is a nested type, this is its +// containing type, or NULL if this is a root/top-level type. +void Generator::FixForeignFieldsInDescriptor( + const Descriptor& descriptor, + const Descriptor* containing_descriptor) const { + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor); + } + + for (int i = 0; i < descriptor.field_count(); ++i) { + const FieldDescriptor& field_descriptor = *descriptor.field(i); + FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name"); + } + + FixContainingTypeInDescriptor(descriptor, containing_descriptor); + for (int i = 0; i < descriptor.enum_type_count(); ++i) { + const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i); + FixContainingTypeInDescriptor(enum_descriptor, &descriptor); + } +} + +void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["message_name"] = descriptor.name(); + m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.message_types_by_name['$message_name$'] = " + "$message_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +// Sets any necessary message_type and enum_type attributes +// for the Python version of |field|. +// +// containing_type may be NULL, in which case this is a module-level field. +// +// python_dict_name is the name of the Python dict where we should +// look the field up in the containing type. (e.g., fields_by_name +// or extensions_by_name). We ignore python_dict_name if containing_type +// is NULL. +void Generator::FixForeignFieldsInField(const Descriptor* containing_type, + const FieldDescriptor& field, + const string& python_dict_name) const { + const string field_referencing_expression = FieldReferencingExpression( + containing_type, field, python_dict_name); + map m; + m["field_ref"] = field_referencing_expression; + const Descriptor* foreign_message_type = field.message_type(); + if (foreign_message_type) { + m["foreign_type"] = ModuleLevelDescriptorName(*foreign_message_type); + printer_->Print(m, "$field_ref$.message_type = $foreign_type$\n"); + } + const EnumDescriptor* enum_type = field.enum_type(); + if (enum_type) { + m["enum_type"] = ModuleLevelDescriptorName(*enum_type); + printer_->Print(m, "$field_ref$.enum_type = $enum_type$\n"); + } +} + +// Returns the module-level expression for the given FieldDescriptor. +// Only works for fields in the .proto file this Generator is generating for. +// +// containing_type may be NULL, in which case this is a module-level field. +// +// python_dict_name is the name of the Python dict where we should +// look the field up in the containing type. (e.g., fields_by_name +// or extensions_by_name). We ignore python_dict_name if containing_type +// is NULL. +string Generator::FieldReferencingExpression( + const Descriptor* containing_type, + const FieldDescriptor& field, + const string& python_dict_name) const { + // We should only ever be looking up fields in the current file. + // The only things we refer to from other files are message descriptors. + GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. " + << file_->name(); + if (!containing_type) { + return field.name(); + } + return strings::Substitute( + "$0.$1['$2']", + ModuleLevelDescriptorName(*containing_type), + python_dict_name, field.name()); +} + +// Prints containing_type for nested descriptors or enum descriptors. +template +void Generator::FixContainingTypeInDescriptor( + const DescriptorT& descriptor, + const Descriptor* containing_descriptor) const { + if (containing_descriptor != NULL) { + const string nested_name = ModuleLevelDescriptorName(descriptor); + const string parent_name = ModuleLevelDescriptorName( + *containing_descriptor); + printer_->Print( + "$nested_name$.containing_type = $parent_name$;\n", + "nested_name", nested_name, + "parent_name", parent_name); + } +} + +// Prints statements setting the message_type and enum_type fields in the +// Python descriptor objects we've already output in ths file. We must +// do this in a separate step due to circular references (otherwise, we'd +// just set everything in the initial assignment statements). +void Generator::FixForeignFieldsInDescriptors() const { + for (int i = 0; i < file_->message_type_count(); ++i) { + FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); + } + for (int i = 0; i < file_->message_type_count(); ++i) { + AddMessageToFileDescriptor(*file_->message_type(i)); + } + printer_->Print("\n"); +} + +// We need to not only set any necessary message_type fields, but +// also need to call RegisterExtension() on each message we're +// extending. +void Generator::FixForeignFieldsInExtensions() const { + // Top-level extensions. + for (int i = 0; i < file_->extension_count(); ++i) { + FixForeignFieldsInExtension(*file_->extension(i)); + } + // Nested extensions. + for (int i = 0; i < file_->message_type_count(); ++i) { + FixForeignFieldsInNestedExtensions(*file_->message_type(i)); + } + printer_->Print("\n"); +} + +void Generator::FixForeignFieldsInExtension( + const FieldDescriptor& extension_field) const { + GOOGLE_CHECK(extension_field.is_extension()); + // extension_scope() will be NULL for top-level extensions, which is + // exactly what FixForeignFieldsInField() wants. + FixForeignFieldsInField(extension_field.extension_scope(), extension_field, + "extensions_by_name"); + + map m; + // Confusingly, for FieldDescriptors that happen to be extensions, + // containing_type() means "extended type." + // On the other hand, extension_scope() will give us what we normally + // mean by containing_type(). + m["extended_message_class"] = ModuleLevelMessageName( + *extension_field.containing_type()); + m["field"] = FieldReferencingExpression(extension_field.extension_scope(), + extension_field, + "extensions_by_name"); + printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n"); +} + +void Generator::FixForeignFieldsInNestedExtensions( + const Descriptor& descriptor) const { + // Recursively fix up extensions in all nested types. + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + FixForeignFieldsInNestedExtensions(*descriptor.nested_type(i)); + } + // Fix up extensions directly contained within this type. + for (int i = 0; i < descriptor.extension_count(); ++i) { + FixForeignFieldsInExtension(*descriptor.extension(i)); + } +} + +// Returns a Python expression that instantiates a Python EnumValueDescriptor +// object for the given C++ descriptor. +void Generator::PrintEnumValueDescriptor( + const EnumValueDescriptor& descriptor) const { + // TODO(robinson): Fix up EnumValueDescriptor "type" fields. + // More circular references. ::sigh:: + string options_string; + descriptor.options().SerializeToString(&options_string); + map m; + m["name"] = descriptor.name(); + m["index"] = SimpleItoa(descriptor.index()); + m["number"] = SimpleItoa(descriptor.number()); + m["options"] = OptionsValue("EnumValueOptions", options_string); + printer_->Print( + m, + "_descriptor.EnumValueDescriptor(\n" + " name='$name$', index=$index$, number=$number$,\n" + " options=$options$,\n" + " type=None)"); +} + +// Returns a Python expression that calls descriptor._ParseOptions using +// the given descriptor class name and serialized options protobuf string. +string Generator::OptionsValue( + const string& class_name, const string& serialized_options) const { + if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { + return "None"; + } else { + string full_class_name = "descriptor_pb2." + class_name; + return "_descriptor._ParseOptions(" + full_class_name + "(), '" + + CEscape(serialized_options)+ "')"; + } +} + +// Prints an expression for a Python FieldDescriptor for |field|. +void Generator::PrintFieldDescriptor( + const FieldDescriptor& field, bool is_extension) const { + string options_string; + field.options().SerializeToString(&options_string); + map m; + m["name"] = field.name(); + m["full_name"] = field.full_name(); + m["index"] = SimpleItoa(field.index()); + m["number"] = SimpleItoa(field.number()); + m["type"] = SimpleItoa(field.type()); + m["cpp_type"] = SimpleItoa(field.cpp_type()); + m["label"] = SimpleItoa(field.label()); + m["has_default_value"] = field.has_default_value() ? "True" : "False"; + m["default_value"] = StringifyDefaultValue(field); + m["is_extension"] = is_extension ? "True" : "False"; + m["options"] = OptionsValue("FieldOptions", options_string); + // We always set message_type and enum_type to None at this point, and then + // these fields in correctly after all referenced descriptors have been + // defined and/or imported (see FixForeignFieldsInDescriptors()). + const char field_descriptor_decl[] = + "_descriptor.FieldDescriptor(\n" + " name='$name$', full_name='$full_name$', index=$index$,\n" + " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" + " has_default_value=$has_default_value$, default_value=$default_value$,\n" + " message_type=None, enum_type=None, containing_type=None,\n" + " is_extension=$is_extension$, extension_scope=None,\n" + " options=$options$)"; + printer_->Print(m, field_descriptor_decl); +} + +// Helper for Print{Fields,Extensions}InDescriptor(). +void Generator::PrintFieldDescriptorsInDescriptor( + const Descriptor& message_descriptor, + bool is_extension, + const string& list_variable_name, + int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const { + printer_->Print("$list$=[\n", "list", list_variable_name); + printer_->Indent(); + for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) { + PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i), + is_extension); + printer_->Print(",\n"); + } + printer_->Outdent(); + printer_->Print("],\n"); +} + +// Prints a statement assigning "fields" to a list of Python FieldDescriptors, +// one for each field present in message_descriptor. +void Generator::PrintFieldsInDescriptor( + const Descriptor& message_descriptor) const { + const bool is_extension = false; + PrintFieldDescriptorsInDescriptor( + message_descriptor, is_extension, "fields", + &Descriptor::field_count, &Descriptor::field); +} + +// Prints a statement assigning "extensions" to a list of Python +// FieldDescriptors, one for each extension present in message_descriptor. +void Generator::PrintExtensionsInDescriptor( + const Descriptor& message_descriptor) const { + const bool is_extension = true; + PrintFieldDescriptorsInDescriptor( + message_descriptor, is_extension, "extensions", + &Descriptor::extension_count, &Descriptor::extension); +} + +bool Generator::GeneratingDescriptorProto() const { + return file_->name() == "google/protobuf/descriptor.proto"; +} + +// Returns the unique Python module-level identifier given to a descriptor. +// This name is module-qualified iff the given descriptor describes an +// entity that doesn't come from the current file. +template +string Generator::ModuleLevelDescriptorName( + const DescriptorT& descriptor) const { + // FIXME(robinson): + // We currently don't worry about collisions with underscores in the type + // names, so these would collide in nasty ways if found in the same file: + // OuterProto.ProtoA.ProtoB + // OuterProto_ProtoA.ProtoB # Underscore instead of period. + // As would these: + // OuterProto.ProtoA_.ProtoB + // OuterProto.ProtoA._ProtoB # Leading vs. trailing underscore. + // (Contrived, but certainly possible). + // + // The C++ implementation doesn't guard against this either. Leaving + // it for now... + string name = NamePrefixedWithNestedTypes(descriptor, "_"); + UpperString(&name); + // Module-private for now. Easy to make public later; almost impossible + // to make private later. + name = "_" + name; + // We now have the name relative to its own module. Also qualify with + // the module name iff this descriptor is from a different .proto file. + if (descriptor.file() != file_) { + name = ModuleName(descriptor.file()->name()) + "." + name; + } + return name; +} + +// Returns the name of the message class itself, not the descriptor. +// Like ModuleLevelDescriptorName(), module-qualifies the name iff +// the given descriptor describes an entity that doesn't come from +// the current file. +string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const { + string name = NamePrefixedWithNestedTypes(descriptor, "."); + if (descriptor.file() != file_) { + name = ModuleName(descriptor.file()->name()) + "." + name; + } + return name; +} + +// Returns the unique Python module-level identifier given to a service +// descriptor. +string Generator::ModuleLevelServiceDescriptorName( + const ServiceDescriptor& descriptor) const { + string name = descriptor.name(); + UpperString(&name); + name = "_" + name; + if (descriptor.file() != file_) { + name = ModuleName(descriptor.file()->name()) + "." + name; + } + return name; +} + +// Prints standard constructor arguments serialized_start and serialized_end. +// Args: +// descriptor: The cpp descriptor to have a serialized reference. +// proto: A proto +// Example printer output: +// serialized_start=41, +// serialized_end=43, +// +template +void Generator::PrintSerializedPbInterval( + const DescriptorT& descriptor, DescriptorProtoT& proto) const { + descriptor.CopyTo(&proto); + string sp; + proto.SerializeToString(&sp); + int offset = file_descriptor_serialized_.find(sp); + GOOGLE_CHECK_GE(offset, 0); + + printer_->Print("serialized_start=$serialized_start$,\n" + "serialized_end=$serialized_end$,\n", + "serialized_start", SimpleItoa(offset), + "serialized_end", SimpleItoa(offset + sp.size())); +} + +namespace { +void PrintDescriptorOptionsFixingCode(const string& descriptor, + const string& options, + io::Printer* printer) { + // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase + // in proto2 python runtime but it couldn't be used here because appengine + // uses a snapshot version of the library in which the new method is not + // yet present. After appengine has synced their runtime library, the code + // below should be cleaned up to use _SetOptions(). + printer->Print( + "$descriptor$.has_options = True\n" + "$descriptor$._options = $options$\n", + "descriptor", descriptor, "options", options); +} +} // namespace + +// Prints expressions that set the options field of all descriptors. +void Generator::FixAllDescriptorOptions() const { + // Prints an expression that sets the file descriptor's options. + string file_options = OptionsValue( + "FileOptions", file_->options().SerializeAsString()); + if (file_options != "None") { + PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); + } + // Prints expressions that set the options for all top level enums. + for (int i = 0; i < file_->enum_type_count(); ++i) { + const EnumDescriptor& enum_descriptor = *file_->enum_type(i); + FixOptionsForEnum(enum_descriptor); + } + // Prints expressions that set the options for all top level extensions. + for (int i = 0; i < file_->extension_count(); ++i) { + const FieldDescriptor& field = *file_->extension(i); + FixOptionsForField(field); + } + // Prints expressions that set the options for all messages, nested enums, + // nested extensions and message fields. + for (int i = 0; i < file_->message_type_count(); ++i) { + FixOptionsForMessage(*file_->message_type(i)); + } +} + +// Prints expressions that set the options for an enum descriptor and its +// value descriptors. +void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { + string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); + string enum_options = OptionsValue( + "EnumOptions", enum_descriptor.options().SerializeAsString()); + if (enum_options != "None") { + PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); + } + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); + string value_options = OptionsValue( + "EnumValueOptions", value_descriptor.options().SerializeAsString()); + if (value_options != "None") { + PrintDescriptorOptionsFixingCode( + StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + value_descriptor.name().c_str()), + value_options, printer_); + } + } +} + +// Prints expressions that set the options for field descriptors (including +// extensions). +void Generator::FixOptionsForField( + const FieldDescriptor& field) const { + string field_options = OptionsValue( + "FieldOptions", field.options().SerializeAsString()); + if (field_options != "None") { + string field_name; + if (field.is_extension()) { + if (field.extension_scope() == NULL) { + // Top level extensions. + field_name = field.name(); + } else { + field_name = FieldReferencingExpression( + field.extension_scope(), field, "extensions_by_name"); + } + } else { + field_name = FieldReferencingExpression( + field.containing_type(), field, "fields_by_name"); + } + PrintDescriptorOptionsFixingCode(field_name, field_options, printer_); + } +} + +// Prints expressions that set the options for a message and all its inner +// types (nested messages, nested enums, extensions, fields). +void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { + // Nested messages. + for (int i = 0; i < descriptor.nested_type_count(); ++i) { + FixOptionsForMessage(*descriptor.nested_type(i)); + } + // Enums. + for (int i = 0; i < descriptor.enum_type_count(); ++i) { + FixOptionsForEnum(*descriptor.enum_type(i)); + } + // Fields. + for (int i = 0; i < descriptor.field_count(); ++i) { + const FieldDescriptor& field = *descriptor.field(i); + FixOptionsForField(field); + } + // Extensions. + for (int i = 0; i < descriptor.extension_count(); ++i) { + const FieldDescriptor& field = *descriptor.extension(i); + FixOptionsForField(field); + } + // Message option for this message. + string message_options = OptionsValue( + "MessageOptions", descriptor.options().SerializeAsString()); + if (message_options != "None") { + string descriptor_name = ModuleLevelDescriptorName(descriptor); + PrintDescriptorOptionsFixingCode(descriptor_name, + message_options, + printer_); + } +} + +} // namespace python +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.h new file mode 100644 index 000000000..a3f22cee6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_generator.h @@ -0,0 +1,161 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: robinson@google.com (Will Robinson) +// +// Generates Python code for a given .proto file. + +#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { + +class Descriptor; +class EnumDescriptor; +class EnumValueDescriptor; +class FieldDescriptor; +class ServiceDescriptor; + +namespace io { class Printer; } + +namespace compiler { +namespace python { + +// CodeGenerator implementation for generated Python protocol buffer classes. +// If you create your own protocol compiler binary and you want it to support +// Python output, you can do so by registering an instance of this +// CodeGenerator with the CommandLineInterface in your main() function. +class LIBPROTOC_EXPORT Generator : public CodeGenerator { + public: + Generator(); + virtual ~Generator(); + + // CodeGenerator methods. + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const; + + private: + void PrintImports() const; + void PrintFileDescriptor() const; + void PrintTopLevelEnums() const; + void PrintAllNestedEnumsInFile() const; + void PrintNestedEnums(const Descriptor& descriptor) const; + void PrintEnum(const EnumDescriptor& enum_descriptor) const; + + void PrintTopLevelExtensions() const; + + void PrintFieldDescriptor( + const FieldDescriptor& field, bool is_extension) const; + void PrintFieldDescriptorsInDescriptor( + const Descriptor& message_descriptor, + bool is_extension, + const string& list_variable_name, + int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; + void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; + void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const; + void PrintMessageDescriptors() const; + void PrintDescriptor(const Descriptor& message_descriptor) const; + void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; + + void PrintMessages() const; + void PrintMessage(const Descriptor& message_descriptor) const; + void PrintNestedMessages(const Descriptor& containing_descriptor) const; + + void FixForeignFieldsInDescriptors() const; + void FixForeignFieldsInDescriptor( + const Descriptor& descriptor, + const Descriptor* containing_descriptor) const; + void FixForeignFieldsInField(const Descriptor* containing_type, + const FieldDescriptor& field, + const string& python_dict_name) const; + void AddMessageToFileDescriptor(const Descriptor& descriptor) const; + string FieldReferencingExpression(const Descriptor* containing_type, + const FieldDescriptor& field, + const string& python_dict_name) const; + template + void FixContainingTypeInDescriptor( + const DescriptorT& descriptor, + const Descriptor* containing_descriptor) const; + + void FixForeignFieldsInExtensions() const; + void FixForeignFieldsInExtension( + const FieldDescriptor& extension_field) const; + void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const; + + void PrintServices() const; + void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const; + void PrintServiceClass(const ServiceDescriptor& descriptor) const; + void PrintServiceStub(const ServiceDescriptor& descriptor) const; + + void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; + string OptionsValue(const string& class_name, + const string& serialized_options) const; + bool GeneratingDescriptorProto() const; + + template + string ModuleLevelDescriptorName(const DescriptorT& descriptor) const; + string ModuleLevelMessageName(const Descriptor& descriptor) const; + string ModuleLevelServiceDescriptorName( + const ServiceDescriptor& descriptor) const; + + template + void PrintSerializedPbInterval( + const DescriptorT& descriptor, DescriptorProtoT& proto) const; + + void FixAllDescriptorOptions() const; + void FixOptionsForField(const FieldDescriptor& field) const; + void FixOptionsForEnum(const EnumDescriptor& descriptor) const; + void FixOptionsForMessage(const Descriptor& descriptor) const; + + // Very coarse-grained lock to ensure that Generate() is reentrant. + // Guards file_, printer_ and file_descriptor_serialized_. + mutable Mutex mutex_; + mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. + mutable string file_descriptor_serialized_; + mutable io::Printer* printer_; // Set in Generate(). Under mutex_. + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); +}; + +} // namespace python +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_plugin_unittest.cc new file mode 100644 index 000000000..da619ad3e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -0,0 +1,116 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// TODO(kenton): Share code with the versions of this test in other languages? +// It seemed like parameterizing it would add more complexity than it is +// worth. + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace python { +namespace { + +class TestGenerator : public CodeGenerator { + public: + TestGenerator() {} + ~TestGenerator() {} + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + TryInsert("test_pb2.py", "imports", context); + TryInsert("test_pb2.py", "module_scope", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); + return true; + } + + void TryInsert(const string& filename, const string& insertion_point, + GeneratorContext* context) const { + scoped_ptr output( + context->OpenForInsert(filename, insertion_point)); + io::Printer printer(output.get(), '$'); + printer.Print("// inserted $name$\n", "name", insertion_point); + } +}; + +// This test verifies that all the expected insertion points exist. It does +// not verify that they are correctly-placed; that would require actually +// compiling the output which is a bit more than I care to do for this test. +TEST(PythonPluginTest, PluginTest) { + File::WriteStringToFileOrDie( + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + TestTempDir() + "/test.proto"); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + python::Generator python_generator; + TestGenerator test_generator; + cli.RegisterGenerator("--python_out", &python_generator, ""); + cli.RegisterGenerator("--test_out", &test_generator, ""); + + string proto_path = "-I" + TestTempDir(); + string python_out = "--python_out=" + TestTempDir(); + string test_out = "--test_out=" + TestTempDir(); + + const char* argv[] = { + "protoc", + proto_path.c_str(), + python_out.c_str(), + test_out.c_str(), + "test.proto" + }; + + EXPECT_EQ(0, cli.Run(5, argv)); +} + +} // namespace +} // namespace python +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.cc new file mode 100644 index 000000000..67da120d6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.cc @@ -0,0 +1,463 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include + +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#endif + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +#ifdef _WIN32 + +static void CloseHandleOrDie(HANDLE handle) { + if (!CloseHandle(handle)) { + GOOGLE_LOG(FATAL) << "CloseHandle: " + << Subprocess::Win32ErrorMessage(GetLastError()); + } +} + +Subprocess::Subprocess() + : process_start_error_(ERROR_SUCCESS), + child_handle_(NULL), child_stdin_(NULL), child_stdout_(NULL) {} + +Subprocess::~Subprocess() { + if (child_stdin_ != NULL) { + CloseHandleOrDie(child_stdin_); + } + if (child_stdout_ != NULL) { + CloseHandleOrDie(child_stdout_); + } +} + +void Subprocess::Start(const string& program, SearchMode search_mode) { + // Create the pipes. + HANDLE stdin_pipe_read; + HANDLE stdin_pipe_write; + HANDLE stdout_pipe_read; + HANDLE stdout_pipe_write; + + if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, NULL, 0)) { + GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); + } + if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, NULL, 0)) { + GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); + } + + // Make child side of the pipes inheritable. + if (!SetHandleInformation(stdin_pipe_read, + HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + GOOGLE_LOG(FATAL) << "SetHandleInformation: " + << Win32ErrorMessage(GetLastError()); + } + if (!SetHandleInformation(stdout_pipe_write, + HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { + GOOGLE_LOG(FATAL) << "SetHandleInformation: " + << Win32ErrorMessage(GetLastError()); + } + + // Setup STARTUPINFO to redirect handles. + STARTUPINFOA startup_info; + ZeroMemory(&startup_info, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = stdin_pipe_read; + startup_info.hStdOutput = stdout_pipe_write; + startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + if (startup_info.hStdError == INVALID_HANDLE_VALUE) { + GOOGLE_LOG(FATAL) << "GetStdHandle: " + << Win32ErrorMessage(GetLastError()); + } + + // CreateProcess() mutates its second parameter. WTF? + char* name_copy = strdup(program.c_str()); + + // Create the process. + PROCESS_INFORMATION process_info; + + if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), + (search_mode == SEARCH_PATH) ? name_copy : NULL, + NULL, // process security attributes + NULL, // thread security attributes + TRUE, // inherit handles? + 0, // obscure creation flags + NULL, // environment (inherit from parent) + NULL, // current directory (inherit from parent) + &startup_info, + &process_info)) { + child_handle_ = process_info.hProcess; + CloseHandleOrDie(process_info.hThread); + child_stdin_ = stdin_pipe_write; + child_stdout_ = stdout_pipe_read; + } else { + process_start_error_ = GetLastError(); + CloseHandleOrDie(stdin_pipe_write); + CloseHandleOrDie(stdout_pipe_read); + } + + CloseHandleOrDie(stdin_pipe_read); + CloseHandleOrDie(stdout_pipe_write); + free(name_copy); +} + +bool Subprocess::Communicate(const Message& input, Message* output, + string* error) { + if (process_start_error_ != ERROR_SUCCESS) { + *error = Win32ErrorMessage(process_start_error_); + return false; + } + + GOOGLE_CHECK(child_handle_ != NULL) << "Must call Start() first."; + + string input_data = input.SerializeAsString(); + string output_data; + + int input_pos = 0; + + while (child_stdout_ != NULL) { + HANDLE handles[2]; + int handle_count = 0; + + if (child_stdin_ != NULL) { + handles[handle_count++] = child_stdin_; + } + if (child_stdout_ != NULL) { + handles[handle_count++] = child_stdout_; + } + + DWORD wait_result = + WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE); + + HANDLE signaled_handle; + if (wait_result >= WAIT_OBJECT_0 && + wait_result < WAIT_OBJECT_0 + handle_count) { + signaled_handle = handles[wait_result - WAIT_OBJECT_0]; + } else if (wait_result == WAIT_FAILED) { + GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: " + << Win32ErrorMessage(GetLastError()); + } else { + GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " + << wait_result; + } + + if (signaled_handle == child_stdin_) { + DWORD n; + if (!WriteFile(child_stdin_, + input_data.data() + input_pos, + input_data.size() - input_pos, + &n, NULL)) { + // Child closed pipe. Presumably it will report an error later. + // Pretend we're done for now. + input_pos = input_data.size(); + } else { + input_pos += n; + } + + if (input_pos == input_data.size()) { + // We're done writing. Close. + CloseHandleOrDie(child_stdin_); + child_stdin_ = NULL; + } + } else if (signaled_handle == child_stdout_) { + char buffer[4096]; + DWORD n; + + if (!ReadFile(child_stdout_, buffer, sizeof(buffer), &n, NULL)) { + // We're done reading. Close. + CloseHandleOrDie(child_stdout_); + child_stdout_ = NULL; + } else { + output_data.append(buffer, n); + } + } + } + + if (child_stdin_ != NULL) { + // Child did not finish reading input before it closed the output. + // Presumably it exited with an error. + CloseHandleOrDie(child_stdin_); + child_stdin_ = NULL; + } + + DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); + + if (wait_result == WAIT_FAILED) { + GOOGLE_LOG(FATAL) << "WaitForSingleObject: " + << Win32ErrorMessage(GetLastError()); + } else if (wait_result != WAIT_OBJECT_0) { + GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " + << wait_result; + } + + DWORD exit_code; + if (!GetExitCodeProcess(child_handle_, &exit_code)) { + GOOGLE_LOG(FATAL) << "GetExitCodeProcess: " + << Win32ErrorMessage(GetLastError()); + } + + CloseHandleOrDie(child_handle_); + child_handle_ = NULL; + + if (exit_code != 0) { + *error = strings::Substitute( + "Plugin failed with status code $0.", exit_code); + return false; + } + + if (!output->ParseFromString(output_data)) { + *error = "Plugin output is unparseable: " + CEscape(output_data); + return false; + } + + return true; +} + +string Subprocess::Win32ErrorMessage(DWORD error_code) { + char* message; + + // WTF? + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, 0, + (LPTSTR)&message, // NOT A BUG! + 0, NULL); + + string result = message; + LocalFree(message); + return result; +} + +// =================================================================== + +#else // _WIN32 + +Subprocess::Subprocess() + : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {} + +Subprocess::~Subprocess() { + if (child_stdin_ != -1) { + close(child_stdin_); + } + if (child_stdout_ != -1) { + close(child_stdout_); + } +} + +void Subprocess::Start(const string& program, SearchMode search_mode) { + // Note that we assume that there are no other threads, thus we don't have to + // do crazy stuff like using socket pairs or avoiding libc locks. + + // [0] is read end, [1] is write end. + int stdin_pipe[2]; + int stdout_pipe[2]; + + GOOGLE_CHECK(pipe(stdin_pipe) != -1); + GOOGLE_CHECK(pipe(stdout_pipe) != -1); + + char* argv[2] = { strdup(program.c_str()), NULL }; + + child_pid_ = fork(); + if (child_pid_ == -1) { + GOOGLE_LOG(FATAL) << "fork: " << strerror(errno); + } else if (child_pid_ == 0) { + // We are the child. + dup2(stdin_pipe[0], STDIN_FILENO); + dup2(stdout_pipe[1], STDOUT_FILENO); + + close(stdin_pipe[0]); + close(stdin_pipe[1]); + close(stdout_pipe[0]); + close(stdout_pipe[1]); + + switch (search_mode) { + case SEARCH_PATH: + execvp(argv[0], argv); + break; + case EXACT_NAME: + execv(argv[0], argv); + break; + } + + // Write directly to STDERR_FILENO to avoid stdio code paths that may do + // stuff that is unsafe here. + int ignored; + ignored = write(STDERR_FILENO, argv[0], strlen(argv[0])); + const char* message = ": program not found or is not executable\n"; + ignored = write(STDERR_FILENO, message, strlen(message)); + (void) ignored; + + // Must use _exit() rather than exit() to avoid flushing output buffers + // that will also be flushed by the parent. + _exit(1); + } else { + free(argv[0]); + + close(stdin_pipe[0]); + close(stdout_pipe[1]); + + child_stdin_ = stdin_pipe[1]; + child_stdout_ = stdout_pipe[0]; + } +} + +bool Subprocess::Communicate(const Message& input, Message* output, + string* error) { + + GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; + + // The "sighandler_t" typedef is GNU-specific, so define our own. + typedef void SignalHandler(int); + + // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us. + SignalHandler* old_pipe_handler = signal(SIGPIPE, SIG_IGN); + + string input_data = input.SerializeAsString(); + string output_data; + + int input_pos = 0; + int max_fd = max(child_stdin_, child_stdout_); + + while (child_stdout_ != -1) { + fd_set read_fds; + fd_set write_fds; + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + if (child_stdout_ != -1) { + FD_SET(child_stdout_, &read_fds); + } + if (child_stdin_ != -1) { + FD_SET(child_stdin_, &write_fds); + } + + if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) { + if (errno == EINTR) { + // Interrupted by signal. Try again. + continue; + } else { + GOOGLE_LOG(FATAL) << "select: " << strerror(errno); + } + } + + if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) { + int n = write(child_stdin_, input_data.data() + input_pos, + input_data.size() - input_pos); + if (n < 0) { + // Child closed pipe. Presumably it will report an error later. + // Pretend we're done for now. + input_pos = input_data.size(); + } else { + input_pos += n; + } + + if (input_pos == input_data.size()) { + // We're done writing. Close. + close(child_stdin_); + child_stdin_ = -1; + } + } + + if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) { + char buffer[4096]; + int n = read(child_stdout_, buffer, sizeof(buffer)); + + if (n > 0) { + output_data.append(buffer, n); + } else { + // We're done reading. Close. + close(child_stdout_); + child_stdout_ = -1; + } + } + } + + if (child_stdin_ != -1) { + // Child did not finish reading input before it closed the output. + // Presumably it exited with an error. + close(child_stdin_); + child_stdin_ = -1; + } + + int status; + while (waitpid(child_pid_, &status, 0) == -1) { + if (errno != EINTR) { + GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno); + } + } + + // Restore SIGPIPE handling. + signal(SIGPIPE, old_pipe_handler); + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + int error_code = WEXITSTATUS(status); + *error = strings::Substitute( + "Plugin failed with status code $0.", error_code); + return false; + } + } else if (WIFSIGNALED(status)) { + int signal = WTERMSIG(status); + *error = strings::Substitute( + "Plugin killed by signal $0.", signal); + return false; + } else { + *error = "Neither WEXITSTATUS nor WTERMSIG is true?"; + return false; + } + + if (!output->ParseFromString(output_data)) { + *error = "Plugin output is unparseable."; + return false; + } + + return true; +} + +#endif // !_WIN32 + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.h new file mode 100644 index 000000000..005649640 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/subprocess.h @@ -0,0 +1,108 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#ifndef GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ +#define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN // right... +#include +#else // _WIN32 +#include +#include +#endif // !_WIN32 +#include + +#include + + +namespace google { +namespace protobuf { + +class Message; + +namespace compiler { + +// Utility class for launching sub-processes. +class LIBPROTOC_EXPORT Subprocess { + public: + Subprocess(); + ~Subprocess(); + + enum SearchMode { + SEARCH_PATH, // Use PATH environment variable. + EXACT_NAME // Program is an exact file name; don't use the PATH. + }; + + // Start the subprocess. Currently we don't provide a way to specify + // arguments as protoc plugins don't have any. + void Start(const string& program, SearchMode search_mode); + + // Serialize the input message and pipe it to the subprocess's stdin, then + // close the pipe. Meanwhile, read from the subprocess's stdout and parse + // the data into *output. All this is done carefully to avoid deadlocks. + // Returns true if successful. On any sort of error, returns false and sets + // *error to a description of the problem. + bool Communicate(const Message& input, Message* output, string* error); + +#ifdef _WIN32 + // Given an error code, returns a human-readable error message. This is + // defined here so that CommandLineInterface can share it. + static string Win32ErrorMessage(DWORD error_code); +#endif + + private: +#ifdef _WIN32 + DWORD process_start_error_; + HANDLE child_handle_; + + // The file handles for our end of the child's pipes. We close each and + // set it to NULL when no longer needed. + HANDLE child_stdin_; + HANDLE child_stdout_; + +#else // _WIN32 + pid_t child_pid_; + + // The file descriptors for our end of the child's pipes. We close each and + // set it to -1 when no longer needed. + int child_stdin_; + int child_stdout_; + +#endif // !_WIN32 +}; + +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/test_plugin.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/test_plugin.cc new file mode 100644 index 000000000..5cbbf3d9d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/test_plugin.cc @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// This is a dummy code generator plugin used by +// command_line_interface_unittest. + +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) { +#ifdef _MSC_VER + // Don't print a silly message or stick a modal dialog box in my face, + // please. + _set_abort_behavior(0, ~0); +#endif // !_MSC_VER + + google::protobuf::compiler::MockCodeGenerator generator("test_plugin"); + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_output_unittest.sh b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_output_unittest.sh new file mode 100644 index 000000000..3a024364d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_output_unittest.sh @@ -0,0 +1,91 @@ +#!/bin/sh +# +# Protocol Buffers - Google's data interchange format +# Copyright 2009 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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) +# +# Test protoc's zip output mode. + +fail() { + echo "$@" >&2 + exit 1 +} + +TEST_TMPDIR=. +PROTOC=./protoc + +echo ' + syntax = "proto2"; + option java_multiple_files = true; + option java_package = "test.jar"; + option java_outer_classname = "Outer"; + message Foo {} + message Bar {} +' > $TEST_TMPDIR/testzip.proto + +$PROTOC \ + --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \ + --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \ + || fail 'protoc failed.' + +echo "Testing output to zip..." +if unzip -h > /dev/null; then + unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.' + + grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'testzip.pb.cc not found in output zip.' + grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'testzip.pb.h not found in output zip.' + grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'testzip_pb2.py not found in output zip.' + grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \ + && fail 'Zip file contained manifest.' +else + echo "Warning: 'unzip' command not available. Skipping test." +fi + +echo "Testing output to jar..." +if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then + jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.' + + grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Foo.java not found in output jar.' + grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Bar.java not found in output jar.' + grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Outer.java not found in output jar.' + grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Manifest not found in output jar.' +else + echo "Warning: 'jar' command not available. Skipping test." +fi + +echo PASS diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.cc new file mode 100644 index 000000000..65d735270 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.cc @@ -0,0 +1,218 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: ambrose@google.com (Ambrose Feinstein), +// kenton@google.com (Kenton Varda) +// +// Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +static const uint32 kCRC32Table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static uint32 ComputeCRC32(const string &buf) { + uint32 x = ~0U; + for (int i = 0; i < buf.size(); ++i) { + unsigned char c = buf[i]; + x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8); + } + return ~x; +} + +static void WriteShort(io::CodedOutputStream *out, uint16 val) { + uint8 p[2]; + p[0] = static_cast(val); + p[1] = static_cast(val >> 8); + out->WriteRaw(p, 2); +} + +ZipWriter::ZipWriter(io::ZeroCopyOutputStream* raw_output) + : raw_output_(raw_output) {} +ZipWriter::~ZipWriter() {} + +bool ZipWriter::Write(const string& filename, const string& contents) { + FileInfo info; + + info.name = filename; + uint16 filename_size = filename.size(); + info.offset = raw_output_->ByteCount(); + info.size = contents.size(); + info.crc32 = ComputeCRC32(contents); + + files_.push_back(info); + + // write file header + io::CodedOutputStream output(raw_output_); + output.WriteLittleEndian32(0x04034b50); // magic + WriteShort(&output, 10); // version needed to extract + WriteShort(&output, 0); // flags + WriteShort(&output, 0); // compression method: stored + WriteShort(&output, 0); // last modified time + WriteShort(&output, 0); // last modified date + output.WriteLittleEndian32(info.crc32); // crc-32 + output.WriteLittleEndian32(info.size); // compressed size + output.WriteLittleEndian32(info.size); // uncompressed size + WriteShort(&output, filename_size); // file name length + WriteShort(&output, 0); // extra field length + output.WriteString(filename); // file name + output.WriteString(contents); // file data + + return !output.HadError(); +} + +bool ZipWriter::WriteDirectory() { + uint16 num_entries = files_.size(); + uint32 dir_ofs = raw_output_->ByteCount(); + + // write central directory + io::CodedOutputStream output(raw_output_); + for (int i = 0; i < num_entries; ++i) { + const string &filename = files_[i].name; + uint16 filename_size = filename.size(); + uint32 crc32 = files_[i].crc32; + uint32 size = files_[i].size; + uint32 offset = files_[i].offset; + + output.WriteLittleEndian32(0x02014b50); // magic + WriteShort(&output, 10); // version made by + WriteShort(&output, 10); // version needed to extract + WriteShort(&output, 0); // flags + WriteShort(&output, 0); // compression method: stored + WriteShort(&output, 0); // last modified time + WriteShort(&output, 0); // last modified date + output.WriteLittleEndian32(crc32); // crc-32 + output.WriteLittleEndian32(size); // compressed size + output.WriteLittleEndian32(size); // uncompressed size + WriteShort(&output, filename_size); // file name length + WriteShort(&output, 0); // extra field length + WriteShort(&output, 0); // file comment length + WriteShort(&output, 0); // starting disk number + WriteShort(&output, 0); // internal file attributes + output.WriteLittleEndian32(0); // external file attributes + output.WriteLittleEndian32(offset); // local header offset + output.WriteString(filename); // file name + } + uint32 dir_len = output.ByteCount(); + + // write end of central directory marker + output.WriteLittleEndian32(0x06054b50); // magic + WriteShort(&output, 0); // disk number + WriteShort(&output, 0); // disk with start of central directory + WriteShort(&output, num_entries); // central directory entries (this disk) + WriteShort(&output, num_entries); // central directory entries (total) + output.WriteLittleEndian32(dir_len); // central directory byte size + output.WriteLittleEndian32(dir_ofs); // central directory offset + WriteShort(&output, 0); // comment length + + return output.HadError(); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.h new file mode 100644 index 000000000..be73972a6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/compiler/zip_writer.h @@ -0,0 +1,93 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { + +class ZipWriter { + public: + ZipWriter(io::ZeroCopyOutputStream* raw_output); + ~ZipWriter(); + + bool Write(const string& filename, const string& contents); + bool WriteDirectory(); + + private: + struct FileInfo { + string name; + uint32 offset; + uint32 size; + uint32 crc32; + }; + + io::ZeroCopyOutputStream* raw_output_; + vector files_; +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.cc new file mode 100644 index 000000000..c941aacca --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.cc @@ -0,0 +1,4949 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef PACKAGE // autoheader #defines this. :( + +namespace google { +namespace protobuf { + +const FieldDescriptor::CppType +FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = { + static_cast(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 +}; + +const char * const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "double", // TYPE_DOUBLE + "float", // TYPE_FLOAT + "int64", // TYPE_INT64 + "uint64", // TYPE_UINT64 + "int32", // TYPE_INT32 + "fixed64", // TYPE_FIXED64 + "fixed32", // TYPE_FIXED32 + "bool", // TYPE_BOOL + "string", // TYPE_STRING + "group", // TYPE_GROUP + "message", // TYPE_MESSAGE + "bytes", // TYPE_BYTES + "uint32", // TYPE_UINT32 + "enum", // TYPE_ENUM + "sfixed32", // TYPE_SFIXED32 + "sfixed64", // TYPE_SFIXED64 + "sint32", // TYPE_SINT32 + "sint64", // TYPE_SINT64 +}; + +const char * const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = { + "ERROR", // 0 is reserved for errors + + "int32", // CPPTYPE_INT32 + "int64", // CPPTYPE_INT64 + "uint32", // CPPTYPE_UINT32 + "uint64", // CPPTYPE_UINT64 + "double", // CPPTYPE_DOUBLE + "float", // CPPTYPE_FLOAT + "bool", // CPPTYPE_BOOL + "enum", // CPPTYPE_ENUM + "string", // CPPTYPE_STRING + "message", // CPPTYPE_MESSAGE +}; + +const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { + "ERROR", // 0 is reserved for errors + + "optional", // LABEL_OPTIONAL + "required", // LABEL_REQUIRED + "repeated", // LABEL_REPEATED +}; + +#ifndef _MSC_VER // MSVC doesn't need these and won't even accept them. +const int FieldDescriptor::kMaxNumber; +const int FieldDescriptor::kFirstReservedNumber; +const int FieldDescriptor::kLastReservedNumber; +#endif + +namespace { + +const string kEmptyString; + +string ToCamelCase(const string& input) { + bool capitalize_next = false; + string result; + result.reserve(input.size()); + + for (int i = 0; i < input.size(); i++) { + if (input[i] == '_') { + capitalize_next = true; + } else if (capitalize_next) { + // Note: I distrust ctype.h due to locales. + if ('a' <= input[i] && input[i] <= 'z') { + result.push_back(input[i] - 'a' + 'A'); + } else { + result.push_back(input[i]); + } + capitalize_next = false; + } else { + result.push_back(input[i]); + } + } + + // Lower-case the first letter. + if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') { + result[0] = result[0] - 'A' + 'a'; + } + + return result; +} + +// A DescriptorPool contains a bunch of hash_maps to implement the +// various Find*By*() methods. Since hashtable lookups are O(1), it's +// most efficient to construct a fixed set of large hash_maps used by +// all objects in the pool rather than construct one or more small +// hash_maps for each object. +// +// The keys to these hash_maps are (parent, name) or (parent, number) +// pairs. Unfortunately STL doesn't provide hash functions for pair<>, +// so we must invent our own. +// +// TODO(kenton): Use StringPiece rather than const char* in keys? It would +// be a lot cleaner but we'd just have to convert it back to const char* +// for the open source release. + +typedef pair PointerStringPair; + +struct PointerStringPairEqual { + inline bool operator()(const PointerStringPair& a, + const PointerStringPair& b) const { + return a.first == b.first && strcmp(a.second, b.second) == 0; + } +}; + +template +struct PointerIntegerPairHash { + size_t operator()(const PairType& p) const { + // FIXME(kenton): What is the best way to compute this hash? I have + // no idea! This seems a bit better than an XOR. + return reinterpret_cast(p.first) * ((1 << 16) - 1) + p.second; + } + + // Used only by MSVC and platforms where hash_map is not available. + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const PairType& a, const PairType& b) const { + return a.first < b.first || + (a.first == b.first && a.second < b.second); + } +}; + +typedef pair DescriptorIntPair; +typedef pair EnumIntPair; + +struct PointerStringPairHash { + size_t operator()(const PointerStringPair& p) const { + // FIXME(kenton): What is the best way to compute this hash? I have + // no idea! This seems a bit better than an XOR. + hash cstring_hash; + return reinterpret_cast(p.first) * ((1 << 16) - 1) + + cstring_hash(p.second); + } + + // Used only by MSVC and platforms where hash_map is not available. + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const PointerStringPair& a, + const PointerStringPair& b) const { + if (a.first < b.first) return true; + if (a.first > b.first) return false; + return strcmp(a.second, b.second) < 0; + } +}; + + +struct Symbol { + enum Type { + NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, + PACKAGE + }; + Type type; + union { + const Descriptor* descriptor; + const FieldDescriptor* field_descriptor; + const EnumDescriptor* enum_descriptor; + const EnumValueDescriptor* enum_value_descriptor; + const ServiceDescriptor* service_descriptor; + const MethodDescriptor* method_descriptor; + const FileDescriptor* package_file_descriptor; + }; + + inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; } + inline bool IsNull() const { return type == NULL_SYMBOL; } + inline bool IsType() const { + return type == MESSAGE || type == ENUM; + } + inline bool IsAggregate() const { + return type == MESSAGE || type == PACKAGE + || type == ENUM || type == SERVICE; + } + +#define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \ + inline explicit Symbol(const TYPE* value) { \ + type = TYPE_CONSTANT; \ + this->FIELD = value; \ + } + + CONSTRUCTOR(Descriptor , MESSAGE , descriptor ) + CONSTRUCTOR(FieldDescriptor , FIELD , field_descriptor ) + CONSTRUCTOR(EnumDescriptor , ENUM , enum_descriptor ) + CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor ) + CONSTRUCTOR(ServiceDescriptor , SERVICE , service_descriptor ) + CONSTRUCTOR(MethodDescriptor , METHOD , method_descriptor ) + CONSTRUCTOR(FileDescriptor , PACKAGE , package_file_descriptor) +#undef CONSTRUCTOR + + const FileDescriptor* GetFile() const { + switch (type) { + case NULL_SYMBOL: return NULL; + case MESSAGE : return descriptor ->file(); + case FIELD : return field_descriptor ->file(); + case ENUM : return enum_descriptor ->file(); + case ENUM_VALUE : return enum_value_descriptor->type()->file(); + case SERVICE : return service_descriptor ->file(); + case METHOD : return method_descriptor ->service()->file(); + case PACKAGE : return package_file_descriptor; + } + return NULL; + } +}; + +const Symbol kNullSymbol; + +typedef hash_map, streq> + SymbolsByNameMap; +typedef hash_map + SymbolsByParentMap; +typedef hash_map, streq> + FilesByNameMap; +typedef hash_map + FieldsByNameMap; +typedef hash_map > + FieldsByNumberMap; +typedef hash_map > + EnumValuesByNumberMap; +// This is a map rather than a hash_map, since we use it to iterate +// through all the extensions that extend a given Descriptor, and an +// ordered data structure that implements lower_bound is convenient +// for that. +typedef map + ExtensionsGroupedByDescriptorMap; + +} // anonymous namespace + +// =================================================================== +// DescriptorPool::Tables + +class DescriptorPool::Tables { + public: + Tables(); + ~Tables(); + + // Record the current state of the tables to the stack of checkpoints. + // Each call to AddCheckpoint() must be paired with exactly one call to either + // ClearLastCheckpoint() or RollbackToLastCheckpoint(). + // + // This is used when building files, since some kinds of validation errors + // cannot be detected until the file's descriptors have already been added to + // the tables. + // + // This supports recursive checkpoints, since building a file may trigger + // recursive building of other files. Note that recursive checkpoints are not + // normally necessary; explicit dependencies are built prior to checkpointing. + // So although we recursively build transitive imports, there is at most one + // checkpoint in the stack during dependency building. + // + // Recursive checkpoints only arise during cross-linking of the descriptors. + // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and + // friends. If the pending file references an unknown symbol + // (e.g., it is not defined in the pending file's explicit dependencies), and + // the pool is using a fallback database, and that database contains a file + // defining that symbol, and that file has not yet been built by the pool, + // the pool builds the file during cross-linking, leading to another + // checkpoint. + void AddCheckpoint(); + + // Mark the last checkpoint as having cleared successfully, removing it from + // the stack. If the stack is empty, all pending symbols will be committed. + // + // Note that this does not guarantee that the symbols added since the last + // checkpoint won't be rolled back: if a checkpoint gets rolled back, + // everything past that point gets rolled back, including symbols added after + // checkpoints that were pushed onto the stack after it and marked as cleared. + void ClearLastCheckpoint(); + + // Roll back the Tables to the state of the checkpoint at the top of the + // stack, removing everything that was added after that point. + void RollbackToLastCheckpoint(); + + // The stack of files which are currently being built. Used to detect + // cyclic dependencies when loading files from a DescriptorDatabase. Not + // used when fallback_database_ == NULL. + vector pending_files_; + + // A set of files which we have tried to load from the fallback database + // and encountered errors. We will not attempt to load them again. + // Not used when fallback_database_ == NULL. + hash_set known_bad_files_; + + // The set of descriptors for which we've already loaded the full + // set of extensions numbers from fallback_database_. + hash_set extensions_loaded_from_db_; + + // ----------------------------------------------------------------- + // Finding items. + + // Find symbols. This returns a null Symbol (symbol.IsNull() is true) + // if not found. + inline Symbol FindSymbol(const string& key) const; + + // This implements the body of DescriptorPool::Find*ByName(). It should + // really be a private method of DescriptorPool, but that would require + // declaring Symbol in descriptor.h, which would drag all kinds of other + // stuff into the header. Yay C++. + Symbol FindByNameHelper( + const DescriptorPool* pool, const string& name) const; + + // These return NULL if not found. + inline const FileDescriptor* FindFile(const string& key) const; + inline const FieldDescriptor* FindExtension(const Descriptor* extendee, + int number); + inline void FindAllExtensions(const Descriptor* extendee, + vector* out) const; + + // ----------------------------------------------------------------- + // Adding items. + + // These add items to the corresponding tables. They return false if + // the key already exists in the table. For AddSymbol(), the string passed + // in must be one that was constructed using AllocateString(), as it will + // be used as a key in the symbols_by_name_ map without copying. + bool AddSymbol(const string& full_name, Symbol symbol); + bool AddFile(const FileDescriptor* file); + bool AddExtension(const FieldDescriptor* field); + + // ----------------------------------------------------------------- + // Allocating memory. + + // Allocate an object which will be reclaimed when the pool is + // destroyed. Note that the object's destructor will never be called, + // so its fields must be plain old data (primitive data types and + // pointers). All of the descriptor types are such objects. + template Type* Allocate(); + + // Allocate an array of objects which will be reclaimed when the + // pool in destroyed. Again, destructors are never called. + template Type* AllocateArray(int count); + + // Allocate a string which will be destroyed when the pool is destroyed. + // The string is initialized to the given value for convenience. + string* AllocateString(const string& value); + + // Allocate a protocol message object. Some older versions of GCC have + // trouble understanding explicit template instantiations in some cases, so + // in those cases we have to pass a dummy pointer of the right type as the + // parameter instead of specifying the type explicitly. + template Type* AllocateMessage(Type* dummy = NULL); + + // Allocate a FileDescriptorTables object. + FileDescriptorTables* AllocateFileTables(); + + private: + vector strings_; // All strings in the pool. + vector messages_; // All messages in the pool. + vector file_tables_; // All file tables in the pool. + vector allocations_; // All other memory allocated in the pool. + + SymbolsByNameMap symbols_by_name_; + FilesByNameMap files_by_name_; + ExtensionsGroupedByDescriptorMap extensions_; + + struct CheckPoint { + explicit CheckPoint(const Tables* tables) + : strings_before_checkpoint(tables->strings_.size()), + messages_before_checkpoint(tables->messages_.size()), + file_tables_before_checkpoint(tables->file_tables_.size()), + allocations_before_checkpoint(tables->allocations_.size()), + pending_symbols_before_checkpoint( + tables->symbols_after_checkpoint_.size()), + pending_files_before_checkpoint( + tables->files_after_checkpoint_.size()), + pending_extensions_before_checkpoint( + tables->extensions_after_checkpoint_.size()) { + } + int strings_before_checkpoint; + int messages_before_checkpoint; + int file_tables_before_checkpoint; + int allocations_before_checkpoint; + int pending_symbols_before_checkpoint; + int pending_files_before_checkpoint; + int pending_extensions_before_checkpoint; + }; + vector checkpoints_; + vector symbols_after_checkpoint_; + vector files_after_checkpoint_; + vector extensions_after_checkpoint_; + + // Allocate some bytes which will be reclaimed when the pool is + // destroyed. + void* AllocateBytes(int size); +}; + +// Contains tables specific to a particular file. These tables are not +// modified once the file has been constructed, so they need not be +// protected by a mutex. This makes operations that depend only on the +// contents of a single file -- e.g. Descriptor::FindFieldByName() -- +// lock-free. +// +// For historical reasons, the definitions of the methods of +// FileDescriptorTables and DescriptorPool::Tables are interleaved below. +// These used to be a single class. +class FileDescriptorTables { + public: + FileDescriptorTables(); + ~FileDescriptorTables(); + + // Empty table, used with placeholder files. + static const FileDescriptorTables kEmpty; + + // ----------------------------------------------------------------- + // Finding items. + + // Find symbols. These return a null Symbol (symbol.IsNull() is true) + // if not found. + inline Symbol FindNestedSymbol(const void* parent, + const string& name) const; + inline Symbol FindNestedSymbolOfType(const void* parent, + const string& name, + const Symbol::Type type) const; + + // These return NULL if not found. + inline const FieldDescriptor* FindFieldByNumber( + const Descriptor* parent, int number) const; + inline const FieldDescriptor* FindFieldByLowercaseName( + const void* parent, const string& lowercase_name) const; + inline const FieldDescriptor* FindFieldByCamelcaseName( + const void* parent, const string& camelcase_name) const; + inline const EnumValueDescriptor* FindEnumValueByNumber( + const EnumDescriptor* parent, int number) const; + + // ----------------------------------------------------------------- + // Adding items. + + // These add items to the corresponding tables. They return false if + // the key already exists in the table. For AddAliasUnderParent(), the + // string passed in must be one that was constructed using AllocateString(), + // as it will be used as a key in the symbols_by_parent_ map without copying. + bool AddAliasUnderParent(const void* parent, const string& name, + Symbol symbol); + bool AddFieldByNumber(const FieldDescriptor* field); + bool AddEnumValueByNumber(const EnumValueDescriptor* value); + + // Adds the field to the lowercase_name and camelcase_name maps. Never + // fails because we allow duplicates; the first field by the name wins. + void AddFieldByStylizedNames(const FieldDescriptor* field); + + private: + SymbolsByParentMap symbols_by_parent_; + FieldsByNameMap fields_by_lowercase_name_; + FieldsByNameMap fields_by_camelcase_name_; + FieldsByNumberMap fields_by_number_; // Not including extensions. + EnumValuesByNumberMap enum_values_by_number_; +}; + +DescriptorPool::Tables::Tables() + // Start some hash_map and hash_set objects with a small # of buckets + : known_bad_files_(3), + extensions_loaded_from_db_(3), + symbols_by_name_(3), + files_by_name_(3) {} + + +DescriptorPool::Tables::~Tables() { + GOOGLE_DCHECK(checkpoints_.empty()); + // Note that the deletion order is important, since the destructors of some + // messages may refer to objects in allocations_. + STLDeleteElements(&messages_); + for (int i = 0; i < allocations_.size(); i++) { + operator delete(allocations_[i]); + } + STLDeleteElements(&strings_); + STLDeleteElements(&file_tables_); +} + +FileDescriptorTables::FileDescriptorTables() + // Initialize all the hash tables to start out with a small # of buckets + : symbols_by_parent_(3), + fields_by_lowercase_name_(3), + fields_by_camelcase_name_(3), + fields_by_number_(3), + enum_values_by_number_(3) { +} + +FileDescriptorTables::~FileDescriptorTables() {} + +const FileDescriptorTables FileDescriptorTables::kEmpty; + +void DescriptorPool::Tables::AddCheckpoint() { + checkpoints_.push_back(CheckPoint(this)); +} + +void DescriptorPool::Tables::ClearLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + checkpoints_.pop_back(); + if (checkpoints_.empty()) { + // All checkpoints have been cleared: we can now commit all of the pending + // data. + symbols_after_checkpoint_.clear(); + files_after_checkpoint_.clear(); + extensions_after_checkpoint_.clear(); + } +} + +void DescriptorPool::Tables::RollbackToLastCheckpoint() { + GOOGLE_DCHECK(!checkpoints_.empty()); + const CheckPoint& checkpoint = checkpoints_.back(); + + for (int i = checkpoint.pending_symbols_before_checkpoint; + i < symbols_after_checkpoint_.size(); + i++) { + symbols_by_name_.erase(symbols_after_checkpoint_[i]); + } + for (int i = checkpoint.pending_files_before_checkpoint; + i < files_after_checkpoint_.size(); + i++) { + files_by_name_.erase(files_after_checkpoint_[i]); + } + for (int i = checkpoint.pending_extensions_before_checkpoint; + i < extensions_after_checkpoint_.size(); + i++) { + extensions_.erase(extensions_after_checkpoint_[i]); + } + + symbols_after_checkpoint_.resize( + checkpoint.pending_symbols_before_checkpoint); + files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint); + extensions_after_checkpoint_.resize( + checkpoint.pending_extensions_before_checkpoint); + + STLDeleteContainerPointers( + strings_.begin() + checkpoint.strings_before_checkpoint, strings_.end()); + STLDeleteContainerPointers( + messages_.begin() + checkpoint.messages_before_checkpoint, + messages_.end()); + STLDeleteContainerPointers( + file_tables_.begin() + checkpoint.file_tables_before_checkpoint, + file_tables_.end()); + for (int i = checkpoint.allocations_before_checkpoint; + i < allocations_.size(); + i++) { + operator delete(allocations_[i]); + } + + strings_.resize(checkpoint.strings_before_checkpoint); + messages_.resize(checkpoint.messages_before_checkpoint); + file_tables_.resize(checkpoint.file_tables_before_checkpoint); + allocations_.resize(checkpoint.allocations_before_checkpoint); + checkpoints_.pop_back(); +} + +// ------------------------------------------------------------------- + +inline Symbol DescriptorPool::Tables::FindSymbol(const string& key) const { + const Symbol* result = FindOrNull(symbols_by_name_, key.c_str()); + if (result == NULL) { + return kNullSymbol; + } else { + return *result; + } +} + +inline Symbol FileDescriptorTables::FindNestedSymbol( + const void* parent, const string& name) const { + const Symbol* result = + FindOrNull(symbols_by_parent_, PointerStringPair(parent, name.c_str())); + if (result == NULL) { + return kNullSymbol; + } else { + return *result; + } +} + +inline Symbol FileDescriptorTables::FindNestedSymbolOfType( + const void* parent, const string& name, const Symbol::Type type) const { + Symbol result = FindNestedSymbol(parent, name); + if (result.type != type) return kNullSymbol; + return result; +} + +Symbol DescriptorPool::Tables::FindByNameHelper( + const DescriptorPool* pool, const string& name) const { + MutexLockMaybe lock(pool->mutex_); + Symbol result = FindSymbol(name); + + if (result.IsNull() && pool->underlay_ != NULL) { + // Symbol not found; check the underlay. + result = + pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name); + } + + if (result.IsNull()) { + // Symbol still not found, so check fallback database. + if (pool->TryFindSymbolInFallbackDatabase(name)) { + result = FindSymbol(name); + } + } + + return result; +} + +inline const FileDescriptor* DescriptorPool::Tables::FindFile( + const string& key) const { + return FindPtrOrNull(files_by_name_, key.c_str()); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( + const Descriptor* parent, int number) const { + return FindPtrOrNull(fields_by_number_, make_pair(parent, number)); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( + const void* parent, const string& lowercase_name) const { + return FindPtrOrNull(fields_by_lowercase_name_, + PointerStringPair(parent, lowercase_name.c_str())); +} + +inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( + const void* parent, const string& camelcase_name) const { + return FindPtrOrNull(fields_by_camelcase_name_, + PointerStringPair(parent, camelcase_name.c_str())); +} + +inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( + const EnumDescriptor* parent, int number) const { + return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number)); +} + +inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( + const Descriptor* extendee, int number) { + return FindPtrOrNull(extensions_, make_pair(extendee, number)); +} + +inline void DescriptorPool::Tables::FindAllExtensions( + const Descriptor* extendee, vector* out) const { + ExtensionsGroupedByDescriptorMap::const_iterator it = + extensions_.lower_bound(make_pair(extendee, 0)); + for (; it != extensions_.end() && it->first.first == extendee; ++it) { + out->push_back(it->second); + } +} + +// ------------------------------------------------------------------- + +bool DescriptorPool::Tables::AddSymbol( + const string& full_name, Symbol symbol) { + if (InsertIfNotPresent(&symbols_by_name_, full_name.c_str(), symbol)) { + symbols_after_checkpoint_.push_back(full_name.c_str()); + return true; + } else { + return false; + } +} + +bool FileDescriptorTables::AddAliasUnderParent( + const void* parent, const string& name, Symbol symbol) { + PointerStringPair by_parent_key(parent, name.c_str()); + return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol); +} + +bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) { + if (InsertIfNotPresent(&files_by_name_, file->name().c_str(), file)) { + files_after_checkpoint_.push_back(file->name().c_str()); + return true; + } else { + return false; + } +} + +void FileDescriptorTables::AddFieldByStylizedNames( + const FieldDescriptor* field) { + const void* parent; + if (field->is_extension()) { + if (field->extension_scope() == NULL) { + parent = field->file(); + } else { + parent = field->extension_scope(); + } + } else { + parent = field->containing_type(); + } + + PointerStringPair lowercase_key(parent, field->lowercase_name().c_str()); + InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key, field); + + PointerStringPair camelcase_key(parent, field->camelcase_name().c_str()); + InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key, field); +} + +bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) { + DescriptorIntPair key(field->containing_type(), field->number()); + return InsertIfNotPresent(&fields_by_number_, key, field); +} + +bool FileDescriptorTables::AddEnumValueByNumber( + const EnumValueDescriptor* value) { + EnumIntPair key(value->type(), value->number()); + return InsertIfNotPresent(&enum_values_by_number_, key, value); +} + +bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) { + DescriptorIntPair key(field->containing_type(), field->number()); + if (InsertIfNotPresent(&extensions_, key, field)) { + extensions_after_checkpoint_.push_back(key); + return true; + } else { + return false; + } +} + +// ------------------------------------------------------------------- + +template +Type* DescriptorPool::Tables::Allocate() { + return reinterpret_cast(AllocateBytes(sizeof(Type))); +} + +template +Type* DescriptorPool::Tables::AllocateArray(int count) { + return reinterpret_cast(AllocateBytes(sizeof(Type) * count)); +} + +string* DescriptorPool::Tables::AllocateString(const string& value) { + string* result = new string(value); + strings_.push_back(result); + return result; +} + +template +Type* DescriptorPool::Tables::AllocateMessage(Type* dummy) { + Type* result = new Type; + messages_.push_back(result); + return result; +} + +FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() { + FileDescriptorTables* result = new FileDescriptorTables; + file_tables_.push_back(result); + return result; +} + +void* DescriptorPool::Tables::AllocateBytes(int size) { + // TODO(kenton): Would it be worthwhile to implement this in some more + // sophisticated way? Probably not for the open source release, but for + // internal use we could easily plug in one of our existing memory pool + // allocators... + if (size == 0) return NULL; + + void* result = operator new(size); + allocations_.push_back(result); + return result; +} + +// =================================================================== +// DescriptorPool + +DescriptorPool::ErrorCollector::~ErrorCollector() {} + +DescriptorPool::DescriptorPool() + : mutex_(NULL), + fallback_database_(NULL), + default_error_collector_(NULL), + underlay_(NULL), + tables_(new Tables), + enforce_dependencies_(true), + allow_unknown_(false) {} + +DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, + ErrorCollector* error_collector) + : mutex_(new Mutex), + fallback_database_(fallback_database), + default_error_collector_(error_collector), + underlay_(NULL), + tables_(new Tables), + enforce_dependencies_(true), + allow_unknown_(false) { +} + +DescriptorPool::DescriptorPool(const DescriptorPool* underlay) + : mutex_(NULL), + fallback_database_(NULL), + default_error_collector_(NULL), + underlay_(underlay), + tables_(new Tables), + enforce_dependencies_(true), + allow_unknown_(false) {} + +DescriptorPool::~DescriptorPool() { + if (mutex_ != NULL) delete mutex_; +} + +// DescriptorPool::BuildFile() defined later. +// DescriptorPool::BuildFileCollectingErrors() defined later. + +void DescriptorPool::InternalDontEnforceDependencies() { + enforce_dependencies_ = false; +} + +bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { + MutexLockMaybe lock(mutex_); + return tables_->FindFile(filename) != NULL; +} + +// generated_pool ==================================================== + +namespace { + + +EncodedDescriptorDatabase* generated_database_ = NULL; +DescriptorPool* generated_pool_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(generated_pool_init_); + +void DeleteGeneratedPool() { + delete generated_database_; + generated_database_ = NULL; + delete generated_pool_; + generated_pool_ = NULL; +} + +static void InitGeneratedPool() { + generated_database_ = new EncodedDescriptorDatabase; + generated_pool_ = new DescriptorPool(generated_database_); + + internal::OnShutdown(&DeleteGeneratedPool); +} + +inline void InitGeneratedPoolOnce() { + ::google::protobuf::GoogleOnceInit(&generated_pool_init_, &InitGeneratedPool); +} + +} // anonymous namespace + +const DescriptorPool* DescriptorPool::generated_pool() { + InitGeneratedPoolOnce(); + return generated_pool_; +} + +DescriptorPool* DescriptorPool::internal_generated_pool() { + InitGeneratedPoolOnce(); + return generated_pool_; +} + +void DescriptorPool::InternalAddGeneratedFile( + const void* encoded_file_descriptor, int size) { + // So, this function is called in the process of initializing the + // descriptors for generated proto classes. Each generated .pb.cc file + // has an internal procedure called AddDescriptors() which is called at + // process startup, and that function calls this one in order to register + // the raw bytes of the FileDescriptorProto representing the file. + // + // We do not actually construct the descriptor objects right away. We just + // hang on to the bytes until they are actually needed. We actually construct + // the descriptor the first time one of the following things happens: + // * Someone calls a method like descriptor(), GetDescriptor(), or + // GetReflection() on the generated types, which requires returning the + // descriptor or an object based on it. + // * Someone looks up the descriptor in DescriptorPool::generated_pool(). + // + // Once one of these happens, the DescriptorPool actually parses the + // FileDescriptorProto and generates a FileDescriptor (and all its children) + // based on it. + // + // Note that FileDescriptorProto is itself a generated protocol message. + // Therefore, when we parse one, we have to be very careful to avoid using + // any descriptor-based operations, since this might cause infinite recursion + // or deadlock. + InitGeneratedPoolOnce(); + GOOGLE_CHECK(generated_database_->Add(encoded_file_descriptor, size)); +} + + +// Find*By* methods ================================================== + +// TODO(kenton): There's a lot of repeated code here, but I'm not sure if +// there's any good way to factor it out. Think about this some time when +// there's nothing more important to do (read: never). + +const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { + MutexLockMaybe lock(mutex_); + const FileDescriptor* result = tables_->FindFile(name); + if (result != NULL) return result; + if (underlay_ != NULL) { + result = underlay_->FindFileByName(name); + if (result != NULL) return result; + } + if (TryFindFileInFallbackDatabase(name)) { + result = tables_->FindFile(name); + if (result != NULL) return result; + } + return NULL; +} + +const FileDescriptor* DescriptorPool::FindFileContainingSymbol( + const string& symbol_name) const { + MutexLockMaybe lock(mutex_); + Symbol result = tables_->FindSymbol(symbol_name); + if (!result.IsNull()) return result.GetFile(); + if (underlay_ != NULL) { + const FileDescriptor* file_result = + underlay_->FindFileContainingSymbol(symbol_name); + if (file_result != NULL) return file_result; + } + if (TryFindSymbolInFallbackDatabase(symbol_name)) { + result = tables_->FindSymbol(symbol_name); + if (!result.IsNull()) return result.GetFile(); + } + return NULL; +} + +const Descriptor* DescriptorPool::FindMessageTypeByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL; +} + +const FieldDescriptor* DescriptorPool::FindFieldByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + if (result.type == Symbol::FIELD && + !result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } +} + +const FieldDescriptor* DescriptorPool::FindExtensionByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + if (result.type == Symbol::FIELD && + result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } +} + +const EnumDescriptor* DescriptorPool::FindEnumTypeByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL; +} + +const EnumValueDescriptor* DescriptorPool::FindEnumValueByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::ENUM_VALUE) ? + result.enum_value_descriptor : NULL; +} + +const ServiceDescriptor* DescriptorPool::FindServiceByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL; +} + +const MethodDescriptor* DescriptorPool::FindMethodByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL; +} + +const FieldDescriptor* DescriptorPool::FindExtensionByNumber( + const Descriptor* extendee, int number) const { + MutexLockMaybe lock(mutex_); + const FieldDescriptor* result = tables_->FindExtension(extendee, number); + if (result != NULL) { + return result; + } + if (underlay_ != NULL) { + result = underlay_->FindExtensionByNumber(extendee, number); + if (result != NULL) return result; + } + if (TryFindExtensionInFallbackDatabase(extendee, number)) { + result = tables_->FindExtension(extendee, number); + if (result != NULL) { + return result; + } + } + return NULL; +} + +void DescriptorPool::FindAllExtensions( + const Descriptor* extendee, vector* out) const { + MutexLockMaybe lock(mutex_); + + // Initialize tables_->extensions_ from the fallback database first + // (but do this only once per descriptor). + if (fallback_database_ != NULL && + tables_->extensions_loaded_from_db_.count(extendee) == 0) { + vector numbers; + if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), + &numbers)) { + for (int i = 0; i < numbers.size(); ++i) { + int number = numbers[i]; + if (tables_->FindExtension(extendee, number) == NULL) { + TryFindExtensionInFallbackDatabase(extendee, number); + } + } + tables_->extensions_loaded_from_db_.insert(extendee); + } + } + + tables_->FindAllExtensions(extendee, out); + if (underlay_ != NULL) { + underlay_->FindAllExtensions(extendee, out); + } +} + +// ------------------------------------------------------------------- + +const FieldDescriptor* +Descriptor::FindFieldByNumber(int key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByNumber(this, key); + if (result == NULL || result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const FieldDescriptor* +Descriptor::FindFieldByLowercaseName(const string& key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == NULL || result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const FieldDescriptor* +Descriptor::FindFieldByCamelcaseName(const string& key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == NULL || result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const FieldDescriptor* +Descriptor::FindFieldByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); + if (!result.IsNull() && !result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } +} + +const FieldDescriptor* +Descriptor::FindExtensionByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); + if (!result.IsNull() && result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } +} + +const FieldDescriptor* +Descriptor::FindExtensionByLowercaseName(const string& key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByLowercaseName(this, key); + if (result == NULL || !result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const FieldDescriptor* +Descriptor::FindExtensionByCamelcaseName(const string& key) const { + const FieldDescriptor* result = + file()->tables_->FindFieldByCamelcaseName(this, key); + if (result == NULL || !result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const Descriptor* +Descriptor::FindNestedTypeByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); + if (!result.IsNull()) { + return result.descriptor; + } else { + return NULL; + } +} + +const EnumDescriptor* +Descriptor::FindEnumTypeByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); + if (!result.IsNull()) { + return result.enum_descriptor; + } else { + return NULL; + } +} + +const EnumValueDescriptor* +Descriptor::FindEnumValueByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + if (!result.IsNull()) { + return result.enum_value_descriptor; + } else { + return NULL; + } +} + +const EnumValueDescriptor* +EnumDescriptor::FindValueByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + if (!result.IsNull()) { + return result.enum_value_descriptor; + } else { + return NULL; + } +} + +const EnumValueDescriptor* +EnumDescriptor::FindValueByNumber(int key) const { + return file()->tables_->FindEnumValueByNumber(this, key); +} + +const MethodDescriptor* +ServiceDescriptor::FindMethodByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD); + if (!result.IsNull()) { + return result.method_descriptor; + } else { + return NULL; + } +} + +const Descriptor* +FileDescriptor::FindMessageTypeByName(const string& key) const { + Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE); + if (!result.IsNull()) { + return result.descriptor; + } else { + return NULL; + } +} + +const EnumDescriptor* +FileDescriptor::FindEnumTypeByName(const string& key) const { + Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM); + if (!result.IsNull()) { + return result.enum_descriptor; + } else { + return NULL; + } +} + +const EnumValueDescriptor* +FileDescriptor::FindEnumValueByName(const string& key) const { + Symbol result = + tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE); + if (!result.IsNull()) { + return result.enum_value_descriptor; + } else { + return NULL; + } +} + +const ServiceDescriptor* +FileDescriptor::FindServiceByName(const string& key) const { + Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE); + if (!result.IsNull()) { + return result.service_descriptor; + } else { + return NULL; + } +} + +const FieldDescriptor* +FileDescriptor::FindExtensionByName(const string& key) const { + Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD); + if (!result.IsNull() && result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } +} + +const FieldDescriptor* +FileDescriptor::FindExtensionByLowercaseName(const string& key) const { + const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key); + if (result == NULL || !result->is_extension()) { + return NULL; + } else { + return result; + } +} + +const FieldDescriptor* +FileDescriptor::FindExtensionByCamelcaseName(const string& key) const { + const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key); + if (result == NULL || !result->is_extension()) { + return NULL; + } else { + return result; + } +} + +bool Descriptor::IsExtensionNumber(int number) const { + // Linear search should be fine because we don't expect a message to have + // more than a couple extension ranges. + for (int i = 0; i < extension_range_count(); i++) { + if (number >= extension_range(i)->start && + number < extension_range(i)->end) { + return true; + } + } + return false; +} + +// ------------------------------------------------------------------- + +bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { + if (fallback_database_ == NULL) return false; + + if (tables_->known_bad_files_.count(name) > 0) return false; + + FileDescriptorProto file_proto; + if (!fallback_database_->FindFileByName(name, &file_proto) || + BuildFileFromDatabase(file_proto) == NULL) { + tables_->known_bad_files_.insert(name); + return false; + } + + return true; +} + +bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const { + string prefix = name; + for (;;) { + string::size_type dot_pos = prefix.find_last_of('.'); + if (dot_pos == string::npos) { + break; + } + prefix = prefix.substr(0, dot_pos); + Symbol symbol = tables_->FindSymbol(prefix); + // If the symbol type is anything other than PACKAGE, then its complete + // definition is already known. + if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) { + return true; + } + } + if (underlay_ != NULL) { + // Check to see if any prefix of this symbol exists in the underlay. + return underlay_->IsSubSymbolOfBuiltType(name); + } + return false; +} + +bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { + if (fallback_database_ == NULL) return false; + + // We skip looking in the fallback database if the name is a sub-symbol of + // any descriptor that already exists in the descriptor pool (except for + // package descriptors). This is valid because all symbols except for + // packages are defined in a single file, so if the symbol exists then we + // should already have its definition. + // + // The other reason to do this is to support "overriding" type definitions + // by merging two databases that define the same type. (Yes, people do + // this.) The main difficulty with making this work is that + // FindFileContainingSymbol() is allowed to return both false positives + // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false + // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). When two + // such databases are merged, looking up a non-existent sub-symbol of a type + // that already exists in the descriptor pool can result in an attempt to + // load multiple definitions of the same type. The check below avoids this. + if (IsSubSymbolOfBuiltType(name)) return false; + + FileDescriptorProto file_proto; + if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) { + return false; + } + + if (tables_->FindFile(file_proto.name()) != NULL) { + // We've already loaded this file, and it apparently doesn't contain the + // symbol we're looking for. Some DescriptorDatabases return false + // positives. + return false; + } + + if (BuildFileFromDatabase(file_proto) == NULL) { + return false; + } + + return true; +} + +bool DescriptorPool::TryFindExtensionInFallbackDatabase( + const Descriptor* containing_type, int field_number) const { + if (fallback_database_ == NULL) return false; + + FileDescriptorProto file_proto; + if (!fallback_database_->FindFileContainingExtension( + containing_type->full_name(), field_number, &file_proto)) { + return false; + } + + if (tables_->FindFile(file_proto.name()) != NULL) { + // We've already loaded this file, and it apparently doesn't contain the + // extension we're looking for. Some DescriptorDatabases return false + // positives. + return false; + } + + if (BuildFileFromDatabase(file_proto) == NULL) { + return false; + } + + return true; +} + +// =================================================================== + +string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const { + GOOGLE_CHECK(has_default_value()) << "No default value"; + switch (cpp_type()) { + case CPPTYPE_INT32: + return SimpleItoa(default_value_int32()); + break; + case CPPTYPE_INT64: + return SimpleItoa(default_value_int64()); + break; + case CPPTYPE_UINT32: + return SimpleItoa(default_value_uint32()); + break; + case CPPTYPE_UINT64: + return SimpleItoa(default_value_uint64()); + break; + case CPPTYPE_FLOAT: + return SimpleFtoa(default_value_float()); + break; + case CPPTYPE_DOUBLE: + return SimpleDtoa(default_value_double()); + break; + case CPPTYPE_BOOL: + return default_value_bool() ? "true" : "false"; + break; + case CPPTYPE_STRING: + if (quote_string_type) { + return "\"" + CEscape(default_value_string()) + "\""; + } else { + if (type() == TYPE_BYTES) { + return CEscape(default_value_string()); + } else { + return default_value_string(); + } + } + break; + case CPPTYPE_ENUM: + return default_value_enum()->name(); + break; + case CPPTYPE_MESSAGE: + GOOGLE_LOG(DFATAL) << "Messages can't have default values!"; + break; + } + GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string"; + return ""; +} + +// CopyTo methods ==================================================== + +void FileDescriptor::CopyTo(FileDescriptorProto* proto) const { + proto->set_name(name()); + if (!package().empty()) proto->set_package(package()); + + for (int i = 0; i < dependency_count(); i++) { + proto->add_dependency(dependency(i)->name()); + } + + for (int i = 0; i < public_dependency_count(); i++) { + proto->add_public_dependency(public_dependencies_[i]); + } + + for (int i = 0; i < weak_dependency_count(); i++) { + proto->add_weak_dependency(weak_dependencies_[i]); + } + + for (int i = 0; i < message_type_count(); i++) { + message_type(i)->CopyTo(proto->add_message_type()); + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->CopyTo(proto->add_enum_type()); + } + for (int i = 0; i < service_count(); i++) { + service(i)->CopyTo(proto->add_service()); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyTo(proto->add_extension()); + } + + if (&options() != &FileOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const { + if (source_code_info_ != &SourceCodeInfo::default_instance()) { + proto->mutable_source_code_info()->CopyFrom(*source_code_info_); + } +} + +void Descriptor::CopyTo(DescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < field_count(); i++) { + field(i)->CopyTo(proto->add_field()); + } + for (int i = 0; i < nested_type_count(); i++) { + nested_type(i)->CopyTo(proto->add_nested_type()); + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->CopyTo(proto->add_enum_type()); + } + for (int i = 0; i < extension_range_count(); i++) { + DescriptorProto::ExtensionRange* range = proto->add_extension_range(); + range->set_start(extension_range(i)->start); + range->set_end(extension_range(i)->end); + } + for (int i = 0; i < extension_count(); i++) { + extension(i)->CopyTo(proto->add_extension()); + } + + if (&options() != &MessageOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { + proto->set_name(name()); + proto->set_number(number()); + + // Some compilers do not allow static_cast directly between two enum types, + // so we must cast to int first. + proto->set_label(static_cast( + implicit_cast(label()))); + proto->set_type(static_cast( + implicit_cast(type()))); + + if (is_extension()) { + if (!containing_type()->is_unqualified_placeholder_) { + proto->set_extendee("."); + } + proto->mutable_extendee()->append(containing_type()->full_name()); + } + + if (cpp_type() == CPPTYPE_MESSAGE) { + if (message_type()->is_placeholder_) { + // We don't actually know if the type is a message type. It could be + // an enum. + proto->clear_type(); + } + + if (!message_type()->is_unqualified_placeholder_) { + proto->set_type_name("."); + } + proto->mutable_type_name()->append(message_type()->full_name()); + } else if (cpp_type() == CPPTYPE_ENUM) { + if (!enum_type()->is_unqualified_placeholder_) { + proto->set_type_name("."); + } + proto->mutable_type_name()->append(enum_type()->full_name()); + } + + if (has_default_value()) { + proto->set_default_value(DefaultValueAsString(false)); + } + + if (&options() != &FieldOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < value_count(); i++) { + value(i)->CopyTo(proto->add_value()); + } + + if (&options() != &EnumOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const { + proto->set_name(name()); + proto->set_number(number()); + + if (&options() != &EnumValueOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const { + proto->set_name(name()); + + for (int i = 0; i < method_count(); i++) { + method(i)->CopyTo(proto->add_method()); + } + + if (&options() != &ServiceOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const { + proto->set_name(name()); + + if (!input_type()->is_unqualified_placeholder_) { + proto->set_input_type("."); + } + proto->mutable_input_type()->append(input_type()->full_name()); + + if (!output_type()->is_unqualified_placeholder_) { + proto->set_output_type("."); + } + proto->mutable_output_type()->append(output_type()->full_name()); + + if (&options() != &MethodOptions::default_instance()) { + proto->mutable_options()->CopyFrom(options()); + } +} + +// DebugString methods =============================================== + +namespace { + +// Used by each of the option formatters. +bool RetrieveOptions(int depth, + const Message &options, + vector *option_entries) { + option_entries->clear(); + const Reflection* reflection = options.GetReflection(); + vector fields; + reflection->ListFields(options, &fields); + for (int i = 0; i < fields.size(); i++) { + int count = 1; + bool repeated = false; + if (fields[i]->is_repeated()) { + count = reflection->FieldSize(options, fields[i]); + repeated = true; + } + for (int j = 0; j < count; j++) { + string fieldval; + if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + string tmp; + TextFormat::Printer printer; + printer.SetInitialIndentLevel(depth + 1); + printer.PrintFieldValueToString(options, fields[i], + repeated ? j : -1, &tmp); + fieldval.append("{\n"); + fieldval.append(tmp); + fieldval.append(depth * 2, ' '); + fieldval.append("}"); + } else { + TextFormat::PrintFieldValueToString(options, fields[i], + repeated ? j : -1, &fieldval); + } + string name; + if (fields[i]->is_extension()) { + name = "(." + fields[i]->full_name() + ")"; + } else { + name = fields[i]->name(); + } + option_entries->push_back(name + " = " + fieldval); + } + } + return !option_entries->empty(); +} + +// Formats options that all appear together in brackets. Does not include +// brackets. +bool FormatBracketedOptions(int depth, const Message &options, string *output) { + vector all_options; + if (RetrieveOptions(depth, options, &all_options)) { + output->append(JoinStrings(all_options, ", ")); + } + return !all_options.empty(); +} + +// Formats options one per line +bool FormatLineOptions(int depth, const Message &options, string *output) { + string prefix(depth * 2, ' '); + vector all_options; + if (RetrieveOptions(depth, options, &all_options)) { + for (int i = 0; i < all_options.size(); i++) { + strings::SubstituteAndAppend(output, "$0option $1;\n", + prefix, all_options[i]); + } + } + return !all_options.empty(); +} + +} // anonymous namespace + +string FileDescriptor::DebugString() const { + string contents = "syntax = \"proto2\";\n\n"; + + set public_dependencies; + set weak_dependencies; + public_dependencies.insert(public_dependencies_, + public_dependencies_ + public_dependency_count_); + weak_dependencies.insert(weak_dependencies_, + weak_dependencies_ + weak_dependency_count_); + + for (int i = 0; i < dependency_count(); i++) { + if (public_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import public \"$0\";\n", + dependency(i)->name()); + } else if (weak_dependencies.count(i) > 0) { + strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n", + dependency(i)->name()); + } else { + strings::SubstituteAndAppend(&contents, "import \"$0\";\n", + dependency(i)->name()); + } + } + + if (!package().empty()) { + strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); + } + + if (FormatLineOptions(0, options(), &contents)) { + contents.append("\n"); // add some space if we had options + } + + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->DebugString(0, &contents); + contents.append("\n"); + } + + // Find all the 'group' type extensions; we will not output their nested + // definitions (those will be done with their group field descriptor). + set groups; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(extension(i)->message_type()); + } + } + + for (int i = 0; i < message_type_count(); i++) { + if (groups.count(message_type(i)) == 0) { + strings::SubstituteAndAppend(&contents, "message $0", + message_type(i)->name()); + message_type(i)->DebugString(0, &contents); + contents.append("\n"); + } + } + + for (int i = 0; i < service_count(); i++) { + service(i)->DebugString(&contents); + contents.append("\n"); + } + + const Descriptor* containing_type = NULL; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->containing_type() != containing_type) { + if (i > 0) contents.append("}\n\n"); + containing_type = extension(i)->containing_type(); + strings::SubstituteAndAppend(&contents, "extend .$0 {\n", + containing_type->full_name()); + } + extension(i)->DebugString(1, &contents); + } + if (extension_count() > 0) contents.append("}\n\n"); + + return contents; +} + +string Descriptor::DebugString() const { + string contents; + strings::SubstituteAndAppend(&contents, "message $0", name()); + DebugString(0, &contents); + return contents; +} + +void Descriptor::DebugString(int depth, string *contents) const { + string prefix(depth * 2, ' '); + ++depth; + contents->append(" {\n"); + + FormatLineOptions(depth, options(), contents); + + // Find all the 'group' types for fields and extensions; we will not output + // their nested definitions (those will be done with their group field + // descriptor). + set groups; + for (int i = 0; i < field_count(); i++) { + if (field(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(field(i)->message_type()); + } + } + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(extension(i)->message_type()); + } + } + + for (int i = 0; i < nested_type_count(); i++) { + if (groups.count(nested_type(i)) == 0) { + strings::SubstituteAndAppend(contents, "$0 message $1", + prefix, nested_type(i)->name()); + nested_type(i)->DebugString(depth, contents); + } + } + for (int i = 0; i < enum_type_count(); i++) { + enum_type(i)->DebugString(depth, contents); + } + for (int i = 0; i < field_count(); i++) { + field(i)->DebugString(depth, contents); + } + + for (int i = 0; i < extension_range_count(); i++) { + strings::SubstituteAndAppend(contents, "$0 extensions $1 to $2;\n", + prefix, + extension_range(i)->start, + extension_range(i)->end - 1); + } + + // Group extensions by what they extend, so they can be printed out together. + const Descriptor* containing_type = NULL; + for (int i = 0; i < extension_count(); i++) { + if (extension(i)->containing_type() != containing_type) { + if (i > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); + containing_type = extension(i)->containing_type(); + strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", + prefix, containing_type->full_name()); + } + extension(i)->DebugString(depth + 1, contents); + } + if (extension_count() > 0) + strings::SubstituteAndAppend(contents, "$0 }\n", prefix); + + strings::SubstituteAndAppend(contents, "$0}\n", prefix); +} + +string FieldDescriptor::DebugString() const { + string contents; + int depth = 0; + if (is_extension()) { + strings::SubstituteAndAppend(&contents, "extend .$0 {\n", + containing_type()->full_name()); + depth = 1; + } + DebugString(depth, &contents); + if (is_extension()) { + contents.append("}\n"); + } + return contents; +} + +void FieldDescriptor::DebugString(int depth, string *contents) const { + string prefix(depth * 2, ' '); + string field_type; + switch (type()) { + case TYPE_MESSAGE: + field_type = "." + message_type()->full_name(); + break; + case TYPE_ENUM: + field_type = "." + enum_type()->full_name(); + break; + default: + field_type = kTypeToName[type()]; + } + + strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4", + prefix, + kLabelToName[label()], + field_type, + type() == TYPE_GROUP ? message_type()->name() : + name(), + number()); + + bool bracketed = false; + if (has_default_value()) { + bracketed = true; + strings::SubstituteAndAppend(contents, " [default = $0", + DefaultValueAsString(true)); + } + + string formatted_options; + if (FormatBracketedOptions(depth, options(), &formatted_options)) { + contents->append(bracketed ? ", " : " ["); + bracketed = true; + contents->append(formatted_options); + } + + if (bracketed) { + contents->append("]"); + } + + if (type() == TYPE_GROUP) { + message_type()->DebugString(depth, contents); + } else { + contents->append(";\n"); + } +} + +string EnumDescriptor::DebugString() const { + string contents; + DebugString(0, &contents); + return contents; +} + +void EnumDescriptor::DebugString(int depth, string *contents) const { + string prefix(depth * 2, ' '); + ++depth; + strings::SubstituteAndAppend(contents, "$0enum $1 {\n", + prefix, name()); + + FormatLineOptions(depth, options(), contents); + + for (int i = 0; i < value_count(); i++) { + value(i)->DebugString(depth, contents); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); +} + +string EnumValueDescriptor::DebugString() const { + string contents; + DebugString(0, &contents); + return contents; +} + +void EnumValueDescriptor::DebugString(int depth, string *contents) const { + string prefix(depth * 2, ' '); + strings::SubstituteAndAppend(contents, "$0$1 = $2", + prefix, name(), number()); + + string formatted_options; + if (FormatBracketedOptions(depth, options(), &formatted_options)) { + strings::SubstituteAndAppend(contents, " [$0]", formatted_options); + } + contents->append(";\n"); +} + +string ServiceDescriptor::DebugString() const { + string contents; + DebugString(&contents); + return contents; +} + +void ServiceDescriptor::DebugString(string *contents) const { + strings::SubstituteAndAppend(contents, "service $0 {\n", name()); + + FormatLineOptions(1, options(), contents); + + for (int i = 0; i < method_count(); i++) { + method(i)->DebugString(1, contents); + } + + contents->append("}\n"); +} + +string MethodDescriptor::DebugString() const { + string contents; + DebugString(0, &contents); + return contents; +} + +void MethodDescriptor::DebugString(int depth, string *contents) const { + string prefix(depth * 2, ' '); + ++depth; + strings::SubstituteAndAppend(contents, "$0rpc $1(.$2) returns (.$3)", + prefix, name(), + input_type()->full_name(), + output_type()->full_name()); + + string formatted_options; + if (FormatLineOptions(depth, options(), &formatted_options)) { + strings::SubstituteAndAppend(contents, " {\n$0$1}\n", + formatted_options, prefix); + } else { + contents->append(";\n"); + } +} + + +// Location methods =============================================== + +static bool PathsEqual(const vector& x, const RepeatedField& y) { + if (x.size() != y.size()) return false; + for (int i = 0; i < x.size(); ++i) { + if (x[i] != y.Get(i)) return false; + } + return true; +} + +bool FileDescriptor::GetSourceLocation(const vector& path, + SourceLocation* out_location) const { + GOOGLE_CHECK_NOTNULL(out_location); + const SourceCodeInfo* info = source_code_info_; + for (int i = 0; info && i < info->location_size(); ++i) { + if (PathsEqual(path, info->location(i).path())) { + const RepeatedField& span = info->location(i).span(); + if (span.size() == 3 || span.size() == 4) { + out_location->start_line = span.Get(0); + out_location->start_column = span.Get(1); + out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); + out_location->end_column = span.Get(span.size() - 1); + + out_location->leading_comments = info->location(i).leading_comments(); + out_location->trailing_comments = info->location(i).trailing_comments(); + return true; + } + } + } + return false; +} + +bool FieldDescriptor::is_packed() const { + return is_packable() && (options_ != NULL) && options_->packed(); +} + +bool Descriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return service()->file()->GetSourceLocation(path, out_location); +} + +bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return file()->GetSourceLocation(path, out_location); +} + +bool EnumValueDescriptor::GetSourceLocation( + SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return type()->file()->GetSourceLocation(path, out_location); +} + +void Descriptor::GetLocationPath(vector* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kNestedTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kMessageTypeFieldNumber); + output->push_back(index()); + } +} + +void FieldDescriptor::GetLocationPath(vector* output) const { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kFieldFieldNumber); + output->push_back(index()); +} + +void EnumDescriptor::GetLocationPath(vector* output) const { + if (containing_type()) { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } else { + output->push_back(FileDescriptorProto::kEnumTypeFieldNumber); + output->push_back(index()); + } +} + +void EnumValueDescriptor::GetLocationPath(vector* output) const { + type()->GetLocationPath(output); + output->push_back(EnumDescriptorProto::kValueFieldNumber); + output->push_back(index()); +} + +void ServiceDescriptor::GetLocationPath(vector* output) const { + output->push_back(FileDescriptorProto::kServiceFieldNumber); + output->push_back(index()); +} + +void MethodDescriptor::GetLocationPath(vector* output) const { + service()->GetLocationPath(output); + output->push_back(ServiceDescriptorProto::kMethodFieldNumber); + output->push_back(index()); +} + +// =================================================================== + +namespace { + +// Represents an options message to interpret. Extension names in the option +// name are respolved relative to name_scope. element_name and orig_opt are +// used only for error reporting (since the parser records locations against +// pointers in the original options, not the mutable copy). The Message must be +// one of the Options messages in descriptor.proto. +struct OptionsToInterpret { + OptionsToInterpret(const string& ns, + const string& el, + const Message* orig_opt, + Message* opt) + : name_scope(ns), + element_name(el), + original_options(orig_opt), + options(opt) { + } + string name_scope; + string element_name; + const Message* original_options; + Message* options; +}; + +} // namespace + +class DescriptorBuilder { + public: + DescriptorBuilder(const DescriptorPool* pool, + DescriptorPool::Tables* tables, + DescriptorPool::ErrorCollector* error_collector); + ~DescriptorBuilder(); + + const FileDescriptor* BuildFile(const FileDescriptorProto& proto); + + private: + friend class OptionInterpreter; + + const DescriptorPool* pool_; + DescriptorPool::Tables* tables_; // for convenience + DescriptorPool::ErrorCollector* error_collector_; + + // As we build descriptors we store copies of the options messages in + // them. We put pointers to those copies in this vector, as we build, so we + // can later (after cross-linking) interpret those options. + vector options_to_interpret_; + + bool had_errors_; + string filename_; + FileDescriptor* file_; + FileDescriptorTables* file_tables_; + set dependencies_; + + // If LookupSymbol() finds a symbol that is in a file which is not a declared + // dependency of this file, it will fail, but will set + // possible_undeclared_dependency_ to point at that file. This is only used + // by AddNotDefinedError() to report a more useful error message. + // possible_undeclared_dependency_name_ is the name of the symbol that was + // actually found in possible_undeclared_dependency_, which may be a parent + // of the symbol actually looked for. + const FileDescriptor* possible_undeclared_dependency_; + string possible_undeclared_dependency_name_; + + void AddError(const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error); + + // Adds an error indicating that undefined_symbol was not defined. Must + // only be called after LookupSymbol() fails. + void AddNotDefinedError( + const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& undefined_symbol); + + // Silly helper which determines if the given file is in the given package. + // I.e., either file->package() == package_name or file->package() is a + // nested package within package_name. + bool IsInPackage(const FileDescriptor* file, const string& package_name); + + // Helper function which finds all public dependencies of the given file, and + // stores the them in the dependencies_ set in the builder. + void RecordPublicDependencies(const FileDescriptor* file); + + // Like tables_->FindSymbol(), but additionally: + // - Search the pool's underlay if not found in tables_. + // - Insure that the resulting Symbol is from one of the file's declared + // dependencies. + Symbol FindSymbol(const string& name); + + // Like FindSymbol() but does not require that the symbol is in one of the + // file's declared dependencies. + Symbol FindSymbolNotEnforcingDeps(const string& name); + + // This implements the body of FindSymbolNotEnforcingDeps(). + Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool, + const string& name); + + // Like FindSymbol(), but looks up the name relative to some other symbol + // name. This first searches siblings of relative_to, then siblings of its + // parents, etc. For example, LookupSymbol("foo.bar", "baz.qux.corge") makes + // the following calls, returning the first non-null result: + // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"), + // FindSymbol("foo.bar"). If AllowUnknownDependencies() has been called + // on the DescriptorPool, this will generate a placeholder type if + // the name is not found (unless the name itself is malformed). The + // placeholder_type parameter indicates what kind of placeholder should be + // constructed in this case. The resolve_mode parameter determines whether + // any symbol is returned, or only symbols that are types. Note, however, + // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode, + // if it believes that's all it could refer to. The caller should always + // check that it receives the type of symbol it was expecting. + enum PlaceholderType { + PLACEHOLDER_MESSAGE, + PLACEHOLDER_ENUM, + PLACEHOLDER_EXTENDABLE_MESSAGE + }; + enum ResolveMode { + LOOKUP_ALL, LOOKUP_TYPES + }; + Symbol LookupSymbol(const string& name, const string& relative_to, + PlaceholderType placeholder_type = PLACEHOLDER_MESSAGE, + ResolveMode resolve_mode = LOOKUP_ALL); + + // Like LookupSymbol() but will not return a placeholder even if + // AllowUnknownDependencies() has been used. + Symbol LookupSymbolNoPlaceholder(const string& name, + const string& relative_to, + ResolveMode resolve_mode = LOOKUP_ALL); + + // Creates a placeholder type suitable for return from LookupSymbol(). May + // return kNullSymbol if the name is not a valid type name. + Symbol NewPlaceholder(const string& name, PlaceholderType placeholder_type); + + // Creates a placeholder file. Never returns NULL. This is used when an + // import is not found and AllowUnknownDependencies() is enabled. + const FileDescriptor* NewPlaceholderFile(const string& name); + + // Calls tables_->AddSymbol() and records an error if it fails. Returns + // true if successful or false if failed, though most callers can ignore + // the return value since an error has already been recorded. + bool AddSymbol(const string& full_name, + const void* parent, const string& name, + const Message& proto, Symbol symbol); + + // Like AddSymbol(), but succeeds if the symbol is already defined as long + // as the existing definition is also a package (because it's OK to define + // the same package in two different files). Also adds all parents of the + // packgae to the symbol table (e.g. AddPackage("foo.bar", ...) will add + // "foo.bar" and "foo" to the table). + void AddPackage(const string& name, const Message& proto, + const FileDescriptor* file); + + // Checks that the symbol name contains only alphanumeric characters and + // underscores. Records an error otherwise. + void ValidateSymbolName(const string& name, const string& full_name, + const Message& proto); + + // Like ValidateSymbolName(), but the name is allowed to contain periods and + // an error is indicated by returning false (not recording the error). + bool ValidateQualifiedName(const string& name); + + // Used by BUILD_ARRAY macro (below) to avoid having to have the type + // specified as a macro parameter. + template + inline void AllocateArray(int size, Type** output) { + *output = tables_->AllocateArray(size); + } + + // Allocates a copy of orig_options in tables_ and stores it in the + // descriptor. Remembers its uninterpreted options, to be interpreted + // later. DescriptorT must be one of the Descriptor messages from + // descriptor.proto. + template void AllocateOptions( + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor); + // Specialization for FileOptions. + void AllocateOptions(const FileOptions& orig_options, + FileDescriptor* descriptor); + + // Implementation for AllocateOptions(). Don't call this directly. + template void AllocateOptionsImpl( + const string& name_scope, + const string& element_name, + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor); + + // These methods all have the same signature for the sake of the BUILD_ARRAY + // macro, below. + void BuildMessage(const DescriptorProto& proto, + const Descriptor* parent, + Descriptor* result); + void BuildFieldOrExtension(const FieldDescriptorProto& proto, + const Descriptor* parent, + FieldDescriptor* result, + bool is_extension); + void BuildField(const FieldDescriptorProto& proto, + const Descriptor* parent, + FieldDescriptor* result) { + BuildFieldOrExtension(proto, parent, result, false); + } + void BuildExtension(const FieldDescriptorProto& proto, + const Descriptor* parent, + FieldDescriptor* result) { + BuildFieldOrExtension(proto, parent, result, true); + } + void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto, + const Descriptor* parent, + Descriptor::ExtensionRange* result); + void BuildEnum(const EnumDescriptorProto& proto, + const Descriptor* parent, + EnumDescriptor* result); + void BuildEnumValue(const EnumValueDescriptorProto& proto, + const EnumDescriptor* parent, + EnumValueDescriptor* result); + void BuildService(const ServiceDescriptorProto& proto, + const void* dummy, + ServiceDescriptor* result); + void BuildMethod(const MethodDescriptorProto& proto, + const ServiceDescriptor* parent, + MethodDescriptor* result); + + // Must be run only after building. + // + // NOTE: Options will not be available during cross-linking, as they + // have not yet been interpreted. Defer any handling of options to the + // Validate*Options methods. + void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto); + void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto); + void CrossLinkField(FieldDescriptor* field, + const FieldDescriptorProto& proto); + void CrossLinkEnum(EnumDescriptor* enum_type, + const EnumDescriptorProto& proto); + void CrossLinkEnumValue(EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& proto); + void CrossLinkService(ServiceDescriptor* service, + const ServiceDescriptorProto& proto); + void CrossLinkMethod(MethodDescriptor* method, + const MethodDescriptorProto& proto); + + // Must be run only after cross-linking. + void InterpretOptions(); + + // A helper class for interpreting options. + class OptionInterpreter { + public: + // Creates an interpreter that operates in the context of the pool of the + // specified builder, which must not be NULL. We don't take ownership of the + // builder. + explicit OptionInterpreter(DescriptorBuilder* builder); + + ~OptionInterpreter(); + + // Interprets the uninterpreted options in the specified Options message. + // On error, calls AddError() on the underlying builder and returns false. + // Otherwise returns true. + bool InterpretOptions(OptionsToInterpret* options_to_interpret); + + class AggregateOptionFinder; + + private: + // Interprets uninterpreted_option_ on the specified message, which + // must be the mutable copy of the original options message to which + // uninterpreted_option_ belongs. + bool InterpretSingleOption(Message* options); + + // Adds the uninterpreted_option to the given options message verbatim. + // Used when AllowUnknownDependencies() is in effect and we can't find + // the option's definition. + void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option, + Message* options); + + // A recursive helper function that drills into the intermediate fields + // in unknown_fields to check if field innermost_field is set on the + // innermost message. Returns false and sets an error if so. + bool ExamineIfOptionIsSet( + vector::const_iterator intermediate_fields_iter, + vector::const_iterator intermediate_fields_end, + const FieldDescriptor* innermost_field, const string& debug_msg_name, + const UnknownFieldSet& unknown_fields); + + // Validates the value for the option field of the currently interpreted + // option and then sets it on the unknown_field. + bool SetOptionValue(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + + // Parses an aggregate value for a CPPTYPE_MESSAGE option and + // saves it into *unknown_fields. + bool SetAggregateOption(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + + // Convenience functions to set an int field the right way, depending on + // its wire type (a single int CppType can represent multiple wire types). + void SetInt32(int number, int32 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetInt64(int number, int64 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetUInt32(int number, uint32 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + void SetUInt64(int number, uint64 value, FieldDescriptor::Type type, + UnknownFieldSet* unknown_fields); + + // A helper function that adds an error at the specified location of the + // option we're currently interpreting, and returns false. + bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location, + const string& msg) { + builder_->AddError(options_to_interpret_->element_name, + *uninterpreted_option_, location, msg); + return false; + } + + // A helper function that adds an error at the location of the option name + // and returns false. + bool AddNameError(const string& msg) { + return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg); + } + + // A helper function that adds an error at the location of the option name + // and returns false. + bool AddValueError(const string& msg) { + return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg); + } + + // We interpret against this builder's pool. Is never NULL. We don't own + // this pointer. + DescriptorBuilder* builder_; + + // The options we're currently interpreting, or NULL if we're not in a call + // to InterpretOptions. + const OptionsToInterpret* options_to_interpret_; + + // The option we're currently interpreting within options_to_interpret_, or + // NULL if we're not in a call to InterpretOptions(). This points to a + // submessage of the original option, not the mutable copy. Therefore we + // can use it to find locations recorded by the parser. + const UninterpretedOption* uninterpreted_option_; + + // Factory used to create the dynamic messages we need to parse + // any aggregate option values we encounter. + DynamicMessageFactory dynamic_factory_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter); + }; + + // Work-around for broken compilers: According to the C++ standard, + // OptionInterpreter should have access to the private members of any class + // which has declared DescriptorBuilder as a friend. Unfortunately some old + // versions of GCC and other compilers do not implement this correctly. So, + // we have to have these intermediate methods to provide access. We also + // redundantly declare OptionInterpreter a friend just to make things extra + // clear for these bad compilers. + friend class OptionInterpreter; + friend class OptionInterpreter::AggregateOptionFinder; + + static inline bool get_allow_unknown(const DescriptorPool* pool) { + return pool->allow_unknown_; + } + static inline bool get_is_placeholder(const Descriptor* descriptor) { + return descriptor->is_placeholder_; + } + static inline void assert_mutex_held(const DescriptorPool* pool) { + if (pool->mutex_ != NULL) { + pool->mutex_->AssertHeld(); + } + } + + // Must be run only after options have been interpreted. + // + // NOTE: Validation code must only reference the options in the mutable + // descriptors, which are the ones that have been interpreted. The const + // proto references are passed in only so they can be provided to calls to + // AddError(). Do not look at their options, which have not been interpreted. + void ValidateFileOptions(FileDescriptor* file, + const FileDescriptorProto& proto); + void ValidateMessageOptions(Descriptor* message, + const DescriptorProto& proto); + void ValidateFieldOptions(FieldDescriptor* field, + const FieldDescriptorProto& proto); + void ValidateEnumOptions(EnumDescriptor* enm, + const EnumDescriptorProto& proto); + void ValidateEnumValueOptions(EnumValueDescriptor* enum_value, + const EnumValueDescriptorProto& proto); + void ValidateServiceOptions(ServiceDescriptor* service, + const ServiceDescriptorProto& proto); + void ValidateMethodOptions(MethodDescriptor* method, + const MethodDescriptorProto& proto); + + void ValidateMapKey(FieldDescriptor* field, + const FieldDescriptorProto& proto); + +}; + +const FileDescriptor* DescriptorPool::BuildFile( + const FileDescriptorProto& proto) { + GOOGLE_CHECK(fallback_database_ == NULL) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto); +} + +const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( + const FileDescriptorProto& proto, + ErrorCollector* error_collector) { + GOOGLE_CHECK(fallback_database_ == NULL) + << "Cannot call BuildFile on a DescriptorPool that uses a " + "DescriptorDatabase. You must instead find a way to get your file " + "into the underlying database."; + GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + return DescriptorBuilder(this, tables_.get(), + error_collector).BuildFile(proto); +} + +const FileDescriptor* DescriptorPool::BuildFileFromDatabase( + const FileDescriptorProto& proto) const { + mutex_->AssertHeld(); + return DescriptorBuilder(this, tables_.get(), + default_error_collector_).BuildFile(proto); +} + +DescriptorBuilder::DescriptorBuilder( + const DescriptorPool* pool, + DescriptorPool::Tables* tables, + DescriptorPool::ErrorCollector* error_collector) + : pool_(pool), + tables_(tables), + error_collector_(error_collector), + had_errors_(false), + possible_undeclared_dependency_(NULL) {} + +DescriptorBuilder::~DescriptorBuilder() {} + +void DescriptorBuilder::AddError( + const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error) { + if (error_collector_ == NULL) { + if (!had_errors_) { + GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_ + << "\":"; + } + GOOGLE_LOG(ERROR) << " " << element_name << ": " << error; + } else { + error_collector_->AddError(filename_, element_name, + &descriptor, location, error); + } + had_errors_ = true; +} + +void DescriptorBuilder::AddNotDefinedError( + const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& undefined_symbol) { + if (possible_undeclared_dependency_ == NULL) { + AddError(element_name, descriptor, location, + "\"" + undefined_symbol + "\" is not defined."); + } else { + AddError(element_name, descriptor, location, + "\"" + possible_undeclared_dependency_name_ + + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + "\", which is not " + "imported by \"" + filename_ + "\". To use it here, please " + "add the necessary import."); + } +} + +bool DescriptorBuilder::IsInPackage(const FileDescriptor* file, + const string& package_name) { + return HasPrefixString(file->package(), package_name) && + (file->package().size() == package_name.size() || + file->package()[package_name.size()] == '.'); +} + +void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) { + if (file == NULL || !dependencies_.insert(file).second) return; + for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) { + RecordPublicDependencies(file->public_dependency(i)); + } +} + +Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper( + const DescriptorPool* pool, const string& name) { + // If we are looking at an underlay, we must lock its mutex_, since we are + // accessing the underlay's tables_ directly. + MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_); + + Symbol result = pool->tables_->FindSymbol(name); + if (result.IsNull() && pool->underlay_ != NULL) { + // Symbol not found; check the underlay. + result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name); + } + + if (result.IsNull()) { + // In theory, we shouldn't need to check fallback_database_ because the + // symbol should be in one of its file's direct dependencies, and we have + // already loaded those by the time we get here. But we check anyway so + // that we can generate better error message when dependencies are missing + // (i.e., "missing dependency" rather than "type is not defined"). + if (pool->TryFindSymbolInFallbackDatabase(name)) { + result = pool->tables_->FindSymbol(name); + } + } + + return result; +} + +Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const string& name) { + return FindSymbolNotEnforcingDepsHelper(pool_, name); +} + +Symbol DescriptorBuilder::FindSymbol(const string& name) { + Symbol result = FindSymbolNotEnforcingDeps(name); + + if (result.IsNull()) return result; + + if (!pool_->enforce_dependencies_) { + // Hack for CompilerUpgrader. + return result; + } + + // Only find symbols which were defined in this file or one of its + // dependencies. + const FileDescriptor* file = result.GetFile(); + if (file == file_ || dependencies_.count(file) > 0) return result; + + if (result.type == Symbol::PACKAGE) { + // Arg, this is overcomplicated. The symbol is a package name. It could + // be that the package was defined in multiple files. result.GetFile() + // returns the first file we saw that used this package. We've determined + // that that file is not a direct dependency of the file we are currently + // building, but it could be that some other file which *is* a direct + // dependency also defines the same package. We can't really rule out this + // symbol unless none of the dependencies define it. + if (IsInPackage(file_, name)) return result; + for (set::const_iterator it = dependencies_.begin(); + it != dependencies_.end(); ++it) { + // Note: A dependency may be NULL if it was not found or had errors. + if (*it != NULL && IsInPackage(*it, name)) return result; + } + } + + possible_undeclared_dependency_ = file; + possible_undeclared_dependency_name_ = name; + return kNullSymbol; +} + +Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( + const string& name, const string& relative_to, ResolveMode resolve_mode) { + possible_undeclared_dependency_ = NULL; + + if (name.size() > 0 && name[0] == '.') { + // Fully-qualified name. + return FindSymbol(name.substr(1)); + } + + // If name is something like "Foo.Bar.baz", and symbols named "Foo" are + // defined in multiple parent scopes, we only want to find "Bar.baz" in the + // innermost one. E.g., the following should produce an error: + // message Bar { message Baz {} } + // message Foo { + // message Bar { + // } + // optional Bar.Baz baz = 1; + // } + // So, we look for just "Foo" first, then look for "Bar.baz" within it if + // found. + string::size_type name_dot_pos = name.find_first_of('.'); + string first_part_of_name; + if (name_dot_pos == string::npos) { + first_part_of_name = name; + } else { + first_part_of_name = name.substr(0, name_dot_pos); + } + + string scope_to_try(relative_to); + + while (true) { + // Chop off the last component of the scope. + string::size_type dot_pos = scope_to_try.find_last_of('.'); + if (dot_pos == string::npos) { + return FindSymbol(name); + } else { + scope_to_try.erase(dot_pos); + } + + // Append ".first_part_of_name" and try to find. + string::size_type old_size = scope_to_try.size(); + scope_to_try.append(1, '.'); + scope_to_try.append(first_part_of_name); + Symbol result = FindSymbol(scope_to_try); + if (!result.IsNull()) { + if (first_part_of_name.size() < name.size()) { + // name is a compound symbol, of which we only found the first part. + // Now try to look up the rest of it. + if (result.IsAggregate()) { + scope_to_try.append(name, first_part_of_name.size(), + name.size() - first_part_of_name.size()); + return FindSymbol(scope_to_try); + } else { + // We found a symbol but it's not an aggregate. Continue the loop. + } + } else { + if (resolve_mode == LOOKUP_TYPES && !result.IsType()) { + // We found a symbol but it's not a type. Continue the loop. + } else { + return result; + } + } + } + + // Not found. Remove the name so we can try again. + scope_to_try.erase(old_size); + } +} + +Symbol DescriptorBuilder::LookupSymbol( + const string& name, const string& relative_to, + PlaceholderType placeholder_type, ResolveMode resolve_mode) { + Symbol result = LookupSymbolNoPlaceholder( + name, relative_to, resolve_mode); + if (result.IsNull() && pool_->allow_unknown_) { + // Not found, but AllowUnknownDependencies() is enabled. Return a + // placeholder instead. + result = NewPlaceholder(name, placeholder_type); + } + return result; +} + +Symbol DescriptorBuilder::NewPlaceholder(const string& name, + PlaceholderType placeholder_type) { + // Compute names. + const string* placeholder_full_name; + const string* placeholder_name; + const string* placeholder_package; + + if (!ValidateQualifiedName(name)) return kNullSymbol; + if (name[0] == '.') { + // Fully-qualified. + placeholder_full_name = tables_->AllocateString(name.substr(1)); + } else { + placeholder_full_name = tables_->AllocateString(name); + } + + string::size_type dotpos = placeholder_full_name->find_last_of('.'); + if (dotpos != string::npos) { + placeholder_package = tables_->AllocateString( + placeholder_full_name->substr(0, dotpos)); + placeholder_name = tables_->AllocateString( + placeholder_full_name->substr(dotpos + 1)); + } else { + placeholder_package = &kEmptyString; + placeholder_name = placeholder_full_name; + } + + // Create the placeholders. + FileDescriptor* placeholder_file = tables_->Allocate(); + memset(placeholder_file, 0, sizeof(*placeholder_file)); + + placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance(); + + placeholder_file->name_ = + tables_->AllocateString(*placeholder_full_name + ".placeholder.proto"); + placeholder_file->package_ = placeholder_package; + placeholder_file->pool_ = pool_; + placeholder_file->options_ = &FileOptions::default_instance(); + placeholder_file->tables_ = &FileDescriptorTables::kEmpty; + // All other fields are zero or NULL. + + if (placeholder_type == PLACEHOLDER_ENUM) { + placeholder_file->enum_type_count_ = 1; + placeholder_file->enum_types_ = + tables_->AllocateArray(1); + + EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0]; + memset(placeholder_enum, 0, sizeof(*placeholder_enum)); + + placeholder_enum->full_name_ = placeholder_full_name; + placeholder_enum->name_ = placeholder_name; + placeholder_enum->file_ = placeholder_file; + placeholder_enum->options_ = &EnumOptions::default_instance(); + placeholder_enum->is_placeholder_ = true; + placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.'); + + // Enums must have at least one value. + placeholder_enum->value_count_ = 1; + placeholder_enum->values_ = tables_->AllocateArray(1); + + EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0]; + memset(placeholder_value, 0, sizeof(*placeholder_value)); + + placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE"); + // Note that enum value names are siblings of their type, not children. + placeholder_value->full_name_ = + placeholder_package->empty() ? placeholder_value->name_ : + tables_->AllocateString(*placeholder_package + ".PLACEHOLDER_VALUE"); + + placeholder_value->number_ = 0; + placeholder_value->type_ = placeholder_enum; + placeholder_value->options_ = &EnumValueOptions::default_instance(); + + return Symbol(placeholder_enum); + } else { + placeholder_file->message_type_count_ = 1; + placeholder_file->message_types_ = + tables_->AllocateArray(1); + + Descriptor* placeholder_message = &placeholder_file->message_types_[0]; + memset(placeholder_message, 0, sizeof(*placeholder_message)); + + placeholder_message->full_name_ = placeholder_full_name; + placeholder_message->name_ = placeholder_name; + placeholder_message->file_ = placeholder_file; + placeholder_message->options_ = &MessageOptions::default_instance(); + placeholder_message->is_placeholder_ = true; + placeholder_message->is_unqualified_placeholder_ = (name[0] != '.'); + + if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) { + placeholder_message->extension_range_count_ = 1; + placeholder_message->extension_ranges_ = + tables_->AllocateArray(1); + placeholder_message->extension_ranges_->start = 1; + // kMaxNumber + 1 because ExtensionRange::end is exclusive. + placeholder_message->extension_ranges_->end = + FieldDescriptor::kMaxNumber + 1; + } + + return Symbol(placeholder_message); + } +} + +const FileDescriptor* DescriptorBuilder::NewPlaceholderFile( + const string& name) { + FileDescriptor* placeholder = tables_->Allocate(); + memset(placeholder, 0, sizeof(*placeholder)); + + placeholder->name_ = tables_->AllocateString(name); + placeholder->package_ = &kEmptyString; + placeholder->pool_ = pool_; + placeholder->options_ = &FileOptions::default_instance(); + placeholder->tables_ = &FileDescriptorTables::kEmpty; + // All other fields are zero or NULL. + + return placeholder; +} + +bool DescriptorBuilder::AddSymbol( + const string& full_name, const void* parent, const string& name, + const Message& proto, Symbol symbol) { + // If the caller passed NULL for the parent, the symbol is at file scope. + // Use its file as the parent instead. + if (parent == NULL) parent = file_; + + if (tables_->AddSymbol(full_name, symbol)) { + if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) { + GOOGLE_LOG(DFATAL) << "\"" << full_name << "\" not previously defined in " + "symbols_by_name_, but was defined in symbols_by_parent_; " + "this shouldn't be possible."; + return false; + } + return true; + } else { + const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile(); + if (other_file == file_) { + string::size_type dot_pos = full_name.find_last_of('.'); + if (dot_pos == string::npos) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" is already defined."); + } else { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name.substr(dot_pos + 1) + + "\" is already defined in \"" + + full_name.substr(0, dot_pos) + "\"."); + } + } else { + // Symbol seems to have been defined in a different file. + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + full_name + "\" is already defined in file \"" + + other_file->name() + "\"."); + } + return false; + } +} + +void DescriptorBuilder::AddPackage( + const string& name, const Message& proto, const FileDescriptor* file) { + if (tables_->AddSymbol(name, Symbol(file))) { + // Success. Also add parent package, if any. + string::size_type dot_pos = name.find_last_of('.'); + if (dot_pos == string::npos) { + // No parents. + ValidateSymbolName(name, name, proto); + } else { + // Has parent. + string* parent_name = tables_->AllocateString(name.substr(0, dot_pos)); + AddPackage(*parent_name, proto, file); + ValidateSymbolName(name.substr(dot_pos + 1), name, proto); + } + } else { + Symbol existing_symbol = tables_->FindSymbol(name); + // It's OK to redefine a package. + if (existing_symbol.type != Symbol::PACKAGE) { + // Symbol seems to have been defined in a different file. + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + "\" is already defined (as something other than " + "a package) in file \"" + existing_symbol.GetFile()->name() + + "\"."); + } + } +} + +void DescriptorBuilder::ValidateSymbolName( + const string& name, const string& full_name, const Message& proto) { + if (name.empty()) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "Missing name."); + } else { + for (int i = 0; i < name.size(); i++) { + // I don't trust isalnum() due to locales. :( + if ((name[i] < 'a' || 'z' < name[i]) && + (name[i] < 'A' || 'Z' < name[i]) && + (name[i] < '0' || '9' < name[i]) && + (name[i] != '_')) { + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, + "\"" + name + "\" is not a valid identifier."); + } + } + } +} + +bool DescriptorBuilder::ValidateQualifiedName(const string& name) { + bool last_was_period = false; + + for (int i = 0; i < name.size(); i++) { + // I don't trust isalnum() due to locales. :( + if (('a' <= name[i] && name[i] <= 'z') || + ('A' <= name[i] && name[i] <= 'Z') || + ('0' <= name[i] && name[i] <= '9') || + (name[i] == '_')) { + last_was_period = false; + } else if (name[i] == '.') { + if (last_was_period) return false; + last_was_period = true; + } else { + return false; + } + } + + return !name.empty() && !last_was_period; +} + +// ------------------------------------------------------------------- + +// This generic implementation is good for all descriptors except +// FileDescriptor. +template void DescriptorBuilder::AllocateOptions( + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor) { + AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(), + orig_options, descriptor); +} + +// We specialize for FileDescriptor. +void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options, + FileDescriptor* descriptor) { + // We add the dummy token so that LookupSymbol does the right thing. + AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(), + orig_options, descriptor); +} + +template void DescriptorBuilder::AllocateOptionsImpl( + const string& name_scope, + const string& element_name, + const typename DescriptorT::OptionsType& orig_options, + DescriptorT* descriptor) { + // We need to use a dummy pointer to work around a bug in older versions of + // GCC. Otherwise, the following two lines could be replaced with: + // typename DescriptorT::OptionsType* options = + // tables_->AllocateMessage(); + typename DescriptorT::OptionsType* const dummy = NULL; + typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy); + // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti + // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the + // reflection based method, which requires the Descriptor. However, we are in + // the middle of building the descriptors, thus the deadlock. + options->ParseFromString(orig_options.SerializeAsString()); + descriptor->options_ = options; + + // Don't add to options_to_interpret_ unless there were uninterpreted + // options. This not only avoids unnecessary work, but prevents a + // bootstrapping problem when building descriptors for descriptor.proto. + // descriptor.proto does not contain any uninterpreted options, but + // attempting to interpret options anyway will cause + // OptionsType::GetDescriptor() to be called which may then deadlock since + // we're still trying to build it. + if (options->uninterpreted_option_size() > 0) { + options_to_interpret_.push_back( + OptionsToInterpret(name_scope, element_name, &orig_options, options)); + } +} + + +// A common pattern: We want to convert a repeated field in the descriptor +// to an array of values, calling some method to build each value. +#define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \ + OUTPUT->NAME##_count_ = INPUT.NAME##_size(); \ + AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \ + for (int i = 0; i < INPUT.NAME##_size(); i++) { \ + METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \ + } + +const FileDescriptor* DescriptorBuilder::BuildFile( + const FileDescriptorProto& proto) { + filename_ = proto.name(); + + // Check if the file already exists and is identical to the one being built. + // Note: This only works if the input is canonical -- that is, it + // fully-qualifies all type names, has no UninterpretedOptions, etc. + // This is fine, because this idempotency "feature" really only exists to + // accomodate one hack in the proto1->proto2 migration layer. + const FileDescriptor* existing_file = tables_->FindFile(filename_); + if (existing_file != NULL) { + // File already in pool. Compare the existing one to the input. + FileDescriptorProto existing_proto; + existing_file->CopyTo(&existing_proto); + if (existing_proto.SerializeAsString() == proto.SerializeAsString()) { + // They're identical. Return the existing descriptor. + return existing_file; + } + + // Not a match. The error will be detected and handled later. + } + + // Check to see if this file is already on the pending files list. + // TODO(kenton): Allow recursive imports? It may not work with some + // (most?) programming languages. E.g., in C++, a forward declaration + // of a type is not sufficient to allow it to be used even in a + // generated header file due to inlining. This could perhaps be + // worked around using tricks involving inserting #include statements + // mid-file, but that's pretty ugly, and I'm pretty sure there are + // some languages out there that do not allow recursive dependencies + // at all. + for (int i = 0; i < tables_->pending_files_.size(); i++) { + if (tables_->pending_files_[i] == proto.name()) { + string error_message("File recursively imports itself: "); + for (; i < tables_->pending_files_.size(); i++) { + error_message.append(tables_->pending_files_[i]); + error_message.append(" -> "); + } + error_message.append(proto.name()); + + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + error_message); + return NULL; + } + } + + // If we have a fallback_database_, attempt to load all dependencies now, + // before checkpointing tables_. This avoids confusion with recursive + // checkpoints. + if (pool_->fallback_database_ != NULL) { + tables_->pending_files_.push_back(proto.name()); + for (int i = 0; i < proto.dependency_size(); i++) { + if (tables_->FindFile(proto.dependency(i)) == NULL && + (pool_->underlay_ == NULL || + pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) { + // We don't care what this returns since we'll find out below anyway. + pool_->TryFindFileInFallbackDatabase(proto.dependency(i)); + } + } + tables_->pending_files_.pop_back(); + } + + // Checkpoint the tables so that we can roll back if something goes wrong. + tables_->AddCheckpoint(); + + FileDescriptor* result = tables_->Allocate(); + file_ = result; + + if (proto.has_source_code_info()) { + SourceCodeInfo *info = tables_->AllocateMessage(); + info->CopyFrom(proto.source_code_info()); + result->source_code_info_ = info; + } else { + result->source_code_info_ = &SourceCodeInfo::default_instance(); + } + + file_tables_ = tables_->AllocateFileTables(); + file_->tables_ = file_tables_; + + if (!proto.has_name()) { + AddError("", proto, DescriptorPool::ErrorCollector::OTHER, + "Missing field: FileDescriptorProto.name."); + } + + result->name_ = tables_->AllocateString(proto.name()); + if (proto.has_package()) { + result->package_ = tables_->AllocateString(proto.package()); + } else { + // We cannot rely on proto.package() returning a valid string if + // proto.has_package() is false, because we might be running at static + // initialization time, in which case default values have not yet been + // initialized. + result->package_ = tables_->AllocateString(""); + } + result->pool_ = pool_; + + // Add to tables. + if (!tables_->AddFile(result)) { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "A file with this name is already in the pool."); + // Bail out early so that if this is actually the exact same file, we + // don't end up reporting that every single symbol is already defined. + tables_->RollbackToLastCheckpoint(); + return NULL; + } + if (!result->package().empty()) { + AddPackage(result->package(), proto, result); + } + + // Make sure all dependencies are loaded. + set seen_dependencies; + result->dependency_count_ = proto.dependency_size(); + result->dependencies_ = + tables_->AllocateArray(proto.dependency_size()); + for (int i = 0; i < proto.dependency_size(); i++) { + if (!seen_dependencies.insert(proto.dependency(i)).second) { + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Import \"" + proto.dependency(i) + "\" was listed twice."); + } + + const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i)); + if (dependency == NULL && pool_->underlay_ != NULL) { + dependency = pool_->underlay_->FindFileByName(proto.dependency(i)); + } + + if (dependency == NULL) { + if (pool_->allow_unknown_) { + dependency = NewPlaceholderFile(proto.dependency(i)); + } else { + string message; + if (pool_->fallback_database_ == NULL) { + message = "Import \"" + proto.dependency(i) + + "\" has not been loaded."; + } else { + message = "Import \"" + proto.dependency(i) + + "\" was not found or had errors."; + } + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + message); + } + } + + result->dependencies_[i] = dependency; + } + + // Check public dependencies. + int public_dependency_count = 0; + result->public_dependencies_ = tables_->AllocateArray( + proto.public_dependency_size()); + for (int i = 0; i < proto.public_dependency_size(); i++) { + // Only put valid public dependency indexes. + int index = proto.public_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->public_dependencies_[public_dependency_count++] = index; + } else { + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Invalid public dependency index."); + } + } + result->public_dependency_count_ = public_dependency_count; + + // Build dependency set + dependencies_.clear(); + for (int i = 0; i < result->dependency_count(); i++) { + RecordPublicDependencies(result->dependency(i)); + } + + // Check weak dependencies. + int weak_dependency_count = 0; + result->weak_dependencies_ = tables_->AllocateArray( + proto.weak_dependency_size()); + for (int i = 0; i < proto.weak_dependency_size(); i++) { + int index = proto.weak_dependency(i); + if (index >= 0 && index < proto.dependency_size()) { + result->weak_dependencies_[weak_dependency_count++] = index; + } else { + AddError(proto.name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Invalid weak dependency index."); + } + } + result->weak_dependency_count_ = weak_dependency_count; + + // Convert children. + BUILD_ARRAY(proto, result, message_type, BuildMessage , NULL); + BUILD_ARRAY(proto, result, enum_type , BuildEnum , NULL); + BUILD_ARRAY(proto, result, service , BuildService , NULL); + BUILD_ARRAY(proto, result, extension , BuildExtension, NULL); + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + // Note that the following steps must occur in exactly the specified order. + + // Cross-link. + CrossLinkFile(result, proto); + + // Interpret any remaining uninterpreted options gathered into + // options_to_interpret_ during descriptor building. Cross-linking has made + // extension options known, so all interpretations should now succeed. + if (!had_errors_) { + OptionInterpreter option_interpreter(this); + for (vector::iterator iter = + options_to_interpret_.begin(); + iter != options_to_interpret_.end(); ++iter) { + option_interpreter.InterpretOptions(&(*iter)); + } + options_to_interpret_.clear(); + } + + // Validate options. + if (!had_errors_) { + ValidateFileOptions(result, proto); + } + + if (had_errors_) { + tables_->RollbackToLastCheckpoint(); + return NULL; + } else { + tables_->ClearLastCheckpoint(); + return result; + } +} + +void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, + const Descriptor* parent, + Descriptor* result) { + const string& scope = (parent == NULL) ? + file_->package() : parent->full_name(); + string* full_name = tables_->AllocateString(scope); + if (!full_name->empty()) full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; + result->containing_type_ = parent; + result->is_placeholder_ = false; + result->is_unqualified_placeholder_ = false; + + BUILD_ARRAY(proto, result, field , BuildField , result); + BUILD_ARRAY(proto, result, nested_type , BuildMessage , result); + BUILD_ARRAY(proto, result, enum_type , BuildEnum , result); + BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result); + BUILD_ARRAY(proto, result, extension , BuildExtension , result); + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); + + // Check that no fields have numbers in extension ranges. + for (int i = 0; i < result->field_count(); i++) { + const FieldDescriptor* field = result->field(i); + for (int j = 0; j < result->extension_range_count(); j++) { + const Descriptor::ExtensionRange* range = result->extension_range(j); + if (range->start <= field->number() && field->number() < range->end) { + AddError(field->full_name(), proto.extension_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Extension range $0 to $1 includes field \"$2\" ($3).", + range->start, range->end - 1, + field->name(), field->number())); + } + } + } + + // Check that extension ranges don't overlap. + for (int i = 0; i < result->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range1 = result->extension_range(i); + for (int j = i + 1; j < result->extension_range_count(); j++) { + const Descriptor::ExtensionRange* range2 = result->extension_range(j); + if (range1->end > range2->start && range2->end > range1->start) { + AddError(result->full_name(), proto.extension_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2->start, range2->end - 1, + range1->start, range1->end - 1)); + } + } + } +} + +void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, + const Descriptor* parent, + FieldDescriptor* result, + bool is_extension) { + const string& scope = (parent == NULL) ? + file_->package() : parent->full_name(); + string* full_name = tables_->AllocateString(scope); + if (!full_name->empty()) full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; + result->number_ = proto.number(); + result->is_extension_ = is_extension; + + // If .proto files follow the style guide then the name should already be + // lower-cased. If that's the case we can just reuse the string we already + // allocated rather than allocate a new one. + string lowercase_name(proto.name()); + LowerString(&lowercase_name); + if (lowercase_name == proto.name()) { + result->lowercase_name_ = result->name_; + } else { + result->lowercase_name_ = tables_->AllocateString(lowercase_name); + } + + // Don't bother with the above optimization for camel-case names since + // .proto files that follow the guide shouldn't be using names in this + // format, so the optimization wouldn't help much. + result->camelcase_name_ = tables_->AllocateString(ToCamelCase(proto.name())); + + // Some compilers do not allow static_cast directly between two enum types, + // so we must cast to int first. + result->type_ = static_cast( + implicit_cast(proto.type())); + result->label_ = static_cast( + implicit_cast(proto.label())); + + // Some of these may be filled in when cross-linking. + result->containing_type_ = NULL; + result->extension_scope_ = NULL; + result->experimental_map_key_ = NULL; + result->message_type_ = NULL; + result->enum_type_ = NULL; + + result->has_default_value_ = proto.has_default_value(); + if (proto.has_default_value() && result->is_repeated()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Repeated fields can't have default values."); + } + + if (proto.has_type()) { + if (proto.has_default_value()) { + char* end_pos = NULL; + switch (result->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + result->default_value_int32_ = + strtol(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_INT64: + result->default_value_int64_ = + strto64(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_UINT32: + result->default_value_uint32_ = + strtoul(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_UINT64: + result->default_value_uint64_ = + strtou64(proto.default_value().c_str(), &end_pos, 0); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + if (proto.default_value() == "inf") { + result->default_value_float_ = numeric_limits::infinity(); + } else if (proto.default_value() == "-inf") { + result->default_value_float_ = -numeric_limits::infinity(); + } else if (proto.default_value() == "nan") { + result->default_value_float_ = numeric_limits::quiet_NaN(); + } else { + result->default_value_float_ = + NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + } + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + if (proto.default_value() == "inf") { + result->default_value_double_ = numeric_limits::infinity(); + } else if (proto.default_value() == "-inf") { + result->default_value_double_ = -numeric_limits::infinity(); + } else if (proto.default_value() == "nan") { + result->default_value_double_ = numeric_limits::quiet_NaN(); + } else { + result->default_value_double_ = + NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + } + break; + case FieldDescriptor::CPPTYPE_BOOL: + if (proto.default_value() == "true") { + result->default_value_bool_ = true; + } else if (proto.default_value() == "false") { + result->default_value_bool_ = false; + } else { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Boolean default must be true or false."); + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + // This will be filled in when cross-linking. + result->default_value_enum_ = NULL; + break; + case FieldDescriptor::CPPTYPE_STRING: + if (result->type() == FieldDescriptor::TYPE_BYTES) { + result->default_value_string_ = tables_->AllocateString( + UnescapeCEscapeString(proto.default_value())); + } else { + result->default_value_string_ = + tables_->AllocateString(proto.default_value()); + } + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Messages can't have default values."); + result->has_default_value_ = false; + break; + } + + if (end_pos != NULL) { + // end_pos is only set non-NULL by the parsers for numeric types, above. + // This checks that the default was non-empty and had no extra junk + // after the end of the number. + if (proto.default_value().empty() || *end_pos != '\0') { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Couldn't parse default value."); + } + } + } else { + // No explicit default value + switch (result->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + result->default_value_int32_ = 0; + break; + case FieldDescriptor::CPPTYPE_INT64: + result->default_value_int64_ = 0; + break; + case FieldDescriptor::CPPTYPE_UINT32: + result->default_value_uint32_ = 0; + break; + case FieldDescriptor::CPPTYPE_UINT64: + result->default_value_uint64_ = 0; + break; + case FieldDescriptor::CPPTYPE_FLOAT: + result->default_value_float_ = 0.0f; + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + result->default_value_double_ = 0.0; + break; + case FieldDescriptor::CPPTYPE_BOOL: + result->default_value_bool_ = false; + break; + case FieldDescriptor::CPPTYPE_ENUM: + // This will be filled in when cross-linking. + result->default_value_enum_ = NULL; + break; + case FieldDescriptor::CPPTYPE_STRING: + result->default_value_string_ = &kEmptyString; + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + break; + } + } + } + + if (result->number() <= 0) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + "Field numbers must be positive integers."); + } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) { + // Only validate that the number is within the valid field range if it is + // not an extension. Since extension numbers are validated with the + // extendee's valid set of extension numbers, and those are in turn + // validated against the max allowed number, the check is unnecessary for + // extension fields. + // This avoids cross-linking issues that arise when attempting to check if + // the extendee is a message_set_wire_format message, which has a higher max + // on extension numbers. + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Field numbers cannot be greater than $0.", + FieldDescriptor::kMaxNumber)); + } else if (result->number() >= FieldDescriptor::kFirstReservedNumber && + result->number() <= FieldDescriptor::kLastReservedNumber) { + AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Field numbers $0 through $1 are reserved for the protocol " + "buffer library implementation.", + FieldDescriptor::kFirstReservedNumber, + FieldDescriptor::kLastReservedNumber)); + } + + if (is_extension) { + if (!proto.has_extendee()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "FieldDescriptorProto.extendee not set for extension field."); + } + + result->extension_scope_ = parent; + } else { + if (proto.has_extendee()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "FieldDescriptorProto.extendee set for non-extension field."); + } + + result->containing_type_ = parent; + } + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); +} + +void DescriptorBuilder::BuildExtensionRange( + const DescriptorProto::ExtensionRange& proto, + const Descriptor* parent, + Descriptor::ExtensionRange* result) { + result->start = proto.start(); + result->end = proto.end(); + if (result->start <= 0) { + AddError(parent->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + "Extension numbers must be positive integers."); + } + + // Checking of the upper bound of the extension range is deferred until after + // options interpreting. This allows messages with message_set_wire_format to + // have extensions beyond FieldDescriptor::kMaxNumber, since the extension + // numbers are actually used as int32s in the message_set_wire_format. + + if (result->start >= result->end) { + AddError(parent->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + "Extension range end number must be greater than start number."); + } +} + +void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, + const Descriptor* parent, + EnumDescriptor* result) { + const string& scope = (parent == NULL) ? + file_->package() : parent->full_name(); + string* full_name = tables_->AllocateString(scope); + if (!full_name->empty()) full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; + result->containing_type_ = parent; + result->is_placeholder_ = false; + result->is_unqualified_placeholder_ = false; + + if (proto.value_size() == 0) { + // We cannot allow enums with no values because this would mean there + // would be no valid default value for fields of this type. + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Enums must contain at least one value."); + } + + BUILD_ARRAY(proto, result, value, BuildEnumValue, result); + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); +} + +void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, + const EnumDescriptor* parent, + EnumValueDescriptor* result) { + result->name_ = tables_->AllocateString(proto.name()); + result->number_ = proto.number(); + result->type_ = parent; + + // Note: full_name for enum values is a sibling to the parent's name, not a + // child of it. + string* full_name = tables_->AllocateString(*parent->full_name_); + full_name->resize(full_name->size() - parent->name_->size()); + full_name->append(*result->name_); + result->full_name_ = full_name; + + ValidateSymbolName(proto.name(), *full_name, proto); + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + // Again, enum values are weird because we makes them appear as siblings + // of the enum type instead of children of it. So, we use + // parent->containing_type() as the value's parent. + bool added_to_outer_scope = + AddSymbol(result->full_name(), parent->containing_type(), result->name(), + proto, Symbol(result)); + + // However, we also want to be able to search for values within a single + // enum type, so we add it as a child of the enum type itself, too. + // Note: This could fail, but if it does, the error has already been + // reported by the above AddSymbol() call, so we ignore the return code. + bool added_to_inner_scope = + file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result)); + + if (added_to_inner_scope && !added_to_outer_scope) { + // This value did not conflict with any values defined in the same enum, + // but it did conflict with some other symbol defined in the enum type's + // scope. Let's print an additional error to explain this. + string outer_scope; + if (parent->containing_type() == NULL) { + outer_scope = file_->package(); + } else { + outer_scope = parent->containing_type()->full_name(); + } + + if (outer_scope.empty()) { + outer_scope = "the global scope"; + } else { + outer_scope = "\"" + outer_scope + "\""; + } + + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Note that enum values use C++ scoping rules, meaning that " + "enum values are siblings of their type, not children of it. " + "Therefore, \"" + result->name() + "\" must be unique within " + + outer_scope + ", not just within \"" + parent->name() + "\"."); + } + + // An enum is allowed to define two numbers that refer to the same value. + // FindValueByNumber() should return the first such value, so we simply + // ignore AddEnumValueByNumber()'s return code. + file_tables_->AddEnumValueByNumber(result); +} + +void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto, + const void* dummy, + ServiceDescriptor* result) { + string* full_name = tables_->AllocateString(file_->package()); + if (!full_name->empty()) full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + result->file_ = file_; + + BUILD_ARRAY(proto, result, method, BuildMethod, result); + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + AddSymbol(result->full_name(), NULL, result->name(), + proto, Symbol(result)); +} + +void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto, + const ServiceDescriptor* parent, + MethodDescriptor* result) { + result->name_ = tables_->AllocateString(proto.name()); + result->service_ = parent; + + string* full_name = tables_->AllocateString(parent->full_name()); + full_name->append(1, '.'); + full_name->append(*result->name_); + result->full_name_ = full_name; + + ValidateSymbolName(proto.name(), *full_name, proto); + + // These will be filled in when cross-linking. + result->input_type_ = NULL; + result->output_type_ = NULL; + + // Copy options. + if (!proto.has_options()) { + result->options_ = NULL; // Will set to default_instance later. + } else { + AllocateOptions(proto.options(), result); + } + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); +} + +#undef BUILD_ARRAY + +// ------------------------------------------------------------------- + +void DescriptorBuilder::CrossLinkFile( + FileDescriptor* file, const FileDescriptorProto& proto) { + if (file->options_ == NULL) { + file->options_ = &FileOptions::default_instance(); + } + + for (int i = 0; i < file->message_type_count(); i++) { + CrossLinkMessage(&file->message_types_[i], proto.message_type(i)); + } + + for (int i = 0; i < file->extension_count(); i++) { + CrossLinkField(&file->extensions_[i], proto.extension(i)); + } + + for (int i = 0; i < file->enum_type_count(); i++) { + CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i)); + } + + for (int i = 0; i < file->service_count(); i++) { + CrossLinkService(&file->services_[i], proto.service(i)); + } +} + +void DescriptorBuilder::CrossLinkMessage( + Descriptor* message, const DescriptorProto& proto) { + if (message->options_ == NULL) { + message->options_ = &MessageOptions::default_instance(); + } + + for (int i = 0; i < message->nested_type_count(); i++) { + CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i)); + } + + for (int i = 0; i < message->enum_type_count(); i++) { + CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i)); + } + + for (int i = 0; i < message->field_count(); i++) { + CrossLinkField(&message->fields_[i], proto.field(i)); + } + + for (int i = 0; i < message->extension_count(); i++) { + CrossLinkField(&message->extensions_[i], proto.extension(i)); + } +} + +void DescriptorBuilder::CrossLinkField( + FieldDescriptor* field, const FieldDescriptorProto& proto) { + if (field->options_ == NULL) { + field->options_ = &FieldOptions::default_instance(); + } + + if (proto.has_extendee()) { + Symbol extendee = LookupSymbol(proto.extendee(), field->full_name(), + PLACEHOLDER_EXTENDABLE_MESSAGE); + if (extendee.IsNull()) { + AddNotDefinedError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + proto.extendee()); + return; + } else if (extendee.type != Symbol::MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "\"" + proto.extendee() + "\" is not a message type."); + return; + } + field->containing_type_ = extendee.descriptor; + + if (!field->containing_type()->IsExtensionNumber(field->number())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("\"$0\" does not declare $1 as an " + "extension number.", + field->containing_type()->full_name(), + field->number())); + } + } + + if (proto.has_type_name()) { + // Assume we are expecting a message type unless the proto contains some + // evidence that it expects an enum type. This only makes a difference if + // we end up creating a placeholder. + bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) || + proto.has_default_value(); + + Symbol type = + LookupSymbol(proto.type_name(), field->full_name(), + expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE, + LOOKUP_TYPES); + + if (type.IsNull()) { + AddNotDefinedError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + proto.type_name()); + return; + } + + if (!proto.has_type()) { + // Choose field type based on symbol. + if (type.type == Symbol::MESSAGE) { + field->type_ = FieldDescriptor::TYPE_MESSAGE; + } else if (type.type == Symbol::ENUM) { + field->type_ = FieldDescriptor::TYPE_ENUM; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not a type."); + return; + } + } + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (type.type != Symbol::MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not a message type."); + return; + } + field->message_type_ = type.descriptor; + + if (field->has_default_value()) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Messages can't have default values."); + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + if (type.type != Symbol::ENUM) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "\"" + proto.type_name() + "\" is not an enum type."); + return; + } + field->enum_type_ = type.enum_descriptor; + + if (field->enum_type()->is_placeholder_) { + // We can't look up default values for placeholder types. We'll have + // to just drop them. + field->has_default_value_ = false; + } + + if (field->has_default_value()) { + // We can't just use field->enum_type()->FindValueByName() here + // because that locks the pool's mutex, which we have already locked + // at this point. + Symbol default_value = + LookupSymbolNoPlaceholder(proto.default_value(), + field->enum_type()->full_name()); + + if (default_value.type == Symbol::ENUM_VALUE && + default_value.enum_value_descriptor->type() == field->enum_type()) { + field->default_value_enum_ = default_value.enum_value_descriptor; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Enum type \"" + field->enum_type()->full_name() + + "\" has no value named \"" + proto.default_value() + "\"."); + } + } else if (field->enum_type()->value_count() > 0) { + // All enums must have at least one value, or we would have reported + // an error elsewhere. We use the first defined value as the default + // if a default is not explicitly defined. + field->default_value_enum_ = field->enum_type()->value(0); + } + } else { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Field with primitive type has type_name."); + } + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Field with message or enum type missing type_name."); + } + } + + // Add the field to the fields-by-number table. + // Note: We have to do this *after* cross-linking because extensions do not + // know their containing type until now. + if (!file_tables_->AddFieldByNumber(field)) { + const FieldDescriptor* conflicting_field = + file_tables_->FindFieldByNumber(field->containing_type(), + field->number()); + if (field->is_extension()) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension number $0 has already been used " + "in \"$1\" by extension \"$2\".", + field->number(), + field->containing_type()->full_name(), + conflicting_field->full_name())); + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Field number $0 has already been used in " + "\"$1\" by field \"$2\".", + field->number(), + field->containing_type()->full_name(), + conflicting_field->name())); + } + } + + if (field->is_extension()) { + // No need for error checking: if the extension number collided, + // we've already been informed of it by the if() above. + tables_->AddExtension(field); + } + + // Add the field to the lowercase-name and camelcase-name tables. + file_tables_->AddFieldByStylizedNames(field); +} + +void DescriptorBuilder::CrossLinkEnum( + EnumDescriptor* enum_type, const EnumDescriptorProto& proto) { + if (enum_type->options_ == NULL) { + enum_type->options_ = &EnumOptions::default_instance(); + } + + for (int i = 0; i < enum_type->value_count(); i++) { + CrossLinkEnumValue(&enum_type->values_[i], proto.value(i)); + } +} + +void DescriptorBuilder::CrossLinkEnumValue( + EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) { + if (enum_value->options_ == NULL) { + enum_value->options_ = &EnumValueOptions::default_instance(); + } +} + +void DescriptorBuilder::CrossLinkService( + ServiceDescriptor* service, const ServiceDescriptorProto& proto) { + if (service->options_ == NULL) { + service->options_ = &ServiceOptions::default_instance(); + } + + for (int i = 0; i < service->method_count(); i++) { + CrossLinkMethod(&service->methods_[i], proto.method(i)); + } +} + +void DescriptorBuilder::CrossLinkMethod( + MethodDescriptor* method, const MethodDescriptorProto& proto) { + if (method->options_ == NULL) { + method->options_ = &MethodOptions::default_instance(); + } + + Symbol input_type = LookupSymbol(proto.input_type(), method->full_name()); + if (input_type.IsNull()) { + AddNotDefinedError(method->full_name(), proto, + DescriptorPool::ErrorCollector::INPUT_TYPE, + proto.input_type()); + } else if (input_type.type != Symbol::MESSAGE) { + AddError(method->full_name(), proto, + DescriptorPool::ErrorCollector::INPUT_TYPE, + "\"" + proto.input_type() + "\" is not a message type."); + } else { + method->input_type_ = input_type.descriptor; + } + + Symbol output_type = LookupSymbol(proto.output_type(), method->full_name()); + if (output_type.IsNull()) { + AddNotDefinedError(method->full_name(), proto, + DescriptorPool::ErrorCollector::OUTPUT_TYPE, + proto.output_type()); + } else if (output_type.type != Symbol::MESSAGE) { + AddError(method->full_name(), proto, + DescriptorPool::ErrorCollector::OUTPUT_TYPE, + "\"" + proto.output_type() + "\" is not a message type."); + } else { + method->output_type_ = output_type.descriptor; + } +} + +// ------------------------------------------------------------------- + +#define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \ + for (int i = 0; i < descriptor->array_name##_count(); ++i) { \ + Validate##type##Options(descriptor->array_name##s_ + i, \ + proto.array_name(i)); \ + } + +// Determine if the file uses optimize_for = LITE_RUNTIME, being careful to +// avoid problems that exist at init time. +static bool IsLite(const FileDescriptor* file) { + // TODO(kenton): I don't even remember how many of these conditions are + // actually possible. I'm just being super-safe. + return file != NULL && + &file->options() != NULL && + &file->options() != &FileOptions::default_instance() && + file->options().optimize_for() == FileOptions::LITE_RUNTIME; +} + +void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, + const FileDescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message); + VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum); + VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service); + VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field); + + // Lite files can only be imported by other Lite files. + if (!IsLite(file)) { + for (int i = 0; i < file->dependency_count(); i++) { + if (IsLite(file->dependency(i))) { + AddError( + file->name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "Files that do not use optimize_for = LITE_RUNTIME cannot import " + "files which do use this option. This file is not lite, but it " + "imports \"" + file->dependency(i)->name() + "\" which is."); + break; + } + } + } +} + +void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, + const DescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field); + VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message); + VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum); + VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field); + + const int64 max_extension_range = + static_cast(message->options().message_set_wire_format() ? + kint32max : + FieldDescriptor::kMaxNumber); + for (int i = 0; i < message->extension_range_count(); ++i) { + if (message->extension_range(i)->end > max_extension_range + 1) { + AddError( + message->full_name(), proto.extension_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension numbers cannot be greater than $0.", + max_extension_range)); + } + } +} + +void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + if (field->options().has_experimental_map_key()) { + ValidateMapKey(field, proto); + } + + // Only message type fields may be lazy. + if (field->options().lazy()) { + if (field->type() != FieldDescriptor::TYPE_MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "[lazy = true] can only be specified for submessage fields."); + } + } + + // Only repeated primitive fields may be packed. + if (field->options().packed() && !field->is_packable()) { + AddError( + field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "[packed = true] can only be specified for repeated primitive fields."); + } + + // Note: Default instance may not yet be initialized here, so we have to + // avoid reading from it. + if (field->containing_type_ != NULL && + &field->containing_type()->options() != + &MessageOptions::default_instance() && + field->containing_type()->options().message_set_wire_format()) { + if (field->is_extension()) { + if (!field->is_optional() || + field->type() != FieldDescriptor::TYPE_MESSAGE) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "Extensions of MessageSets must be optional messages."); + } + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "MessageSets cannot have fields, only extensions."); + } + } + + // Lite extensions can only be of Lite types. + if (IsLite(field->file()) && + field->containing_type_ != NULL && + !IsLite(field->containing_type()->file())) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::EXTENDEE, + "Extensions to non-lite types can only be declared in non-lite " + "files. Note that you cannot extend a non-lite type to contain " + "a lite type, but the reverse is allowed."); + } + +} + +void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, + const EnumDescriptorProto& proto) { + VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue); + if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) { + map used_values; + for (int i = 0; i < enm->value_count(); ++i) { + const EnumValueDescriptor* enum_value = enm->value(i); + if (used_values.find(enum_value->number()) != used_values.end()) { + string error = + "\"" + enum_value->full_name() + + "\" uses the same enum value as \"" + + used_values[enum_value->number()] + "\". If this is intended, set " + "'option allow_alias = true;' to the enum definition."; + if (!enm->options().allow_alias()) { + // Generate error if duplicated enum values are explicitly disallowed. + AddError(enm->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + error); + } else { + // Generate warning if duplicated values are found but the option + // isn't set. + GOOGLE_LOG(ERROR) << error; + } + } else { + used_values[enum_value->number()] = enum_value->full_name(); + } + } + } +} + +void DescriptorBuilder::ValidateEnumValueOptions( + EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto) { + // Nothing to do so far. +} +void DescriptorBuilder::ValidateServiceOptions(ServiceDescriptor* service, + const ServiceDescriptorProto& proto) { + if (IsLite(service->file()) && + (service->file()->options().cc_generic_services() || + service->file()->options().java_generic_services())) { + AddError(service->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Files with optimize_for = LITE_RUNTIME cannot define services " + "unless you set both options cc_generic_services and " + "java_generic_sevices to false."); + } + + VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method); +} + +void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* method, + const MethodDescriptorProto& proto) { + // Nothing to do so far. +} + +void DescriptorBuilder::ValidateMapKey(FieldDescriptor* field, + const FieldDescriptorProto& proto) { + if (!field->is_repeated()) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "map type is only allowed for repeated fields."); + return; + } + + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "map type is only allowed for fields with a message type."); + return; + } + + const Descriptor* item_type = field->message_type(); + if (item_type == NULL) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Could not find field type."); + return; + } + + // Find the field in item_type named by "experimental_map_key" + const string& key_name = field->options().experimental_map_key(); + const Symbol key_symbol = LookupSymbol( + key_name, + // We append ".key_name" to the containing type's name since + // LookupSymbol() searches for peers of the supplied name, not + // children of the supplied name. + item_type->full_name() + "." + key_name); + + if (key_symbol.IsNull() || key_symbol.field_descriptor->is_extension()) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "Could not find field named \"" + key_name + "\" in type \"" + + item_type->full_name() + "\"."); + return; + } + const FieldDescriptor* key_field = key_symbol.field_descriptor; + + if (key_field->is_repeated()) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "map_key must not name a repeated field."); + return; + } + + if (key_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, + "map key must name a scalar or string field."); + return; + } + + field->experimental_map_key_ = key_field; +} + + +#undef VALIDATE_OPTIONS_FROM_ARRAY + +// ------------------------------------------------------------------- + +DescriptorBuilder::OptionInterpreter::OptionInterpreter( + DescriptorBuilder* builder) : builder_(builder) { + GOOGLE_CHECK(builder_); +} + +DescriptorBuilder::OptionInterpreter::~OptionInterpreter() { +} + +bool DescriptorBuilder::OptionInterpreter::InterpretOptions( + OptionsToInterpret* options_to_interpret) { + // Note that these may be in different pools, so we can't use the same + // descriptor and reflection objects on both. + Message* options = options_to_interpret->options; + const Message* original_options = options_to_interpret->original_options; + + bool failed = false; + options_to_interpret_ = options_to_interpret; + + // Find the uninterpreted_option field in the mutable copy of the options + // and clear them, since we're about to interpret them. + const FieldDescriptor* uninterpreted_options_field = + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(uninterpreted_options_field != NULL) + << "No field named \"uninterpreted_option\" in the Options proto."; + options->GetReflection()->ClearField(options, uninterpreted_options_field); + + // Find the uninterpreted_option field in the original options. + const FieldDescriptor* original_uninterpreted_options_field = + original_options->GetDescriptor()-> + FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(original_uninterpreted_options_field != NULL) + << "No field named \"uninterpreted_option\" in the Options proto."; + + const int num_uninterpreted_options = original_options->GetReflection()-> + FieldSize(*original_options, original_uninterpreted_options_field); + for (int i = 0; i < num_uninterpreted_options; ++i) { + uninterpreted_option_ = down_cast( + &original_options->GetReflection()->GetRepeatedMessage( + *original_options, original_uninterpreted_options_field, i)); + if (!InterpretSingleOption(options)) { + // Error already added by InterpretSingleOption(). + failed = true; + break; + } + } + // Reset these, so we don't have any dangling pointers. + uninterpreted_option_ = NULL; + options_to_interpret_ = NULL; + + if (!failed) { + // InterpretSingleOption() added the interpreted options in the + // UnknownFieldSet, in case the option isn't yet known to us. Now we + // serialize the options message and deserialize it back. That way, any + // option fields that we do happen to know about will get moved from the + // UnknownFieldSet into the real fields, and thus be available right away. + // If they are not known, that's OK too. They will get reparsed into the + // UnknownFieldSet and wait there until the message is parsed by something + // that does know about the options. + string buf; + options->AppendToString(&buf); + GOOGLE_CHECK(options->ParseFromString(buf)) + << "Protocol message serialized itself in invalid fashion."; + } + + return !failed; +} + +bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( + Message* options) { + // First do some basic validation. + if (uninterpreted_option_->name_size() == 0) { + // This should never happen unless the parser has gone seriously awry or + // someone has manually created the uninterpreted option badly. + return AddNameError("Option must have a name."); + } + if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") { + return AddNameError("Option must not use reserved name " + "\"uninterpreted_option\"."); + } + + const Descriptor* options_descriptor = NULL; + // Get the options message's descriptor from the builder's pool, so that we + // get the version that knows about any extension options declared in the + // file we're currently building. The descriptor should be there as long as + // the file we're building imported "google/protobuf/descriptors.proto". + + // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not + // DescriptorPool::FindMessageTypeByName() because we're already holding the + // pool's mutex, and the latter method locks it again. We don't use + // FindSymbol() because files that use custom options only need to depend on + // the file that defines the option, not descriptor.proto itself. + Symbol symbol = builder_->FindSymbolNotEnforcingDeps( + options->GetDescriptor()->full_name()); + if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) { + options_descriptor = symbol.descriptor; + } else { + // The options message's descriptor was not in the builder's pool, so use + // the standard version from the generated pool. We're not holding the + // generated pool's mutex, so we can search it the straightforward way. + options_descriptor = options->GetDescriptor(); + } + GOOGLE_CHECK(options_descriptor); + + // We iterate over the name parts to drill into the submessages until we find + // the leaf field for the option. As we drill down we remember the current + // submessage's descriptor in |descriptor| and the next field in that + // submessage in |field|. We also track the fields we're drilling down + // through in |intermediate_fields|. As we go, we reconstruct the full option + // name in |debug_msg_name|, for use in error messages. + const Descriptor* descriptor = options_descriptor; + const FieldDescriptor* field = NULL; + vector intermediate_fields; + string debug_msg_name = ""; + + for (int i = 0; i < uninterpreted_option_->name_size(); ++i) { + const string& name_part = uninterpreted_option_->name(i).name_part(); + if (debug_msg_name.size() > 0) { + debug_msg_name += "."; + } + if (uninterpreted_option_->name(i).is_extension()) { + debug_msg_name += "(" + name_part + ")"; + // Search for the extension's descriptor as an extension in the builder's + // pool. Note that we use DescriptorBuilder::LookupSymbol(), not + // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows + // relative lookups, and 2) because we're already holding the pool's + // mutex, and the latter method locks it again. + symbol = builder_->LookupSymbol(name_part, + options_to_interpret_->name_scope); + if (!symbol.IsNull() && symbol.type == Symbol::FIELD) { + field = symbol.field_descriptor; + } + // If we don't find the field then the field's descriptor was not in the + // builder's pool, but there's no point in looking in the generated + // pool. We require that you import the file that defines any extensions + // you use, so they must be present in the builder's pool. + } else { + debug_msg_name += name_part; + // Search for the field's descriptor as a regular field. + field = descriptor->FindFieldByName(name_part); + } + + if (field == NULL) { + if (get_allow_unknown(builder_->pool_)) { + // We can't find the option, but AllowUnknownDependencies() is enabled, + // so we will just leave it as uninterpreted. + AddWithoutInterpreting(*uninterpreted_option_, options); + return true; + } else { + return AddNameError("Option \"" + debug_msg_name + "\" unknown."); + } + } else if (field->containing_type() != descriptor) { + if (get_is_placeholder(field->containing_type())) { + // The field is an extension of a placeholder type, so we can't + // reliably verify whether it is a valid extension to use here (e.g. + // we don't know if it is an extension of the correct *Options message, + // or if it has a valid field number, etc.). Just leave it as + // uninterpreted instead. + AddWithoutInterpreting(*uninterpreted_option_, options); + return true; + } else { + // This can only happen if, due to some insane misconfiguration of the + // pools, we find the options message in one pool but the field in + // another. This would probably imply a hefty bug somewhere. + return AddNameError("Option field \"" + debug_msg_name + + "\" is not a field or extension of message \"" + + descriptor->name() + "\"."); + } + } else if (field->is_repeated()) { + return AddNameError("Option field \"" + debug_msg_name + + "\" is repeated. Repeated options are not " + "supported."); + } else if (i < uninterpreted_option_->name_size() - 1) { + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return AddNameError("Option \"" + debug_msg_name + + "\" is an atomic type, not a message."); + } else { + // Drill down into the submessage. + intermediate_fields.push_back(field); + descriptor = field->message_type(); + } + } + } + + // We've found the leaf field. Now we use UnknownFieldSets to set its value + // on the options message. We do so because the message may not yet know + // about its extension fields, so we may not be able to set the fields + // directly. But the UnknownFieldSets will serialize to the same wire-format + // message, so reading that message back in once the extension fields are + // known will populate them correctly. + + // First see if the option is already set. + if (!ExamineIfOptionIsSet( + intermediate_fields.begin(), + intermediate_fields.end(), + field, debug_msg_name, + options->GetReflection()->GetUnknownFields(*options))) { + return false; // ExamineIfOptionIsSet() already added the error. + } + + + // First set the value on the UnknownFieldSet corresponding to the + // innermost message. + scoped_ptr unknown_fields(new UnknownFieldSet()); + if (!SetOptionValue(field, unknown_fields.get())) { + return false; // SetOptionValue() already added the error. + } + + // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all + // the intermediate messages. + for (vector::reverse_iterator iter = + intermediate_fields.rbegin(); + iter != intermediate_fields.rend(); ++iter) { + scoped_ptr parent_unknown_fields(new UnknownFieldSet()); + switch ((*iter)->type()) { + case FieldDescriptor::TYPE_MESSAGE: { + io::StringOutputStream outstr( + parent_unknown_fields->AddLengthDelimited((*iter)->number())); + io::CodedOutputStream out(&outstr); + internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out); + GOOGLE_CHECK(!out.HadError()) + << "Unexpected failure while serializing option submessage " + << debug_msg_name << "\"."; + break; + } + + case FieldDescriptor::TYPE_GROUP: { + parent_unknown_fields->AddGroup((*iter)->number()) + ->MergeFrom(*unknown_fields); + break; + } + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " + << (*iter)->type(); + return false; + } + unknown_fields.reset(parent_unknown_fields.release()); + } + + // Now merge the UnknownFieldSet corresponding to the top-level message into + // the options message. + options->GetReflection()->MutableUnknownFields(options)->MergeFrom( + *unknown_fields); + + return true; +} + +void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting( + const UninterpretedOption& uninterpreted_option, Message* options) { + const FieldDescriptor* field = + options->GetDescriptor()->FindFieldByName("uninterpreted_option"); + GOOGLE_CHECK(field != NULL); + + options->GetReflection()->AddMessage(options, field) + ->CopyFrom(uninterpreted_option); +} + +bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet( + vector::const_iterator intermediate_fields_iter, + vector::const_iterator intermediate_fields_end, + const FieldDescriptor* innermost_field, const string& debug_msg_name, + const UnknownFieldSet& unknown_fields) { + // We do linear searches of the UnknownFieldSet and its sub-groups. This + // should be fine since it's unlikely that any one options structure will + // contain more than a handful of options. + + if (intermediate_fields_iter == intermediate_fields_end) { + // We're at the innermost submessage. + for (int i = 0; i < unknown_fields.field_count(); i++) { + if (unknown_fields.field(i).number() == innermost_field->number()) { + return AddNameError("Option \"" + debug_msg_name + + "\" was already set."); + } + } + return true; + } + + for (int i = 0; i < unknown_fields.field_count(); i++) { + if (unknown_fields.field(i).number() == + (*intermediate_fields_iter)->number()) { + const UnknownField* unknown_field = &unknown_fields.field(i); + FieldDescriptor::Type type = (*intermediate_fields_iter)->type(); + // Recurse into the next submessage. + switch (type) { + case FieldDescriptor::TYPE_MESSAGE: + if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) { + UnknownFieldSet intermediate_unknown_fields; + if (intermediate_unknown_fields.ParseFromString( + unknown_field->length_delimited()) && + !ExamineIfOptionIsSet(intermediate_fields_iter + 1, + intermediate_fields_end, + innermost_field, debug_msg_name, + intermediate_unknown_fields)) { + return false; // Error already added. + } + } + break; + + case FieldDescriptor::TYPE_GROUP: + if (unknown_field->type() == UnknownField::TYPE_GROUP) { + if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1, + intermediate_fields_end, + innermost_field, debug_msg_name, + unknown_field->group())) { + return false; // Error already added. + } + } + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type; + return false; + } + } + } + return true; +} + +bool DescriptorBuilder::OptionInterpreter::SetOptionValue( + const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields) { + // We switch on the CppType to validate. + switch (option_field->cpp_type()) { + + case FieldDescriptor::CPPTYPE_INT32: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > + static_cast(kint32max)) { + return AddValueError("Value out of range for int32 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt32(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else if (uninterpreted_option_->has_negative_int_value()) { + if (uninterpreted_option_->negative_int_value() < + static_cast(kint32min)) { + return AddValueError("Value out of range for int32 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt32(option_field->number(), + uninterpreted_option_->negative_int_value(), + option_field->type(), unknown_fields); + } + } else { + return AddValueError("Value must be integer for int32 option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_INT64: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > + static_cast(kint64max)) { + return AddValueError("Value out of range for int64 option \"" + + option_field->full_name() + "\"."); + } else { + SetInt64(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else if (uninterpreted_option_->has_negative_int_value()) { + SetInt64(option_field->number(), + uninterpreted_option_->negative_int_value(), + option_field->type(), unknown_fields); + } else { + return AddValueError("Value must be integer for int64 option \"" + + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_UINT32: + if (uninterpreted_option_->has_positive_int_value()) { + if (uninterpreted_option_->positive_int_value() > kuint32max) { + return AddValueError("Value out of range for uint32 option \"" + + option_field->name() + "\"."); + } else { + SetUInt32(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } + } else { + return AddValueError("Value must be non-negative integer for uint32 " + "option \"" + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_UINT64: + if (uninterpreted_option_->has_positive_int_value()) { + SetUInt64(option_field->number(), + uninterpreted_option_->positive_int_value(), + option_field->type(), unknown_fields); + } else { + return AddValueError("Value must be non-negative integer for uint64 " + "option \"" + option_field->full_name() + "\"."); + } + break; + + case FieldDescriptor::CPPTYPE_FLOAT: { + float value; + if (uninterpreted_option_->has_double_value()) { + value = uninterpreted_option_->double_value(); + } else if (uninterpreted_option_->has_positive_int_value()) { + value = uninterpreted_option_->positive_int_value(); + } else if (uninterpreted_option_->has_negative_int_value()) { + value = uninterpreted_option_->negative_int_value(); + } else { + return AddValueError("Value must be number for float option \"" + + option_field->full_name() + "\"."); + } + unknown_fields->AddFixed32(option_field->number(), + google::protobuf::internal::WireFormatLite::EncodeFloat(value)); + break; + } + + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value; + if (uninterpreted_option_->has_double_value()) { + value = uninterpreted_option_->double_value(); + } else if (uninterpreted_option_->has_positive_int_value()) { + value = uninterpreted_option_->positive_int_value(); + } else if (uninterpreted_option_->has_negative_int_value()) { + value = uninterpreted_option_->negative_int_value(); + } else { + return AddValueError("Value must be number for double option \"" + + option_field->full_name() + "\"."); + } + unknown_fields->AddFixed64(option_field->number(), + google::protobuf::internal::WireFormatLite::EncodeDouble(value)); + break; + } + + case FieldDescriptor::CPPTYPE_BOOL: + uint64 value; + if (!uninterpreted_option_->has_identifier_value()) { + return AddValueError("Value must be identifier for boolean option " + "\"" + option_field->full_name() + "\"."); + } + if (uninterpreted_option_->identifier_value() == "true") { + value = 1; + } else if (uninterpreted_option_->identifier_value() == "false") { + value = 0; + } else { + return AddValueError("Value must be \"true\" or \"false\" for boolean " + "option \"" + option_field->full_name() + "\"."); + } + unknown_fields->AddVarint(option_field->number(), value); + break; + + case FieldDescriptor::CPPTYPE_ENUM: { + if (!uninterpreted_option_->has_identifier_value()) { + return AddValueError("Value must be identifier for enum-valued option " + "\"" + option_field->full_name() + "\"."); + } + const EnumDescriptor* enum_type = option_field->enum_type(); + const string& value_name = uninterpreted_option_->identifier_value(); + const EnumValueDescriptor* enum_value = NULL; + + if (enum_type->file()->pool() != DescriptorPool::generated_pool()) { + // Note that the enum value's fully-qualified name is a sibling of the + // enum's name, not a child of it. + string fully_qualified_name = enum_type->full_name(); + fully_qualified_name.resize(fully_qualified_name.size() - + enum_type->name().size()); + fully_qualified_name += value_name; + + // Search for the enum value's descriptor in the builder's pool. Note + // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not + // DescriptorPool::FindEnumValueByName() because we're already holding + // the pool's mutex, and the latter method locks it again. + Symbol symbol = + builder_->FindSymbolNotEnforcingDeps(fully_qualified_name); + if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) { + if (symbol.enum_value_descriptor->type() != enum_type) { + return AddValueError("Enum type \"" + enum_type->full_name() + + "\" has no value named \"" + value_name + "\" for option \"" + + option_field->full_name() + + "\". This appears to be a value from a sibling type."); + } else { + enum_value = symbol.enum_value_descriptor; + } + } + } else { + // The enum type is in the generated pool, so we can search for the + // value there. + enum_value = enum_type->FindValueByName(value_name); + } + + if (enum_value == NULL) { + return AddValueError("Enum type \"" + + option_field->enum_type()->full_name() + + "\" has no value named \"" + value_name + "\" for " + "option \"" + option_field->full_name() + "\"."); + } else { + // Sign-extension is not a problem, since we cast directly from int32 to + // uint64, without first going through uint32. + unknown_fields->AddVarint(option_field->number(), + static_cast(static_cast(enum_value->number()))); + } + break; + } + + case FieldDescriptor::CPPTYPE_STRING: + if (!uninterpreted_option_->has_string_value()) { + return AddValueError("Value must be quoted string for string option " + "\"" + option_field->full_name() + "\"."); + } + // The string has already been unquoted and unescaped by the parser. + unknown_fields->AddLengthDelimited(option_field->number(), + uninterpreted_option_->string_value()); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (!SetAggregateOption(option_field, unknown_fields)) { + return false; + } + break; + } + + return true; +} + +class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder + : public TextFormat::Finder { + public: + DescriptorBuilder* builder_; + + virtual const FieldDescriptor* FindExtension( + Message* message, const string& name) const { + assert_mutex_held(builder_->pool_); + const Descriptor* descriptor = message->GetDescriptor(); + Symbol result = builder_->LookupSymbolNoPlaceholder( + name, descriptor->full_name()); + if (result.type == Symbol::FIELD && + result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else if (result.type == Symbol::MESSAGE && + descriptor->options().message_set_wire_format()) { + const Descriptor* foreign_type = result.descriptor; + // The text format allows MessageSet items to be specified using + // the type name, rather than the extension identifier. If the symbol + // lookup returned a Message, and the enclosing Message has + // message_set_wire_format = true, then return the message set + // extension, if one exists. + for (int i = 0; i < foreign_type->extension_count(); i++) { + const FieldDescriptor* extension = foreign_type->extension(i); + if (extension->containing_type() == descriptor && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && + extension->message_type() == foreign_type) { + // Found it. + return extension; + } + } + } + return NULL; + } +}; + +// A custom error collector to record any text-format parsing errors +namespace { +class AggregateErrorCollector : public io::ErrorCollector { + public: + string error_; + + virtual void AddError(int line, int column, const string& message) { + if (!error_.empty()) { + error_ += "; "; + } + error_ += message; + } + + virtual void AddWarning(int line, int column, const string& message) { + // Ignore warnings + } +}; +} + +// We construct a dynamic message of the type corresponding to +// option_field, parse the supplied text-format string into this +// message, and serialize the resulting message to produce the value. +bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( + const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields) { + if (!uninterpreted_option_->has_aggregate_value()) { + return AddValueError("Option \"" + option_field->full_name() + + "\" is a message. To set the entire message, use " + "syntax like \"" + option_field->name() + + " = { }\". " + "To set fields within it, use " + "syntax like \"" + option_field->name() + + ".foo = value\"."); + } + + const Descriptor* type = option_field->message_type(); + scoped_ptr dynamic(dynamic_factory_.GetPrototype(type)->New()); + GOOGLE_CHECK(dynamic.get() != NULL) + << "Could not create an instance of " << option_field->DebugString(); + + AggregateErrorCollector collector; + AggregateOptionFinder finder; + finder.builder_ = builder_; + TextFormat::Parser parser; + parser.RecordErrorsTo(&collector); + parser.SetFinder(&finder); + if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(), + dynamic.get())) { + AddValueError("Error while parsing option value for \"" + + option_field->name() + "\": " + collector.error_); + return false; + } else { + string serial; + dynamic->SerializeToString(&serial); // Never fails + if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) { + unknown_fields->AddLengthDelimited(option_field->number(), serial); + } else { + GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP); + UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number()); + group->ParseFromString(serial); + } + return true; + } +} + +void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, + FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + unknown_fields->AddVarint(number, + static_cast(static_cast(value))); + break; + + case FieldDescriptor::TYPE_SFIXED32: + unknown_fields->AddFixed32(number, static_cast(value)); + break; + + case FieldDescriptor::TYPE_SINT32: + unknown_fields->AddVarint(number, + google::protobuf::internal::WireFormatLite::ZigZagEncode32(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetInt64(int number, int64 value, + FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_INT64: + unknown_fields->AddVarint(number, static_cast(value)); + break; + + case FieldDescriptor::TYPE_SFIXED64: + unknown_fields->AddFixed64(number, static_cast(value)); + break; + + case FieldDescriptor::TYPE_SINT64: + unknown_fields->AddVarint(number, + google::protobuf::internal::WireFormatLite::ZigZagEncode64(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetUInt32(int number, uint32 value, + FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_UINT32: + unknown_fields->AddVarint(number, static_cast(value)); + break; + + case FieldDescriptor::TYPE_FIXED32: + unknown_fields->AddFixed32(number, static_cast(value)); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type; + break; + } +} + +void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value, + FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { + switch (type) { + case FieldDescriptor::TYPE_UINT64: + unknown_fields->AddVarint(number, value); + break; + + case FieldDescriptor::TYPE_FIXED64: + unknown_fields->AddFixed64(number, value); + break; + + default: + GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type; + break; + } +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.h new file mode 100644 index 000000000..33e3af724 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.h @@ -0,0 +1,1521 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains classes which describe a type of protocol message. +// You can use a message's descriptor to learn at runtime what fields +// it contains and what the types of those fields are. The Message +// interface also allows you to dynamically access and modify individual +// fields by passing the FieldDescriptor of the field you are interested +// in. +// +// Most users will not care about descriptors, because they will write +// code specific to certain protocol types and will simply use the classes +// generated by the protocol compiler directly. Advanced users who want +// to operate on arbitrary types (not known at compile time) may want to +// read descriptors in order to learn about the contents of a message. +// A very small number of users will want to construct their own +// Descriptors, either because they are implementing Message manually or +// because they are writing something like the protocol compiler. +// +// For an example of how you might use descriptors, see the code example +// at the top of message.h. + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#define GOOGLE_PROTOBUF_DESCRIPTOR_H__ + +#include +#include +#include + +// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. +#ifdef TYPE_BOOL +#undef TYPE_BOOL +#endif // TYPE_BOOL + +namespace google { +namespace protobuf { + +// Defined in this file. +class Descriptor; +class FieldDescriptor; +class EnumDescriptor; +class EnumValueDescriptor; +class ServiceDescriptor; +class MethodDescriptor; +class FileDescriptor; +class DescriptorDatabase; +class DescriptorPool; + +// Defined in descriptor.proto +class DescriptorProto; +class FieldDescriptorProto; +class EnumDescriptorProto; +class EnumValueDescriptorProto; +class ServiceDescriptorProto; +class MethodDescriptorProto; +class FileDescriptorProto; +class MessageOptions; +class FieldOptions; +class EnumOptions; +class EnumValueOptions; +class ServiceOptions; +class MethodOptions; +class FileOptions; +class UninterpretedOption; +class SourceCodeInfo; + +// Defined in message.h +class Message; + +// Defined in descriptor.cc +class DescriptorBuilder; +class FileDescriptorTables; + +// Defined in unknown_field_set.h. +class UnknownField; + +// NB, all indices are zero-based. +struct SourceLocation { + int start_line; + int end_line; + int start_column; + int end_column; + + // Doc comments found at the source location. + // TODO(kenton): Maybe this struct should have been named SourceInfo or + // something instead. Oh well. + string leading_comments; + string trailing_comments; +}; + +// Describes a type of protocol message, or a particular group within a +// message. To obtain the Descriptor for a given message object, call +// Message::GetDescriptor(). Generated message classes also have a +// static method called descriptor() which returns the type's descriptor. +// Use DescriptorPool to construct your own descriptors. +class LIBPROTOBUF_EXPORT Descriptor { + public: + // The name of the message type, not including its scope. + const string& name() const; + + // The fully-qualified name of the message type, scope delimited by + // periods. For example, message type "Foo" which is declared in package + // "bar" has full name "bar.Foo". If a type "Baz" is nested within + // Foo, Baz's full_name is "bar.Foo.Baz". To get only the part that + // comes after the last '.', use name(). + const string& full_name() const; + + // Index of this descriptor within the file or containing type's message + // type array. + int index() const; + + // The .proto file in which this message type was defined. Never NULL. + const FileDescriptor* file() const; + + // If this Descriptor describes a nested type, this returns the type + // in which it is nested. Otherwise, returns NULL. + const Descriptor* containing_type() const; + + // Get options for this message type. These are specified in the .proto file + // by placing lines like "option foo = 1234;" in the message definition. + // Allowed options are defined by MessageOptions in + // google/protobuf/descriptor.proto, and any available extensions of that + // message. + const MessageOptions& options() const; + + // Write the contents of this Descriptor into the given DescriptorProto. + // The target DescriptorProto must be clear before calling this; if it + // isn't, the result may be garbage. + void CopyTo(DescriptorProto* proto) const; + + // Write the contents of this decriptor in a human-readable form. Output + // will be suitable for re-parsing. + string DebugString() const; + + // Field stuff ----------------------------------------------------- + + // The number of fields in this message type. + int field_count() const; + // Gets a field by index, where 0 <= index < field_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* field(int index) const; + + // Looks up a field by declared tag number. Returns NULL if no such field + // exists. + const FieldDescriptor* FindFieldByNumber(int number) const; + // Looks up a field by name. Returns NULL if no such field exists. + const FieldDescriptor* FindFieldByName(const string& name) const; + + // Looks up a field by lowercased name (as returned by lowercase_name()). + // This lookup may be ambiguous if multiple field names differ only by case, + // in which case the field returned is chosen arbitrarily from the matches. + const FieldDescriptor* FindFieldByLowercaseName( + const string& lowercase_name) const; + + // Looks up a field by camel-case name (as returned by camelcase_name()). + // This lookup may be ambiguous if multiple field names differ in a way that + // leads them to have identical camel-case names, in which case the field + // returned is chosen arbitrarily from the matches. + const FieldDescriptor* FindFieldByCamelcaseName( + const string& camelcase_name) const; + + // Nested type stuff ----------------------------------------------- + + // The number of nested types in this message type. + int nested_type_count() const; + // Gets a nested type by index, where 0 <= index < nested_type_count(). + // These are returned in the order they were defined in the .proto file. + const Descriptor* nested_type(int index) const; + + // Looks up a nested type by name. Returns NULL if no such nested type + // exists. + const Descriptor* FindNestedTypeByName(const string& name) const; + + // Enum stuff ------------------------------------------------------ + + // The number of enum types in this message type. + int enum_type_count() const; + // Gets an enum type by index, where 0 <= index < enum_type_count(). + // These are returned in the order they were defined in the .proto file. + const EnumDescriptor* enum_type(int index) const; + + // Looks up an enum type by name. Returns NULL if no such enum type exists. + const EnumDescriptor* FindEnumTypeByName(const string& name) const; + + // Looks up an enum value by name, among all enum types in this message. + // Returns NULL if no such value exists. + const EnumValueDescriptor* FindEnumValueByName(const string& name) const; + + // Extensions ------------------------------------------------------ + + // A range of field numbers which are designated for third-party + // extensions. + struct ExtensionRange { + int start; // inclusive + int end; // exclusive + }; + + // The number of extension ranges in this message type. + int extension_range_count() const; + // Gets an extension range by index, where 0 <= index < + // extension_range_count(). These are returned in the order they were defined + // in the .proto file. + const ExtensionRange* extension_range(int index) const; + + // Returns true if the number is in one of the extension ranges. + bool IsExtensionNumber(int number) const; + + // The number of extensions -- extending *other* messages -- that were + // defined nested within this message type's scope. + int extension_count() const; + // Get an extension by index, where 0 <= index < extension_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* extension(int index) const; + + // Looks up a named extension (which extends some *other* message type) + // defined within this message type's scope. + const FieldDescriptor* FindExtensionByName(const string& name) const; + + // Similar to FindFieldByLowercaseName(), but finds extensions defined within + // this message type's scope. + const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const; + + // Similar to FindFieldByCamelcaseName(), but finds extensions defined within + // this message type's scope. + const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this message declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef MessageOptions OptionsType; + + // Internal version of DebugString; controls the level of indenting for + // correct depth + void DebugString(int depth, string *contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const FileDescriptor* file_; + const Descriptor* containing_type_; + const MessageOptions* options_; + + // True if this is a placeholder for an unknown type. + bool is_placeholder_; + // True if this is a placeholder and the type name wasn't fully-qualified. + bool is_unqualified_placeholder_; + + int field_count_; + FieldDescriptor* fields_; + int nested_type_count_; + Descriptor* nested_types_; + int enum_type_count_; + EnumDescriptor* enum_types_; + int extension_range_count_; + ExtensionRange* extension_ranges_; + int extension_count_; + FieldDescriptor* extensions_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in descriptor.cc + // and update them to initialize the field. + + // Must be constructed using DescriptorPool. + Descriptor() {} + friend class DescriptorBuilder; + friend class EnumDescriptor; + friend class FieldDescriptor; + friend class MethodDescriptor; + friend class FileDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor); +}; + +// Describes a single field of a message. To get the descriptor for a given +// field, first get the Descriptor for the message in which it is defined, +// then call Descriptor::FindFieldByName(). To get a FieldDescriptor for +// an extension, do one of the following: +// - Get the Descriptor or FileDescriptor for its containing scope, then +// call Descriptor::FindExtensionByName() or +// FileDescriptor::FindExtensionByName(). +// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber(). +// - Given a Reflection for a message object, call +// Reflection::FindKnownExtensionByName() or +// Reflection::FindKnownExtensionByNumber(). +// Use DescriptorPool to construct your own descriptors. +class LIBPROTOBUF_EXPORT FieldDescriptor { + public: + // Identifies a field type. 0 is reserved for errors. The order is weird + // for historical reasons. Types 12 and up are new in proto2. + enum Type { + TYPE_DOUBLE = 1, // double, exactly eight bytes on the wire. + TYPE_FLOAT = 2, // float, exactly four bytes on the wire. + TYPE_INT64 = 3, // int64, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT64 if negative + // values are likely. + TYPE_UINT64 = 4, // uint64, varint on the wire. + TYPE_INT32 = 5, // int32, varint on the wire. Negative numbers + // take 10 bytes. Use TYPE_SINT32 if negative + // values are likely. + TYPE_FIXED64 = 6, // uint64, exactly eight bytes on the wire. + TYPE_FIXED32 = 7, // uint32, exactly four bytes on the wire. + TYPE_BOOL = 8, // bool, varint on the wire. + TYPE_STRING = 9, // UTF-8 text. + TYPE_GROUP = 10, // Tag-delimited message. Deprecated. + TYPE_MESSAGE = 11, // Length-delimited message. + + TYPE_BYTES = 12, // Arbitrary byte array. + TYPE_UINT32 = 13, // uint32, varint on the wire + TYPE_ENUM = 14, // Enum, varint on the wire + TYPE_SFIXED32 = 15, // int32, exactly four bytes on the wire + TYPE_SFIXED64 = 16, // int64, exactly eight bytes on the wire + TYPE_SINT32 = 17, // int32, ZigZag-encoded varint on the wire + TYPE_SINT64 = 18, // int64, ZigZag-encoded varint on the wire + + MAX_TYPE = 18, // Constant useful for defining lookup tables + // indexed by Type. + }; + + // Specifies the C++ data type used to represent the field. There is a + // fixed mapping from Type to CppType where each Type maps to exactly one + // CppType. 0 is reserved for errors. + enum CppType { + CPPTYPE_INT32 = 1, // TYPE_INT32, TYPE_SINT32, TYPE_SFIXED32 + CPPTYPE_INT64 = 2, // TYPE_INT64, TYPE_SINT64, TYPE_SFIXED64 + CPPTYPE_UINT32 = 3, // TYPE_UINT32, TYPE_FIXED32 + CPPTYPE_UINT64 = 4, // TYPE_UINT64, TYPE_FIXED64 + CPPTYPE_DOUBLE = 5, // TYPE_DOUBLE + CPPTYPE_FLOAT = 6, // TYPE_FLOAT + CPPTYPE_BOOL = 7, // TYPE_BOOL + CPPTYPE_ENUM = 8, // TYPE_ENUM + CPPTYPE_STRING = 9, // TYPE_STRING, TYPE_BYTES + CPPTYPE_MESSAGE = 10, // TYPE_MESSAGE, TYPE_GROUP + + MAX_CPPTYPE = 10, // Constant useful for defining lookup tables + // indexed by CppType. + }; + + // Identifies whether the field is optional, required, or repeated. 0 is + // reserved for errors. + enum Label { + LABEL_OPTIONAL = 1, // optional + LABEL_REQUIRED = 2, // required + LABEL_REPEATED = 3, // repeated + + MAX_LABEL = 3, // Constant useful for defining lookup tables + // indexed by Label. + }; + + // Valid field numbers are positive integers up to kMaxNumber. + static const int kMaxNumber = (1 << 29) - 1; + + // First field number reserved for the protocol buffer library implementation. + // Users may not declare fields that use reserved numbers. + static const int kFirstReservedNumber = 19000; + // Last field number reserved for the protocol buffer library implementation. + // Users may not declare fields that use reserved numbers. + static const int kLastReservedNumber = 19999; + + const string& name() const; // Name of this field within the message. + const string& full_name() const; // Fully-qualified name of the field. + const FileDescriptor* file() const;// File in which this field was defined. + bool is_extension() const; // Is this an extension field? + int number() const; // Declared tag number. + + // Same as name() except converted to lower-case. This (and especially the + // FindFieldByLowercaseName() method) can be useful when parsing formats + // which prefer to use lowercase naming style. (Although, technically + // field names should be lowercased anyway according to the protobuf style + // guide, so this only makes a difference when dealing with old .proto files + // which do not follow the guide.) + const string& lowercase_name() const; + + // Same as name() except converted to camel-case. In this conversion, any + // time an underscore appears in the name, it is removed and the next + // letter is capitalized. Furthermore, the first letter of the name is + // lower-cased. Examples: + // FooBar -> fooBar + // foo_bar -> fooBar + // fooBar -> fooBar + // This (and especially the FindFieldByCamelcaseName() method) can be useful + // when parsing formats which prefer to use camel-case naming style. + const string& camelcase_name() const; + + Type type() const; // Declared type of this field. + const char* type_name() const; // Name of the declared type. + CppType cpp_type() const; // C++ type of this field. + const char* cpp_type_name() const; // Name of the C++ type. + Label label() const; // optional/required/repeated + + bool is_required() const; // shorthand for label() == LABEL_REQUIRED + bool is_optional() const; // shorthand for label() == LABEL_OPTIONAL + bool is_repeated() const; // shorthand for label() == LABEL_REPEATED + bool is_packable() const; // shorthand for is_repeated() && + // IsTypePackable(type()) + bool is_packed() const; // shorthand for is_packable() && + // options().packed() + + // Index of this field within the message's field array, or the file or + // extension scope's extensions array. + int index() const; + + // Does this field have an explicitly-declared default value? + bool has_default_value() const; + + // Get the field default value if cpp_type() == CPPTYPE_INT32. If no + // explicit default was defined, the default is 0. + int32 default_value_int32() const; + // Get the field default value if cpp_type() == CPPTYPE_INT64. If no + // explicit default was defined, the default is 0. + int64 default_value_int64() const; + // Get the field default value if cpp_type() == CPPTYPE_UINT32. If no + // explicit default was defined, the default is 0. + uint32 default_value_uint32() const; + // Get the field default value if cpp_type() == CPPTYPE_UINT64. If no + // explicit default was defined, the default is 0. + uint64 default_value_uint64() const; + // Get the field default value if cpp_type() == CPPTYPE_FLOAT. If no + // explicit default was defined, the default is 0.0. + float default_value_float() const; + // Get the field default value if cpp_type() == CPPTYPE_DOUBLE. If no + // explicit default was defined, the default is 0.0. + double default_value_double() const; + // Get the field default value if cpp_type() == CPPTYPE_BOOL. If no + // explicit default was defined, the default is false. + bool default_value_bool() const; + // Get the field default value if cpp_type() == CPPTYPE_ENUM. If no + // explicit default was defined, the default is the first value defined + // in the enum type (all enum types are required to have at least one value). + // This never returns NULL. + const EnumValueDescriptor* default_value_enum() const; + // Get the field default value if cpp_type() == CPPTYPE_STRING. If no + // explicit default was defined, the default is the empty string. + const string& default_value_string() const; + + // The Descriptor for the message of which this is a field. For extensions, + // this is the extended type. Never NULL. + const Descriptor* containing_type() const; + + // An extension may be declared within the scope of another message. If this + // field is an extension (is_extension() is true), then extension_scope() + // returns that message, or NULL if the extension was declared at global + // scope. If this is not an extension, extension_scope() is undefined (may + // assert-fail). + const Descriptor* extension_scope() const; + + // If type is TYPE_MESSAGE or TYPE_GROUP, returns a descriptor for the + // message or the group type. Otherwise, undefined. + const Descriptor* message_type() const; + // If type is TYPE_ENUM, returns a descriptor for the enum. Otherwise, + // undefined. + const EnumDescriptor* enum_type() const; + + // EXPERIMENTAL; DO NOT USE. + // If this field is a map field, experimental_map_key() is the field + // that is the key for this map. + // experimental_map_key()->containing_type() is the same as message_type(). + const FieldDescriptor* experimental_map_key() const; + + // Get the FieldOptions for this field. This includes things listed in + // square brackets after the field definition. E.g., the field: + // optional string text = 1 [ctype=CORD]; + // has the "ctype" option set. Allowed options are defined by FieldOptions + // in google/protobuf/descriptor.proto, and any available extensions of that + // message. + const FieldOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(FieldDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Helper method to get the CppType for a particular Type. + static CppType TypeToCppType(Type type); + + // Return true iff [packed = true] is valid for fields of this type. + static inline bool IsTypePackable(Type field_type); + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this field declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef FieldOptions OptionsType; + + // See Descriptor::DebugString(). + void DebugString(int depth, string *contents) const; + + // formats the default value appropriately and returns it as a string. + // Must have a default value to call this. If quote_string_type is true, then + // types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped. + string DefaultValueAsString(bool quote_string_type) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const string* lowercase_name_; + const string* camelcase_name_; + const FileDescriptor* file_; + int number_; + Type type_; + Label label_; + bool is_extension_; + const Descriptor* containing_type_; + const Descriptor* extension_scope_; + const Descriptor* message_type_; + const EnumDescriptor* enum_type_; + const FieldDescriptor* experimental_map_key_; + const FieldOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in + // descriptor.cc and update them to initialize the field. + + bool has_default_value_; + union { + int32 default_value_int32_; + int64 default_value_int64_; + uint32 default_value_uint32_; + uint64 default_value_uint64_; + float default_value_float_; + double default_value_double_; + bool default_value_bool_; + + const EnumValueDescriptor* default_value_enum_; + const string* default_value_string_; + }; + + static const CppType kTypeToCppTypeMap[MAX_TYPE + 1]; + + static const char * const kTypeToName[MAX_TYPE + 1]; + + static const char * const kCppTypeToName[MAX_CPPTYPE + 1]; + + static const char * const kLabelToName[MAX_LABEL + 1]; + + // Must be constructed using DescriptorPool. + FieldDescriptor() {} + friend class DescriptorBuilder; + friend class FileDescriptor; + friend class Descriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor); +}; + +// Describes an enum type defined in a .proto file. To get the EnumDescriptor +// for a generated enum type, call TypeName_descriptor(). Use DescriptorPool +// to construct your own descriptors. +class LIBPROTOBUF_EXPORT EnumDescriptor { + public: + // The name of this enum type in the containing scope. + const string& name() const; + + // The fully-qualified name of the enum type, scope delimited by periods. + const string& full_name() const; + + // Index of this enum within the file or containing message's enum array. + int index() const; + + // The .proto file in which this enum type was defined. Never NULL. + const FileDescriptor* file() const; + + // The number of values for this EnumDescriptor. Guaranteed to be greater + // than zero. + int value_count() const; + // Gets a value by index, where 0 <= index < value_count(). + // These are returned in the order they were defined in the .proto file. + const EnumValueDescriptor* value(int index) const; + + // Looks up a value by name. Returns NULL if no such value exists. + const EnumValueDescriptor* FindValueByName(const string& name) const; + // Looks up a value by number. Returns NULL if no such value exists. If + // multiple values have this number, the first one defined is returned. + const EnumValueDescriptor* FindValueByNumber(int number) const; + + // If this enum type is nested in a message type, this is that message type. + // Otherwise, NULL. + const Descriptor* containing_type() const; + + // Get options for this enum type. These are specified in the .proto file by + // placing lines like "option foo = 1234;" in the enum definition. Allowed + // options are defined by EnumOptions in google/protobuf/descriptor.proto, + // and any available extensions of that message. + const EnumOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(EnumDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef EnumOptions OptionsType; + + // See Descriptor::DebugString(). + void DebugString(int depth, string *contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const FileDescriptor* file_; + const Descriptor* containing_type_; + const EnumOptions* options_; + + // True if this is a placeholder for an unknown type. + bool is_placeholder_; + // True if this is a placeholder and the type name wasn't fully-qualified. + bool is_unqualified_placeholder_; + + int value_count_; + EnumValueDescriptor* values_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + EnumDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + friend class FieldDescriptor; + friend class EnumValueDescriptor; + friend class FileDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor); +}; + +// Describes an individual enum constant of a particular type. To get the +// EnumValueDescriptor for a given enum value, first get the EnumDescriptor +// for its type, then use EnumDescriptor::FindValueByName() or +// EnumDescriptor::FindValueByNumber(). Use DescriptorPool to construct +// your own descriptors. +class LIBPROTOBUF_EXPORT EnumValueDescriptor { + public: + const string& name() const; // Name of this enum constant. + int index() const; // Index within the enums's Descriptor. + int number() const; // Numeric value of this enum constant. + + // The full_name of an enum value is a sibling symbol of the enum type. + // e.g. the full name of FieldDescriptorProto::TYPE_INT32 is actually + // "google.protobuf.FieldDescriptorProto.TYPE_INT32", NOT + // "google.protobuf.FieldDescriptorProto.Type.TYPE_INT32". This is to conform + // with C++ scoping rules for enums. + const string& full_name() const; + + // The type of this value. Never NULL. + const EnumDescriptor* type() const; + + // Get options for this enum value. These are specified in the .proto file + // by adding text like "[foo = 1234]" after an enum value definition. + // Allowed options are defined by EnumValueOptions in + // google/protobuf/descriptor.proto, and any available extensions of that + // message. + const EnumValueOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(EnumValueDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this enum value declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef EnumValueOptions OptionsType; + + // See Descriptor::DebugString(). + void DebugString(int depth, string *contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + int number_; + const EnumDescriptor* type_; + const EnumValueOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() + // in descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + EnumValueDescriptor() {} + friend class DescriptorBuilder; + friend class EnumDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor); +}; + +// Describes an RPC service. To get the ServiceDescriptor for a service, +// call Service::GetDescriptor(). Generated service classes also have a +// static method called descriptor() which returns the type's +// ServiceDescriptor. Use DescriptorPool to construct your own descriptors. +class LIBPROTOBUF_EXPORT ServiceDescriptor { + public: + // The name of the service, not including its containing scope. + const string& name() const; + // The fully-qualified name of the service, scope delimited by periods. + const string& full_name() const; + // Index of this service within the file's services array. + int index() const; + + // The .proto file in which this service was defined. Never NULL. + const FileDescriptor* file() const; + + // Get options for this service type. These are specified in the .proto file + // by placing lines like "option foo = 1234;" in the service definition. + // Allowed options are defined by ServiceOptions in + // google/protobuf/descriptor.proto, and any available extensions of that + // message. + const ServiceOptions& options() const; + + // The number of methods this service defines. + int method_count() const; + // Gets a MethodDescriptor by index, where 0 <= index < method_count(). + // These are returned in the order they were defined in the .proto file. + const MethodDescriptor* method(int index) const; + + // Look up a MethodDescriptor by name. + const MethodDescriptor* FindMethodByName(const string& name) const; + // See Descriptor::CopyTo(). + void CopyTo(ServiceDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this service declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef ServiceOptions OptionsType; + + // See Descriptor::DebugString(). + void DebugString(string *contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const FileDescriptor* file_; + const ServiceOptions* options_; + int method_count_; + MethodDescriptor* methods_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + ServiceDescriptor() {} + friend class DescriptorBuilder; + friend class FileDescriptor; + friend class MethodDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor); +}; + +// Describes an individual service method. To obtain a MethodDescriptor given +// a service, first get its ServiceDescriptor, then call +// ServiceDescriptor::FindMethodByName(). Use DescriptorPool to construct your +// own descriptors. +class LIBPROTOBUF_EXPORT MethodDescriptor { + public: + // Name of this method, not including containing scope. + const string& name() const; + // The fully-qualified name of the method, scope delimited by periods. + const string& full_name() const; + // Index within the service's Descriptor. + int index() const; + + // Gets the service to which this method belongs. Never NULL. + const ServiceDescriptor* service() const; + + // Gets the type of protocol message which this method accepts as input. + const Descriptor* input_type() const; + // Gets the type of protocol message which this message produces as output. + const Descriptor* output_type() const; + + // Get options for this method. These are specified in the .proto file by + // placing lines like "option foo = 1234;" in curly-braces after a method + // declaration. Allowed options are defined by MethodOptions in + // google/protobuf/descriptor.proto, and any available extensions of that + // message. + const MethodOptions& options() const; + + // See Descriptor::CopyTo(). + void CopyTo(MethodDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this method declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + typedef MethodOptions OptionsType; + + // See Descriptor::DebugString(). + void DebugString(int depth, string *contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const ServiceDescriptor* service_; + const Descriptor* input_type_; + const Descriptor* output_type_; + const MethodOptions* options_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in + // descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + MethodDescriptor() {} + friend class DescriptorBuilder; + friend class ServiceDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor); +}; + + +// Describes a whole .proto file. To get the FileDescriptor for a compiled-in +// file, get the descriptor for something defined in that file and call +// descriptor->file(). Use DescriptorPool to construct your own descriptors. +class LIBPROTOBUF_EXPORT FileDescriptor { + public: + // The filename, relative to the source tree. + // e.g. "google/protobuf/descriptor.proto" + const string& name() const; + + // The package, e.g. "google.protobuf.compiler". + const string& package() const; + + // The DescriptorPool in which this FileDescriptor and all its contents were + // allocated. Never NULL. + const DescriptorPool* pool() const; + + // The number of files imported by this one. + int dependency_count() const; + // Gets an imported file by index, where 0 <= index < dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* dependency(int index) const; + + // The number of files public imported by this one. + // The public dependency list is a subset of the dependency list. + int public_dependency_count() const; + // Gets a public imported file by index, where 0 <= index < + // public_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* public_dependency(int index) const; + + // The number of files that are imported for weak fields. + // The weak dependency list is a subset of the dependency list. + int weak_dependency_count() const; + // Gets a weak imported file by index, where 0 <= index < + // weak_dependency_count(). + // These are returned in the order they were defined in the .proto file. + const FileDescriptor* weak_dependency(int index) const; + + // Number of top-level message types defined in this file. (This does not + // include nested types.) + int message_type_count() const; + // Gets a top-level message type, where 0 <= index < message_type_count(). + // These are returned in the order they were defined in the .proto file. + const Descriptor* message_type(int index) const; + + // Number of top-level enum types defined in this file. (This does not + // include nested types.) + int enum_type_count() const; + // Gets a top-level enum type, where 0 <= index < enum_type_count(). + // These are returned in the order they were defined in the .proto file. + const EnumDescriptor* enum_type(int index) const; + + // Number of services defined in this file. + int service_count() const; + // Gets a service, where 0 <= index < service_count(). + // These are returned in the order they were defined in the .proto file. + const ServiceDescriptor* service(int index) const; + + // Number of extensions defined at file scope. (This does not include + // extensions nested within message types.) + int extension_count() const; + // Gets an extension's descriptor, where 0 <= index < extension_count(). + // These are returned in the order they were defined in the .proto file. + const FieldDescriptor* extension(int index) const; + + // Get options for this file. These are specified in the .proto file by + // placing lines like "option foo = 1234;" at the top level, outside of any + // other definitions. Allowed options are defined by FileOptions in + // google/protobuf/descriptor.proto, and any available extensions of that + // message. + const FileOptions& options() const; + + // Find a top-level message type by name. Returns NULL if not found. + const Descriptor* FindMessageTypeByName(const string& name) const; + // Find a top-level enum type by name. Returns NULL if not found. + const EnumDescriptor* FindEnumTypeByName(const string& name) const; + // Find an enum value defined in any top-level enum by name. Returns NULL if + // not found. + const EnumValueDescriptor* FindEnumValueByName(const string& name) const; + // Find a service definition by name. Returns NULL if not found. + const ServiceDescriptor* FindServiceByName(const string& name) const; + // Find a top-level extension definition by name. Returns NULL if not found. + const FieldDescriptor* FindExtensionByName(const string& name) const; + // Similar to FindExtensionByName(), but searches by lowercased-name. See + // Descriptor::FindFieldByLowercaseName(). + const FieldDescriptor* FindExtensionByLowercaseName(const string& name) const; + // Similar to FindExtensionByName(), but searches by camelcased-name. See + // Descriptor::FindFieldByCamelcaseName(). + const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + + // See Descriptor::CopyTo(). + // Notes: + // - This method does NOT copy source code information since it is relatively + // large and rarely needed. See CopySourceCodeInfoTo() below. + void CopyTo(FileDescriptorProto* proto) const; + // Write the source code information of this FileDescriptor into the given + // FileDescriptorProto. See CopyTo() above. + void CopySourceCodeInfoTo(FileDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + private: + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of the declaration or declaration-part denoted by |path|. + // Returns false and leaves |*out_location| unchanged iff location + // information was not available. (See SourceCodeInfo for + // description of path encoding.) + bool GetSourceLocation(const vector& path, + SourceLocation* out_location) const; + + typedef FileOptions OptionsType; + + const string* name_; + const string* package_; + const DescriptorPool* pool_; + int dependency_count_; + const FileDescriptor** dependencies_; + int public_dependency_count_; + int* public_dependencies_; + int weak_dependency_count_; + int* weak_dependencies_; + int message_type_count_; + Descriptor* message_types_; + int enum_type_count_; + EnumDescriptor* enum_types_; + int service_count_; + ServiceDescriptor* services_; + int extension_count_; + FieldDescriptor* extensions_; + const FileOptions* options_; + + const FileDescriptorTables* tables_; + const SourceCodeInfo* source_code_info_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() in + // descriptor.cc and update them to initialize the field. + + FileDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + friend class FieldDescriptor; + friend class EnumDescriptor; + friend class EnumValueDescriptor; + friend class MethodDescriptor; + friend class ServiceDescriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor); +}; + +// =================================================================== + +// Used to construct descriptors. +// +// Normally you won't want to build your own descriptors. Message classes +// constructed by the protocol compiler will provide them for you. However, +// if you are implementing Message on your own, or if you are writing a +// program which can operate on totally arbitrary types and needs to load +// them from some sort of database, you might need to. +// +// Since Descriptors are composed of a whole lot of cross-linked bits of +// data that would be a pain to put together manually, the +// DescriptorPool class is provided to make the process easier. It can +// take a FileDescriptorProto (defined in descriptor.proto), validate it, +// and convert it to a set of nicely cross-linked Descriptors. +// +// DescriptorPool also helps with memory management. Descriptors are +// composed of many objects containing static data and pointers to each +// other. In all likelihood, when it comes time to delete this data, +// you'll want to delete it all at once. In fact, it is not uncommon to +// have a whole pool of descriptors all cross-linked with each other which +// you wish to delete all at once. This class represents such a pool, and +// handles the memory management for you. +// +// You can also search for descriptors within a DescriptorPool by name, and +// extensions by number. +class LIBPROTOBUF_EXPORT DescriptorPool { + public: + // Create a normal, empty DescriptorPool. + DescriptorPool(); + + // Constructs a DescriptorPool that, when it can't find something among the + // descriptors already in the pool, looks for it in the given + // DescriptorDatabase. + // Notes: + // - If a DescriptorPool is constructed this way, its BuildFile*() methods + // must not be called (they will assert-fail). The only way to populate + // the pool with descriptors is to call the Find*By*() methods. + // - The Find*By*() methods may block the calling thread if the + // DescriptorDatabase blocks. This in turn means that parsing messages + // may block if they need to look up extensions. + // - The Find*By*() methods will use mutexes for thread-safety, thus making + // them slower even when they don't have to fall back to the database. + // In fact, even the Find*By*() methods of descriptor objects owned by + // this pool will be slower, since they will have to obtain locks too. + // - An ErrorCollector may optionally be given to collect validation errors + // in files loaded from the database. If not given, errors will be printed + // to GOOGLE_LOG(ERROR). Remember that files are built on-demand, so this + // ErrorCollector may be called from any thread that calls one of the + // Find*By*() methods. + class ErrorCollector; + explicit DescriptorPool(DescriptorDatabase* fallback_database, + ErrorCollector* error_collector = NULL); + + ~DescriptorPool(); + + // Get a pointer to the generated pool. Generated protocol message classes + // which are compiled into the binary will allocate their descriptors in + // this pool. Do not add your own descriptors to this pool. + static const DescriptorPool* generated_pool(); + + // Find a FileDescriptor in the pool by file name. Returns NULL if not + // found. + const FileDescriptor* FindFileByName(const string& name) const; + + // Find the FileDescriptor in the pool which defines the given symbol. + // If any of the Find*ByName() methods below would succeed, then this is + // equivalent to calling that method and calling the result's file() method. + // Otherwise this returns NULL. + const FileDescriptor* FindFileContainingSymbol( + const string& symbol_name) const; + + // Looking up descriptors ------------------------------------------ + // These find descriptors by fully-qualified name. These will find both + // top-level descriptors and nested descriptors. They return NULL if not + // found. + + const Descriptor* FindMessageTypeByName(const string& name) const; + const FieldDescriptor* FindFieldByName(const string& name) const; + const FieldDescriptor* FindExtensionByName(const string& name) const; + const EnumDescriptor* FindEnumTypeByName(const string& name) const; + const EnumValueDescriptor* FindEnumValueByName(const string& name) const; + const ServiceDescriptor* FindServiceByName(const string& name) const; + const MethodDescriptor* FindMethodByName(const string& name) const; + + // Finds an extension of the given type by number. The extendee must be + // a member of this DescriptorPool or one of its underlays. + const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee, + int number) const; + + // Finds extensions of extendee. The extensions will be appended to + // out in an undefined order. Only extensions defined directly in + // this DescriptorPool or one of its underlays are guaranteed to be + // found: extensions defined in the fallback database might not be found + // depending on the database implementation. + void FindAllExtensions(const Descriptor* extendee, + vector* out) const; + + // Building descriptors -------------------------------------------- + + // When converting a FileDescriptorProto to a FileDescriptor, various + // errors might be detected in the input. The caller may handle these + // programmatically by implementing an ErrorCollector. + class LIBPROTOBUF_EXPORT ErrorCollector { + public: + inline ErrorCollector() {} + virtual ~ErrorCollector(); + + // These constants specify what exact part of the construct is broken. + // This is useful e.g. for mapping the error back to an exact location + // in a .proto file. + enum ErrorLocation { + NAME, // the symbol name, or the package name for files + NUMBER, // field or extension range number + TYPE, // field type + EXTENDEE, // field extendee + DEFAULT_VALUE, // field default value + INPUT_TYPE, // method input type + OUTPUT_TYPE, // method output type + OPTION_NAME, // name in assignment + OPTION_VALUE, // value in option assignment + OTHER // some other problem + }; + + // Reports an error in the FileDescriptorProto. + virtual void AddError( + const string& filename, // File name in which the error occurred. + const string& element_name, // Full name of the erroneous element. + const Message* descriptor, // Descriptor of the erroneous element. + ErrorLocation location, // One of the location constants, above. + const string& message // Human-readable error message. + ) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); + }; + + // Convert the FileDescriptorProto to real descriptors and place them in + // this DescriptorPool. All dependencies of the file must already be in + // the pool. Returns the resulting FileDescriptor, or NULL if there were + // problems with the input (e.g. the message was invalid, or dependencies + // were missing). Details about the errors are written to GOOGLE_LOG(ERROR). + const FileDescriptor* BuildFile(const FileDescriptorProto& proto); + + // Same as BuildFile() except errors are sent to the given ErrorCollector. + const FileDescriptor* BuildFileCollectingErrors( + const FileDescriptorProto& proto, + ErrorCollector* error_collector); + + // By default, it is an error if a FileDescriptorProto contains references + // to types or other files that are not found in the DescriptorPool (or its + // backing DescriptorDatabase, if any). If you call + // AllowUnknownDependencies(), however, then unknown types and files + // will be replaced by placeholder descriptors. This can allow you to + // perform some useful operations with a .proto file even if you do not + // have access to other .proto files on which it depends. However, some + // heuristics must be used to fill in the gaps in information, and these + // can lead to descriptors which are inaccurate. For example, the + // DescriptorPool may be forced to guess whether an unknown type is a message + // or an enum, as well as what package it resides in. Furthermore, + // placeholder types will not be discoverable via FindMessageTypeByName() + // and similar methods, which could confuse some descriptor-based algorithms. + // Generally, the results of this option should only be relied upon for + // debugging purposes. + void AllowUnknownDependencies() { allow_unknown_ = true; } + + // Internal stuff -------------------------------------------------- + // These methods MUST NOT be called from outside the proto2 library. + // These methods may contain hidden pitfalls and may be removed in a + // future library version. + + // Create a DescriptorPool which is overlaid on top of some other pool. + // If you search for a descriptor in the overlay and it is not found, the + // underlay will be searched as a backup. If the underlay has its own + // underlay, that will be searched next, and so on. This also means that + // files built in the overlay will be cross-linked with the underlay's + // descriptors if necessary. The underlay remains property of the caller; + // it must remain valid for the lifetime of the newly-constructed pool. + // + // Example: Say you want to parse a .proto file at runtime in order to use + // its type with a DynamicMessage. Say this .proto file has dependencies, + // but you know that all the dependencies will be things that are already + // compiled into the binary. For ease of use, you'd like to load the types + // right out of generated_pool() rather than have to parse redundant copies + // of all these .protos and runtime. But, you don't want to add the parsed + // types directly into generated_pool(): this is not allowed, and would be + // bad design anyway. So, instead, you could use generated_pool() as an + // underlay for a new DescriptorPool in which you add only the new file. + // + // WARNING: Use of underlays can lead to many subtle gotchas. Instead, + // try to formulate what you want to do in terms of DescriptorDatabases. + explicit DescriptorPool(const DescriptorPool* underlay); + + // Called by generated classes at init time to add their descriptors to + // generated_pool. Do NOT call this in your own code! filename must be a + // permanent string (e.g. a string literal). + static void InternalAddGeneratedFile( + const void* encoded_file_descriptor, int size); + + + // For internal use only: Gets a non-const pointer to the generated pool. + // This is called at static-initialization time only, so thread-safety is + // not a concern. If both an underlay and a fallback database are present, + // the underlay takes precedence. + static DescriptorPool* internal_generated_pool(); + + // For internal use only: Changes the behavior of BuildFile() such that it + // allows the file to make reference to message types declared in other files + // which it did not officially declare as dependencies. + void InternalDontEnforceDependencies(); + + // For internal use only. + void internal_set_underlay(const DescriptorPool* underlay) { + underlay_ = underlay; + } + + // For internal (unit test) use only: Returns true if a FileDescriptor has + // been constructed for the given file, false otherwise. Useful for testing + // lazy descriptor initialization behavior. + bool InternalIsFileLoaded(const string& filename) const; + + private: + friend class Descriptor; + friend class FieldDescriptor; + friend class EnumDescriptor; + friend class ServiceDescriptor; + friend class FileDescriptor; + friend class DescriptorBuilder; + + // Return true if the given name is a sub-symbol of any non-package + // descriptor that already exists in the descriptor pool. (The full + // definition of such types is already known.) + bool IsSubSymbolOfBuiltType(const string& name) const; + + // Tries to find something in the fallback database and link in the + // corresponding proto file. Returns true if successful, in which case + // the caller should search for the thing again. These are declared + // const because they are called by (semantically) const methods. + bool TryFindFileInFallbackDatabase(const string& name) const; + bool TryFindSymbolInFallbackDatabase(const string& name) const; + bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type, + int field_number) const; + + // Like BuildFile() but called internally when the file has been loaded from + // fallback_database_. Declared const because it is called by (semantically) + // const methods. + const FileDescriptor* BuildFileFromDatabase( + const FileDescriptorProto& proto) const; + + // If fallback_database_ is NULL, this is NULL. Otherwise, this is a mutex + // which must be locked while accessing tables_. + Mutex* mutex_; + + // See constructor. + DescriptorDatabase* fallback_database_; + ErrorCollector* default_error_collector_; + const DescriptorPool* underlay_; + + // This class contains a lot of hash maps with complicated types that + // we'd like to keep out of the header. + class Tables; + scoped_ptr tables_; + + bool enforce_dependencies_; + bool allow_unknown_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); +}; + +// inline methods ==================================================== + +// These macros makes this repetitive code more readable. +#define PROTOBUF_DEFINE_ACCESSOR(CLASS, FIELD, TYPE) \ + inline TYPE CLASS::FIELD() const { return FIELD##_; } + +// Strings fields are stored as pointers but returned as const references. +#define PROTOBUF_DEFINE_STRING_ACCESSOR(CLASS, FIELD) \ + inline const string& CLASS::FIELD() const { return *FIELD##_; } + +// Arrays take an index parameter, obviously. +#define PROTOBUF_DEFINE_ARRAY_ACCESSOR(CLASS, FIELD, TYPE) \ + inline TYPE CLASS::FIELD(int index) const { return FIELD##s_ + index; } + +#define PROTOBUF_DEFINE_OPTIONS_ACCESSOR(CLASS, TYPE) \ + inline const TYPE& CLASS::options() const { return *options_; } + +PROTOBUF_DEFINE_STRING_ACCESSOR(Descriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(Descriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int) + +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, field, const FieldDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, nested_type, const Descriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, enum_type, const EnumDescriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_range_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, extension_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, + const Descriptor::ExtensionRange*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, + const FieldDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions) + +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name) +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, lowercase_name) +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, camelcase_name) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, number, int) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, type, FieldDescriptor::Type) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, label, FieldDescriptor::Label) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, experimental_map_key, + const FieldDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int64 , int64 ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint32, uint32) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_uint64, uint64) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_float , float ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_double, double) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_bool , bool ) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_enum, + const EnumValueDescriptor*) +PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) + +PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value, + const EnumValueDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions) + +PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int) +PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumValueDescriptor, EnumValueOptions) + +PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(ServiceDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method, + const MethodDescriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions) + +PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions) +PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, public_dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, weak_dependency_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int) +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions) + +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, service, + const ServiceDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension, + const FieldDescriptor*) + +#undef PROTOBUF_DEFINE_ACCESSOR +#undef PROTOBUF_DEFINE_STRING_ACCESSOR +#undef PROTOBUF_DEFINE_ARRAY_ACCESSOR + +// A few accessors differ from the macros... + +inline bool FieldDescriptor::is_required() const { + return label() == LABEL_REQUIRED; +} + +inline bool FieldDescriptor::is_optional() const { + return label() == LABEL_OPTIONAL; +} + +inline bool FieldDescriptor::is_repeated() const { + return label() == LABEL_REPEATED; +} + +inline bool FieldDescriptor::is_packable() const { + return is_repeated() && IsTypePackable(type()); +} + +// To save space, index() is computed by looking at the descriptor's position +// in the parent's array of children. +inline int FieldDescriptor::index() const { + if (!is_extension_) { + return this - containing_type_->fields_; + } else if (extension_scope_ != NULL) { + return this - extension_scope_->extensions_; + } else { + return this - file_->extensions_; + } +} + +inline int Descriptor::index() const { + if (containing_type_ == NULL) { + return this - file_->message_types_; + } else { + return this - containing_type_->nested_types_; + } +} + +inline int EnumDescriptor::index() const { + if (containing_type_ == NULL) { + return this - file_->enum_types_; + } else { + return this - containing_type_->enum_types_; + } +} + +inline int EnumValueDescriptor::index() const { + return this - type_->values_; +} + +inline int ServiceDescriptor::index() const { + return this - file_->services_; +} + +inline int MethodDescriptor::index() const { + return this - service_->methods_; +} + +inline const char* FieldDescriptor::type_name() const { + return kTypeToName[type_]; +} + +inline FieldDescriptor::CppType FieldDescriptor::cpp_type() const { + return kTypeToCppTypeMap[type_]; +} + +inline const char* FieldDescriptor::cpp_type_name() const { + return kCppTypeToName[kTypeToCppTypeMap[type_]]; +} + +inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) { + return kTypeToCppTypeMap[type]; +} + +inline bool FieldDescriptor::IsTypePackable(Type field_type) { + return (field_type != FieldDescriptor::TYPE_STRING && + field_type != FieldDescriptor::TYPE_GROUP && + field_type != FieldDescriptor::TYPE_MESSAGE && + field_type != FieldDescriptor::TYPE_BYTES); +} + +inline const FileDescriptor* FileDescriptor::dependency(int index) const { + return dependencies_[index]; +} + +inline const FileDescriptor* FileDescriptor::public_dependency( + int index) const { + return dependencies_[public_dependencies_[index]]; +} + +inline const FileDescriptor* FileDescriptor::weak_dependency( + int index) const { + return dependencies_[weak_dependencies_[index]]; +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.cc new file mode 100644 index 000000000..65379f4d4 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.cc @@ -0,0 +1,8146 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto + +#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION +#include "google/protobuf/descriptor.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { + +namespace { + +const ::google::protobuf::Descriptor* FileDescriptorSet_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FileDescriptorSet_reflection_ = NULL; +const ::google::protobuf::Descriptor* FileDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FileDescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* DescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + DescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + DescriptorProto_ExtensionRange_reflection_ = NULL; +const ::google::protobuf::Descriptor* FieldDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FieldDescriptorProto_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor_ = NULL; +const ::google::protobuf::Descriptor* EnumDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EnumDescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* EnumValueDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EnumValueDescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* ServiceDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ServiceDescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* MethodDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + MethodDescriptorProto_reflection_ = NULL; +const ::google::protobuf::Descriptor* FileOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FileOptions_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor_ = NULL; +const ::google::protobuf::Descriptor* MessageOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + MessageOptions_reflection_ = NULL; +const ::google::protobuf::Descriptor* FieldOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + FieldOptions_reflection_ = NULL; +const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor_ = NULL; +const ::google::protobuf::Descriptor* EnumOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EnumOptions_reflection_ = NULL; +const ::google::protobuf::Descriptor* EnumValueOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + EnumValueOptions_reflection_ = NULL; +const ::google::protobuf::Descriptor* ServiceOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + ServiceOptions_reflection_ = NULL; +const ::google::protobuf::Descriptor* MethodOptions_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + MethodOptions_reflection_ = NULL; +const ::google::protobuf::Descriptor* UninterpretedOption_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + UninterpretedOption_reflection_ = NULL; +const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + UninterpretedOption_NamePart_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_Location_reflection_ = NULL; + +} // namespace + + +void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { + protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + const ::google::protobuf::FileDescriptor* file = + ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( + "google/protobuf/descriptor.proto"); + GOOGLE_CHECK(file != NULL); + FileDescriptorSet_descriptor_ = file->message_type(0); + static const int FileDescriptorSet_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, file_), + }; + FileDescriptorSet_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FileDescriptorSet_descriptor_, + FileDescriptorSet::default_instance_, + FileDescriptorSet_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FileDescriptorSet)); + FileDescriptorProto_descriptor_ = file->message_type(1); + static const int FileDescriptorProto_offsets_[11] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, public_dependency_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, weak_dependency_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, message_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, enum_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_), + }; + FileDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FileDescriptorProto_descriptor_, + FileDescriptorProto::default_instance_, + FileDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FileDescriptorProto)); + DescriptorProto_descriptor_ = file->message_type(2); + static const int DescriptorProto_offsets_[7] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, nested_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, enum_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_), + }; + DescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + DescriptorProto_descriptor_, + DescriptorProto::default_instance_, + DescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(DescriptorProto)); + DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0); + static const int DescriptorProto_ExtensionRange_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_), + }; + DescriptorProto_ExtensionRange_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + DescriptorProto_ExtensionRange_descriptor_, + DescriptorProto_ExtensionRange::default_instance_, + DescriptorProto_ExtensionRange_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(DescriptorProto_ExtensionRange)); + FieldDescriptorProto_descriptor_ = file->message_type(3); + static const int FieldDescriptorProto_offsets_[8] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_), + }; + FieldDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FieldDescriptorProto_descriptor_, + FieldDescriptorProto::default_instance_, + FieldDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FieldDescriptorProto)); + FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0); + FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1); + EnumDescriptorProto_descriptor_ = file->message_type(4); + static const int EnumDescriptorProto_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, options_), + }; + EnumDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EnumDescriptorProto_descriptor_, + EnumDescriptorProto::default_instance_, + EnumDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EnumDescriptorProto)); + EnumValueDescriptorProto_descriptor_ = file->message_type(5); + static const int EnumValueDescriptorProto_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, options_), + }; + EnumValueDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EnumValueDescriptorProto_descriptor_, + EnumValueDescriptorProto::default_instance_, + EnumValueDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EnumValueDescriptorProto)); + ServiceDescriptorProto_descriptor_ = file->message_type(6); + static const int ServiceDescriptorProto_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, options_), + }; + ServiceDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ServiceDescriptorProto_descriptor_, + ServiceDescriptorProto::default_instance_, + ServiceDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ServiceDescriptorProto)); + MethodDescriptorProto_descriptor_ = file->message_type(7); + static const int MethodDescriptorProto_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, output_type_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, options_), + }; + MethodDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + MethodDescriptorProto_descriptor_, + MethodDescriptorProto::default_instance_, + MethodDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(MethodDescriptorProto)); + FileOptions_descriptor_ = file->message_type(8); + static const int FileOptions_offsets_[10] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), + }; + FileOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FileOptions_descriptor_, + FileOptions::default_instance_, + FileOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FileOptions)); + FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0); + MessageOptions_descriptor_ = file->message_type(9); + static const int MessageOptions_offsets_[3] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_), + }; + MessageOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + MessageOptions_descriptor_, + MessageOptions::default_instance_, + MessageOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(MessageOptions)); + FieldOptions_descriptor_ = file->message_type(10); + static const int FieldOptions_offsets_[7] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_), + }; + FieldOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + FieldOptions_descriptor_, + FieldOptions::default_instance_, + FieldOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(FieldOptions)); + FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0); + EnumOptions_descriptor_ = file->message_type(11); + static const int EnumOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_), + }; + EnumOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EnumOptions_descriptor_, + EnumOptions::default_instance_, + EnumOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EnumOptions)); + EnumValueOptions_descriptor_ = file->message_type(12); + static const int EnumValueOptions_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_), + }; + EnumValueOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + EnumValueOptions_descriptor_, + EnumValueOptions::default_instance_, + EnumValueOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(EnumValueOptions)); + ServiceOptions_descriptor_ = file->message_type(13); + static const int ServiceOptions_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_), + }; + ServiceOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + ServiceOptions_descriptor_, + ServiceOptions::default_instance_, + ServiceOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(ServiceOptions)); + MethodOptions_descriptor_ = file->message_type(14); + static const int MethodOptions_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_), + }; + MethodOptions_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + MethodOptions_descriptor_, + MethodOptions::default_instance_, + MethodOptions_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _unknown_fields_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_), + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(MethodOptions)); + UninterpretedOption_descriptor_ = file->message_type(15); + static const int UninterpretedOption_offsets_[7] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_), + }; + UninterpretedOption_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + UninterpretedOption_descriptor_, + UninterpretedOption::default_instance_, + UninterpretedOption_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(UninterpretedOption)); + UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0); + static const int UninterpretedOption_NamePart_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, is_extension_), + }; + UninterpretedOption_NamePart_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + UninterpretedOption_NamePart_descriptor_, + UninterpretedOption_NamePart::default_instance_, + UninterpretedOption_NamePart_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(UninterpretedOption_NamePart)); + SourceCodeInfo_descriptor_ = file->message_type(16); + static const int SourceCodeInfo_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), + }; + SourceCodeInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_descriptor_, + SourceCodeInfo::default_instance_, + SourceCodeInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo)); + SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0); + static const int SourceCodeInfo_Location_offsets_[4] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_), + }; + SourceCodeInfo_Location_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_Location_descriptor_, + SourceCodeInfo_Location::default_instance_, + SourceCodeInfo_Location_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo_Location)); +} + +namespace { + +GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); +inline void protobuf_AssignDescriptorsOnce() { + ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, + &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto); +} + +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FileDescriptorSet_descriptor_, &FileDescriptorSet::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FileDescriptorProto_descriptor_, &FileDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + DescriptorProto_descriptor_, &DescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EnumDescriptorProto_descriptor_, &EnumDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EnumValueDescriptorProto_descriptor_, &EnumValueDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ServiceDescriptorProto_descriptor_, &ServiceDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + MethodDescriptorProto_descriptor_, &MethodDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FileOptions_descriptor_, &FileOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + MessageOptions_descriptor_, &MessageOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + FieldOptions_descriptor_, &FieldOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EnumOptions_descriptor_, &EnumOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + EnumValueOptions_descriptor_, &EnumValueOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + ServiceOptions_descriptor_, &ServiceOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + MethodOptions_descriptor_, &MethodOptions::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + UninterpretedOption_descriptor_, &UninterpretedOption::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance()); +} + +} // namespace + +void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { + delete FileDescriptorSet::default_instance_; + delete FileDescriptorSet_reflection_; + delete FileDescriptorProto::default_instance_; + delete FileDescriptorProto_reflection_; + delete DescriptorProto::default_instance_; + delete DescriptorProto_reflection_; + delete DescriptorProto_ExtensionRange::default_instance_; + delete DescriptorProto_ExtensionRange_reflection_; + delete FieldDescriptorProto::default_instance_; + delete FieldDescriptorProto_reflection_; + delete EnumDescriptorProto::default_instance_; + delete EnumDescriptorProto_reflection_; + delete EnumValueDescriptorProto::default_instance_; + delete EnumValueDescriptorProto_reflection_; + delete ServiceDescriptorProto::default_instance_; + delete ServiceDescriptorProto_reflection_; + delete MethodDescriptorProto::default_instance_; + delete MethodDescriptorProto_reflection_; + delete FileOptions::default_instance_; + delete FileOptions_reflection_; + delete MessageOptions::default_instance_; + delete MessageOptions_reflection_; + delete FieldOptions::default_instance_; + delete FieldOptions_reflection_; + delete EnumOptions::default_instance_; + delete EnumOptions_reflection_; + delete EnumValueOptions::default_instance_; + delete EnumValueOptions_reflection_; + delete ServiceOptions::default_instance_; + delete ServiceOptions_reflection_; + delete MethodOptions::default_instance_; + delete MethodOptions_reflection_; + delete UninterpretedOption::default_instance_; + delete UninterpretedOption_reflection_; + delete UninterpretedOption_NamePart::default_instance_; + delete UninterpretedOption_NamePart_reflection_; + delete SourceCodeInfo::default_instance_; + delete SourceCodeInfo_reflection_; + delete SourceCodeInfo_Location::default_instance_; + delete SourceCodeInfo_Location_reflection_; +} + +void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { + static bool already_here = false; + if (already_here) return; + already_here = true; + GOOGLE_PROTOBUF_VERIFY_VERSION; + + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + "\n google/protobuf/descriptor.proto\022\017goog" + "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" + "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" + "roto\"\313\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" + "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen" + "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf." + "ServiceDescriptorProto\0228\n\textension\030\007 \003(" + "\0132%.google.protobuf.FieldDescriptorProto" + "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" + "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" + "le.protobuf.SourceCodeInfo\"\251\003\n\017Descripto" + "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go" + "ogle.protobuf.FieldDescriptorProto\0228\n\tex" + "tension\030\006 \003(\0132%.google.protobuf.FieldDes" + "criptorProto\0225\n\013nested_type\030\003 \003(\0132 .goog" + "le.protobuf.DescriptorProto\0227\n\tenum_type" + "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP" + "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p" + "rotobuf.DescriptorProto.ExtensionRange\0220" + "\n\007options\030\007 \001(\0132\037.google.protobuf.Messag" + "eOptions\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001(" + "\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescriptorProto\022" + "\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004" + " \001(\0162+.google.protobuf.FieldDescriptorPr" + "oto.Label\0228\n\004type\030\005 \001(\0162*.google.protobu" + "f.FieldDescriptorProto.Type\022\021\n\ttype_name" + "\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_valu" + "e\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.google.protob" + "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020" + "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP" + "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED" + "64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n" + "\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_M" + "ESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020" + "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT" + "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_" + "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n" + "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001" + "\n\023EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005v" + "alue\030\002 \003(\0132).google.protobuf.EnumValueDe" + "scriptorProto\022-\n\007options\030\003 \001(\0132\034.google." + "protobuf.EnumOptions\"l\n\030EnumValueDescrip" + "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" + "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" + "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" + "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" + "tobuf.MethodDescriptorProto\0220\n\007options\030\003" + " \001(\0132\037.google.protobuf.ServiceOptions\"\177\n" + "\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\n" + "input_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n" + "\007options\030\004 \001(\0132\036.google.protobuf.MethodO" + "ptions\"\351\003\n\013FileOptions\022\024\n\014java_package\030\001" + " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja" + "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g" + "enerate_equals_and_hash\030\024 \001(\010:\005false\022F\n\014" + "optimize_for\030\t \001(\0162).google.protobuf.Fil" + "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa" + "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f" + "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" + "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022C" + "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" + "rotobuf.UninterpretedOption\":\n\014OptimizeM" + "ode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RU" + "NTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n" + "\027message_set_wire_format\030\001 \001(\010:\005false\022.\n" + "\037no_standard_descriptor_accessor\030\002 \001(\010:\005" + "false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g" + "oogle.protobuf.UninterpretedOption*\t\010\350\007\020" + "\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#." + "google.protobuf.FieldOptions.CType:\006STRI" + "NG\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022" + "\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experiment" + "al_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(\010:\005false\022C\n" + "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr" + "otobuf.UninterpretedOption\"/\n\005CType\022\n\n\006S" + "TRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007" + "\020\200\200\200\200\002\"x\n\013EnumOptions\022\031\n\013allow_alias\030\002 \001" + "(\010:\004true\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption*\t\010" + "\350\007\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterp" + "reted_option\030\347\007 \003(\0132$.google.protobuf.Un" + "interpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceO" + "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." + "google.protobuf.UninterpretedOption*\t\010\350\007" + "\020\200\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted" + "_option\030\347\007 \003(\0132$.google.protobuf.Uninter" + "pretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterprete" + "dOption\022;\n\004name\030\002 \003(\0132-.google.protobuf." + "UninterpretedOption.NamePart\022\030\n\020identifi" + "er_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001" + "(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double" + "_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017ag" + "gregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_" + "part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016Sou" + "rceCodeInfo\022:\n\010location\030\001 \003(\0132(.google.p" + "rotobuf.SourceCodeInfo.Location\032c\n\010Locat" + "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022" + "\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing_co" + "mments\030\004 \001(\tB)\n\023com.google.protobufB\020Des" + "criptorProtosH\001", 4135); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); + FileDescriptorSet::default_instance_ = new FileDescriptorSet(); + FileDescriptorProto::default_instance_ = new FileDescriptorProto(); + DescriptorProto::default_instance_ = new DescriptorProto(); + DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange(); + FieldDescriptorProto::default_instance_ = new FieldDescriptorProto(); + EnumDescriptorProto::default_instance_ = new EnumDescriptorProto(); + EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto(); + ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto(); + MethodDescriptorProto::default_instance_ = new MethodDescriptorProto(); + FileOptions::default_instance_ = new FileOptions(); + MessageOptions::default_instance_ = new MessageOptions(); + FieldOptions::default_instance_ = new FieldOptions(); + EnumOptions::default_instance_ = new EnumOptions(); + EnumValueOptions::default_instance_ = new EnumValueOptions(); + ServiceOptions::default_instance_ = new ServiceOptions(); + MethodOptions::default_instance_ = new MethodOptions(); + UninterpretedOption::default_instance_ = new UninterpretedOption(); + UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart(); + SourceCodeInfo::default_instance_ = new SourceCodeInfo(); + SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location(); + FileDescriptorSet::default_instance_->InitAsDefaultInstance(); + FileDescriptorProto::default_instance_->InitAsDefaultInstance(); + DescriptorProto::default_instance_->InitAsDefaultInstance(); + DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance(); + FieldDescriptorProto::default_instance_->InitAsDefaultInstance(); + EnumDescriptorProto::default_instance_->InitAsDefaultInstance(); + EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance(); + ServiceDescriptorProto::default_instance_->InitAsDefaultInstance(); + MethodDescriptorProto::default_instance_->InitAsDefaultInstance(); + FileOptions::default_instance_->InitAsDefaultInstance(); + MessageOptions::default_instance_->InitAsDefaultInstance(); + FieldOptions::default_instance_->InitAsDefaultInstance(); + EnumOptions::default_instance_->InitAsDefaultInstance(); + EnumValueOptions::default_instance_->InitAsDefaultInstance(); + ServiceOptions::default_instance_->InitAsDefaultInstance(); + MethodOptions::default_instance_->InitAsDefaultInstance(); + UninterpretedOption::default_instance_->InitAsDefaultInstance(); + UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance(); + ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto); +} + +// Force AddDescriptors() to be called at static initialization time. +struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto { + StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto() { + protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + } +} static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_; + +// =================================================================== + +#ifndef _MSC_VER +const int FileDescriptorSet::kFileFieldNumber; +#endif // !_MSC_VER + +FileDescriptorSet::FileDescriptorSet() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FileDescriptorSet::InitAsDefaultInstance() { +} + +FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FileDescriptorSet::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FileDescriptorSet::~FileDescriptorSet() { + SharedDtor(); +} + +void FileDescriptorSet::SharedDtor() { + if (this != default_instance_) { + } +} + +void FileDescriptorSet::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FileDescriptorSet::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileDescriptorSet_descriptor_; +} + +const FileDescriptorSet& FileDescriptorSet::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +FileDescriptorSet* FileDescriptorSet::default_instance_ = NULL; + +FileDescriptorSet* FileDescriptorSet::New() const { + return new FileDescriptorSet; +} + +void FileDescriptorSet::Clear() { + file_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FileDescriptorSet::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.FileDescriptorProto file = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_file())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_file; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FileDescriptorSet::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.FileDescriptorProto file = 1; + for (int i = 0; i < this->file_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->file(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FileDescriptorSet::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.FileDescriptorProto file = 1; + for (int i = 0; i < this->file_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->file(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FileDescriptorSet::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.FileDescriptorProto file = 1; + total_size += 1 * this->file_size(); + for (int i = 0; i < this->file_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->file(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FileDescriptorSet* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) { + GOOGLE_CHECK_NE(&from, this); + file_.MergeFrom(from.file_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileDescriptorSet::IsInitialized() const { + + for (int i = 0; i < file_size(); i++) { + if (!this->file(i).IsInitialized()) return false; + } + return true; +} + +void FileDescriptorSet::Swap(FileDescriptorSet* other) { + if (other != this) { + file_.Swap(&other->file_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileDescriptorSet_descriptor_; + metadata.reflection = FileDescriptorSet_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int FileDescriptorProto::kNameFieldNumber; +const int FileDescriptorProto::kPackageFieldNumber; +const int FileDescriptorProto::kDependencyFieldNumber; +const int FileDescriptorProto::kPublicDependencyFieldNumber; +const int FileDescriptorProto::kWeakDependencyFieldNumber; +const int FileDescriptorProto::kMessageTypeFieldNumber; +const int FileDescriptorProto::kEnumTypeFieldNumber; +const int FileDescriptorProto::kServiceFieldNumber; +const int FileDescriptorProto::kExtensionFieldNumber; +const int FileDescriptorProto::kOptionsFieldNumber; +const int FileDescriptorProto::kSourceCodeInfoFieldNumber; +#endif // !_MSC_VER + +FileDescriptorProto::FileDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FileDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance()); + source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance()); +} + +FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FileDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + source_code_info_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FileDescriptorProto::~FileDescriptorProto() { + SharedDtor(); +} + +void FileDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (package_ != &::google::protobuf::internal::kEmptyString) { + delete package_; + } + if (this != default_instance_) { + delete options_; + delete source_code_info_; + } +} + +void FileDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FileDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileDescriptorProto_descriptor_; +} + +const FileDescriptorProto& FileDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +FileDescriptorProto* FileDescriptorProto::default_instance_ = NULL; + +FileDescriptorProto* FileDescriptorProto::New() const { + return new FileDescriptorProto; +} + +void FileDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_package()) { + if (package_ != &::google::protobuf::internal::kEmptyString) { + package_->clear(); + } + } + } + if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) { + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); + } + if (has_source_code_info()) { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + } + } + dependency_.Clear(); + public_dependency_.Clear(); + weak_dependency_.Clear(); + message_type_.Clear(); + enum_type_.Clear(); + service_.Clear(); + extension_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FileDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_package; + break; + } + + // optional string package = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_package: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_dependency; + break; + } + + // repeated string dependency = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_dependency: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_dependency())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(this->dependency_size() - 1).data(), + this->dependency(this->dependency_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_dependency; + if (input->ExpectTag(34)) goto parse_message_type; + break; + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_message_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_message_type())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_message_type; + if (input->ExpectTag(42)) goto parse_enum_type; + break; + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_enum_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_enum_type())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(42)) goto parse_enum_type; + if (input->ExpectTag(50)) goto parse_service; + break; + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_service: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_service())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(50)) goto parse_service; + if (input->ExpectTag(58)) goto parse_extension; + break; + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_extension: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(58)) goto parse_extension; + if (input->ExpectTag(66)) goto parse_options; + break; + } + + // optional .google.protobuf.FileOptions options = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(74)) goto parse_source_code_info; + break; + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_source_code_info: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_source_code_info())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_public_dependency; + break; + } + + // repeated int32 public_dependency = 10; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_public_dependency: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 80, input, this->mutable_public_dependency()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_public_dependency()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_public_dependency; + if (input->ExpectTag(88)) goto parse_weak_dependency; + break; + } + + // repeated int32 weak_dependency = 11; + case 11: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_weak_dependency: + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 88, input, this->mutable_weak_dependency()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_weak_dependency()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(88)) goto parse_weak_dependency; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FileDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // optional string package = 2; + if (has_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->package(), output); + } + + // repeated string dependency = 3; + for (int i = 0; i < this->dependency_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(i).data(), this->dependency(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->dependency(i), output); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + for (int i = 0; i < this->message_type_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->message_type(i), output); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + for (int i = 0; i < this->enum_type_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 5, this->enum_type(i), output); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + for (int i = 0; i < this->service_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 6, this->service(i), output); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + for (int i = 0; i < this->extension_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 7, this->extension(i), output); + } + + // optional .google.protobuf.FileOptions options = 8; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 8, this->options(), output); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 9, this->source_code_info(), output); + } + + // repeated int32 public_dependency = 10; + for (int i = 0; i < this->public_dependency_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32( + 10, this->public_dependency(i), output); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0; i < this->weak_dependency_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32( + 11, this->weak_dependency(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // optional string package = 2; + if (has_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->package().data(), this->package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->package(), target); + } + + // repeated string dependency = 3; + for (int i = 0; i < this->dependency_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->dependency(i).data(), this->dependency(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(3, this->dependency(i), target); + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + for (int i = 0; i < this->message_type_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->message_type(i), target); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + for (int i = 0; i < this->enum_type_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 5, this->enum_type(i), target); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + for (int i = 0; i < this->service_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 6, this->service(i), target); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + for (int i = 0; i < this->extension_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 7, this->extension(i), target); + } + + // optional .google.protobuf.FileOptions options = 8; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->options(), target); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 9, this->source_code_info(), target); + } + + // repeated int32 public_dependency = 10; + for (int i = 0; i < this->public_dependency_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArray(10, this->public_dependency(i), target); + } + + // repeated int32 weak_dependency = 11; + for (int i = 0; i < this->weak_dependency_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32ToArray(11, this->weak_dependency(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FileDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional string package = 2; + if (has_package()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->package()); + } + + } + if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) { + // optional .google.protobuf.FileOptions options = 8; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->source_code_info()); + } + + } + // repeated string dependency = 3; + total_size += 1 * this->dependency_size(); + for (int i = 0; i < this->dependency_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->dependency(i)); + } + + // repeated int32 public_dependency = 10; + { + int data_size = 0; + for (int i = 0; i < this->public_dependency_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->public_dependency(i)); + } + total_size += 1 * this->public_dependency_size() + data_size; + } + + // repeated int32 weak_dependency = 11; + { + int data_size = 0; + for (int i = 0; i < this->weak_dependency_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->weak_dependency(i)); + } + total_size += 1 * this->weak_dependency_size() + data_size; + } + + // repeated .google.protobuf.DescriptorProto message_type = 4; + total_size += 1 * this->message_type_size(); + for (int i = 0; i < this->message_type_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->message_type(i)); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + total_size += 1 * this->enum_type_size(); + for (int i = 0; i < this->enum_type_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->enum_type(i)); + } + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + total_size += 1 * this->service_size(); + for (int i = 0; i < this->service_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->service(i)); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + total_size += 1 * this->extension_size(); + for (int i = 0; i < this->extension_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->extension(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FileDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + dependency_.MergeFrom(from.dependency_); + public_dependency_.MergeFrom(from.public_dependency_); + weak_dependency_.MergeFrom(from.weak_dependency_); + message_type_.MergeFrom(from.message_type_); + enum_type_.MergeFrom(from.enum_type_); + service_.MergeFrom(from.service_); + extension_.MergeFrom(from.extension_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_package()) { + set_package(from.package()); + } + } + if (from._has_bits_[9 / 32] & (0xffu << (9 % 32))) { + if (from.has_options()) { + mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options()); + } + if (from.has_source_code_info()) { + mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileDescriptorProto::IsInitialized() const { + + for (int i = 0; i < message_type_size(); i++) { + if (!this->message_type(i).IsInitialized()) return false; + } + for (int i = 0; i < enum_type_size(); i++) { + if (!this->enum_type(i).IsInitialized()) return false; + } + for (int i = 0; i < service_size(); i++) { + if (!this->service(i).IsInitialized()) return false; + } + for (int i = 0; i < extension_size(); i++) { + if (!this->extension(i).IsInitialized()) return false; + } + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void FileDescriptorProto::Swap(FileDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(package_, other->package_); + dependency_.Swap(&other->dependency_); + public_dependency_.Swap(&other->public_dependency_); + weak_dependency_.Swap(&other->weak_dependency_); + message_type_.Swap(&other->message_type_); + enum_type_.Swap(&other->enum_type_); + service_.Swap(&other->service_); + extension_.Swap(&other->extension_); + std::swap(options_, other->options_); + std::swap(source_code_info_, other->source_code_info_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileDescriptorProto_descriptor_; + metadata.reflection = FileDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int DescriptorProto_ExtensionRange::kStartFieldNumber; +const int DescriptorProto_ExtensionRange::kEndFieldNumber; +#endif // !_MSC_VER + +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void DescriptorProto_ExtensionRange::InitAsDefaultInstance() { +} + +DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void DescriptorProto_ExtensionRange::SharedCtor() { + _cached_size_ = 0; + start_ = 0; + end_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { + SharedDtor(); +} + +void DescriptorProto_ExtensionRange::SharedDtor() { + if (this != default_instance_) { + } +} + +void DescriptorProto_ExtensionRange::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange::descriptor() { + protobuf_AssignDescriptorsOnce(); + return DescriptorProto_ExtensionRange_descriptor_; +} + +const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::default_instance_ = NULL; + +DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New() const { + return new DescriptorProto_ExtensionRange; +} + +void DescriptorProto_ExtensionRange::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + start_ = 0; + end_ = 0; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional int32 start = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &start_))); + set_has_start(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_end; + break; + } + + // optional int32 end = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_end: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &end_))); + set_has_end(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional int32 start = 1; + if (has_start()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); + } + + // optional int32 end = 2; + if (has_end()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional int32 start = 1; + if (has_start()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); + } + + // optional int32 end = 2; + if (has_end()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int DescriptorProto_ExtensionRange::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional int32 start = 1; + if (has_start()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->start()); + } + + // optional int32 end = 2; + if (has_end()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->end()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const DescriptorProto_ExtensionRange* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_start()) { + set_start(from.start()); + } + if (from.has_end()) { + set_end(from.end()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto_ExtensionRange::IsInitialized() const { + + return true; +} + +void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) { + if (other != this) { + std::swap(start_, other->start_); + std::swap(end_, other->end_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = DescriptorProto_ExtensionRange_descriptor_; + metadata.reflection = DescriptorProto_ExtensionRange_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int DescriptorProto::kNameFieldNumber; +const int DescriptorProto::kFieldFieldNumber; +const int DescriptorProto::kExtensionFieldNumber; +const int DescriptorProto::kNestedTypeFieldNumber; +const int DescriptorProto::kEnumTypeFieldNumber; +const int DescriptorProto::kExtensionRangeFieldNumber; +const int DescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +DescriptorProto::DescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void DescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance()); +} + +DescriptorProto::DescriptorProto(const DescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void DescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +DescriptorProto::~DescriptorProto() { + SharedDtor(); +} + +void DescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + delete options_; + } +} + +void DescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* DescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return DescriptorProto_descriptor_; +} + +const DescriptorProto& DescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +DescriptorProto* DescriptorProto::default_instance_ = NULL; + +DescriptorProto* DescriptorProto::New() const { + return new DescriptorProto; +} + +void DescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); + } + } + field_.Clear(); + extension_.Clear(); + nested_type_.Clear(); + enum_type_.Clear(); + extension_range_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool DescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_field; + break; + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_field: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_field())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_field; + if (input->ExpectTag(26)) goto parse_nested_type; + break; + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_nested_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_nested_type())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_nested_type; + if (input->ExpectTag(34)) goto parse_enum_type; + break; + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_enum_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_enum_type())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_enum_type; + if (input->ExpectTag(42)) goto parse_extension_range; + break; + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_extension_range: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension_range())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(42)) goto parse_extension_range; + if (input->ExpectTag(50)) goto parse_extension; + break; + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_extension: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_extension())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(50)) goto parse_extension; + if (input->ExpectTag(58)) goto parse_options; + break; + } + + // optional .google.protobuf.MessageOptions options = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void DescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + for (int i = 0; i < this->field_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->field(i), output); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + for (int i = 0; i < this->nested_type_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->nested_type(i), output); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + for (int i = 0; i < this->enum_type_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->enum_type(i), output); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + for (int i = 0; i < this->extension_range_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 5, this->extension_range(i), output); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + for (int i = 0; i < this->extension_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 6, this->extension(i), output); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 7, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + for (int i = 0; i < this->field_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->field(i), target); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + for (int i = 0; i < this->nested_type_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->nested_type(i), target); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + for (int i = 0; i < this->enum_type_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->enum_type(i), target); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + for (int i = 0; i < this->extension_range_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 5, this->extension_range(i), target); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + for (int i = 0; i < this->extension_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 6, this->extension(i), target); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 7, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int DescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional .google.protobuf.MessageOptions options = 7; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + // repeated .google.protobuf.FieldDescriptorProto field = 2; + total_size += 1 * this->field_size(); + for (int i = 0; i < this->field_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->field(i)); + } + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + total_size += 1 * this->extension_size(); + for (int i = 0; i < this->extension_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->extension(i)); + } + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + total_size += 1 * this->nested_type_size(); + for (int i = 0; i < this->nested_type_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->nested_type(i)); + } + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + total_size += 1 * this->enum_type_size(); + for (int i = 0; i < this->enum_type_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->enum_type(i)); + } + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + total_size += 1 * this->extension_range_size(); + for (int i = 0; i < this->extension_range_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->extension_range(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const DescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void DescriptorProto::MergeFrom(const DescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + field_.MergeFrom(from.field_); + extension_.MergeFrom(from.extension_); + nested_type_.MergeFrom(from.nested_type_); + enum_type_.MergeFrom(from.enum_type_); + extension_range_.MergeFrom(from.extension_range_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void DescriptorProto::CopyFrom(const DescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto::IsInitialized() const { + + for (int i = 0; i < field_size(); i++) { + if (!this->field(i).IsInitialized()) return false; + } + for (int i = 0; i < extension_size(); i++) { + if (!this->extension(i).IsInitialized()) return false; + } + for (int i = 0; i < nested_type_size(); i++) { + if (!this->nested_type(i).IsInitialized()) return false; + } + for (int i = 0; i < enum_type_size(); i++) { + if (!this->enum_type(i).IsInitialized()) return false; + } + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void DescriptorProto::Swap(DescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + field_.Swap(&other->field_); + extension_.Swap(&other->extension_); + nested_type_.Swap(&other->nested_type_); + enum_type_.Swap(&other->enum_type_); + extension_range_.Swap(&other->extension_range_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata DescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = DescriptorProto_descriptor_; + metadata.reflection = DescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldDescriptorProto_Type_descriptor_; +} +bool FieldDescriptorProto_Type_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT64; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT32; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED64; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FIXED32; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BOOL; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_STRING; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_GROUP; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_MESSAGE; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_BYTES; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_UINT32; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_ENUM; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED32; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SFIXED64; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT32; +const FieldDescriptorProto_Type FieldDescriptorProto::TYPE_SINT64; +const FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN; +const FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX; +const int FieldDescriptorProto::Type_ARRAYSIZE; +#endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldDescriptorProto_Label_descriptor_; +} +bool FieldDescriptorProto_Label_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL; +const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED; +const FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED; +const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; +const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; +const int FieldDescriptorProto::Label_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int FieldDescriptorProto::kNameFieldNumber; +const int FieldDescriptorProto::kNumberFieldNumber; +const int FieldDescriptorProto::kLabelFieldNumber; +const int FieldDescriptorProto::kTypeFieldNumber; +const int FieldDescriptorProto::kTypeNameFieldNumber; +const int FieldDescriptorProto::kExtendeeFieldNumber; +const int FieldDescriptorProto::kDefaultValueFieldNumber; +const int FieldDescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +FieldDescriptorProto::FieldDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FieldDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance()); +} + +FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FieldDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + number_ = 0; + label_ = 1; + type_ = 1; + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FieldDescriptorProto::~FieldDescriptorProto() { + SharedDtor(); +} + +void FieldDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (type_name_ != &::google::protobuf::internal::kEmptyString) { + delete type_name_; + } + if (extendee_ != &::google::protobuf::internal::kEmptyString) { + delete extendee_; + } + if (default_value_ != &::google::protobuf::internal::kEmptyString) { + delete default_value_; + } + if (this != default_instance_) { + delete options_; + } +} + +void FieldDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FieldDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldDescriptorProto_descriptor_; +} + +const FieldDescriptorProto& FieldDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +FieldDescriptorProto* FieldDescriptorProto::default_instance_ = NULL; + +FieldDescriptorProto* FieldDescriptorProto::New() const { + return new FieldDescriptorProto; +} + +void FieldDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + number_ = 0; + label_ = 1; + type_ = 1; + if (has_type_name()) { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { + type_name_->clear(); + } + } + if (has_extendee()) { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { + extendee_->clear(); + } + } + if (has_default_value()) { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { + default_value_->clear(); + } + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FieldDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_extendee; + break; + } + + // optional string extendee = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_extendee: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_extendee())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_number; + break; + } + + // optional int32 number = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_number: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &number_))); + set_has_number(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_label; + break; + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_label: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) { + set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value)); + } else { + mutable_unknown_fields()->AddVarint(4, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_type; + break; + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_type: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) { + set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value)); + } else { + mutable_unknown_fields()->AddVarint(5, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(50)) goto parse_type_name; + break; + } + + // optional string type_name = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_type_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_type_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(58)) goto parse_default_value; + break; + } + + // optional string default_value = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_default_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_default_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(66)) goto parse_options; + break; + } + + // optional .google.protobuf.FieldOptions options = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FieldDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // optional string extendee = 2; + if (has_extendee()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->extendee(), output); + } + + // optional int32 number = 3; + if (has_number()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output); + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (has_label()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 4, this->label(), output); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (has_type()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 5, this->type(), output); + } + + // optional string type_name = 6; + if (has_type_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 6, this->type_name(), output); + } + + // optional string default_value = 7; + if (has_default_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 7, this->default_value(), output); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 8, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // optional string extendee = 2; + if (has_extendee()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->extendee().data(), this->extendee().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->extendee(), target); + } + + // optional int32 number = 3; + if (has_number()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (has_label()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 4, this->label(), target); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (has_type()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 5, this->type(), target); + } + + // optional string type_name = 6; + if (has_type_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->type_name().data(), this->type_name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 6, this->type_name(), target); + } + + // optional string default_value = 7; + if (has_default_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->default_value().data(), this->default_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 7, this->default_value(), target); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FieldDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional int32 number = 3; + if (has_number()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->number()); + } + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + if (has_label()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->label()); + } + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + if (has_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->type()); + } + + // optional string type_name = 6; + if (has_type_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->type_name()); + } + + // optional string extendee = 2; + if (has_extendee()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->extendee()); + } + + // optional string default_value = 7; + if (has_default_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->default_value()); + } + + // optional .google.protobuf.FieldOptions options = 8; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FieldDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_number()) { + set_number(from.number()); + } + if (from.has_label()) { + set_label(from.label()); + } + if (from.has_type()) { + set_type(from.type()); + } + if (from.has_type_name()) { + set_type_name(from.type_name()); + } + if (from.has_extendee()) { + set_extendee(from.extendee()); + } + if (from.has_default_value()) { + set_default_value(from.default_value()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldDescriptorProto::IsInitialized() const { + + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(number_, other->number_); + std::swap(label_, other->label_); + std::swap(type_, other->type_); + std::swap(type_name_, other->type_name_); + std::swap(extendee_, other->extendee_); + std::swap(default_value_, other->default_value_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FieldDescriptorProto_descriptor_; + metadata.reflection = FieldDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EnumDescriptorProto::kNameFieldNumber; +const int EnumDescriptorProto::kValueFieldNumber; +const int EnumDescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +EnumDescriptorProto::EnumDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EnumDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance()); +} + +EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EnumDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EnumDescriptorProto::~EnumDescriptorProto() { + SharedDtor(); +} + +void EnumDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + delete options_; + } +} + +void EnumDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EnumDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EnumDescriptorProto_descriptor_; +} + +const EnumDescriptorProto& EnumDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +EnumDescriptorProto* EnumDescriptorProto::default_instance_ = NULL; + +EnumDescriptorProto* EnumDescriptorProto::New() const { + return new EnumDescriptorProto; +} + +void EnumDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); + } + } + value_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EnumDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_value; + break; + } + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_value())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_value; + if (input->ExpectTag(26)) goto parse_options; + break; + } + + // optional .google.protobuf.EnumOptions options = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EnumDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + for (int i = 0; i < this->value_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->value(i), output); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + for (int i = 0; i < this->value_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->value(i), target); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EnumDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional .google.protobuf.EnumOptions options = 3; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + total_size += 1 * this->value_size(); + for (int i = 0; i < this->value_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->value(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EnumDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + value_.MergeFrom(from.value_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumDescriptorProto::IsInitialized() const { + + for (int i = 0; i < value_size(); i++) { + if (!this->value(i).IsInitialized()) return false; + } + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void EnumDescriptorProto::Swap(EnumDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + value_.Swap(&other->value_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumDescriptorProto_descriptor_; + metadata.reflection = EnumDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EnumValueDescriptorProto::kNameFieldNumber; +const int EnumValueDescriptorProto::kNumberFieldNumber; +const int EnumValueDescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +EnumValueDescriptorProto::EnumValueDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EnumValueDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance()); +} + +EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EnumValueDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + number_ = 0; + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EnumValueDescriptorProto::~EnumValueDescriptorProto() { + SharedDtor(); +} + +void EnumValueDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + delete options_; + } +} + +void EnumValueDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EnumValueDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EnumValueDescriptorProto_descriptor_; +} + +const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +EnumValueDescriptorProto* EnumValueDescriptorProto::default_instance_ = NULL; + +EnumValueDescriptorProto* EnumValueDescriptorProto::New() const { + return new EnumValueDescriptorProto; +} + +void EnumValueDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + number_ = 0; + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EnumValueDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_number; + break; + } + + // optional int32 number = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_number: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &number_))); + set_has_number(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_options; + break; + } + + // optional .google.protobuf.EnumValueOptions options = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EnumValueDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // optional int32 number = 2; + if (has_number()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // optional int32 number = 2; + if (has_number()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EnumValueDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional int32 number = 2; + if (has_number()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->number()); + } + + // optional .google.protobuf.EnumValueOptions options = 3; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EnumValueDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_number()) { + set_number(from.number()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumValueDescriptorProto::IsInitialized() const { + + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(number_, other->number_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumValueDescriptorProto_descriptor_; + metadata.reflection = EnumValueDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ServiceDescriptorProto::kNameFieldNumber; +const int ServiceDescriptorProto::kMethodFieldNumber; +const int ServiceDescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +ServiceDescriptorProto::ServiceDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ServiceDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance()); +} + +ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ServiceDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ServiceDescriptorProto::~ServiceDescriptorProto() { + SharedDtor(); +} + +void ServiceDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (this != default_instance_) { + delete options_; + } +} + +void ServiceDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ServiceDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ServiceDescriptorProto_descriptor_; +} + +const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +ServiceDescriptorProto* ServiceDescriptorProto::default_instance_ = NULL; + +ServiceDescriptorProto* ServiceDescriptorProto::New() const { + return new ServiceDescriptorProto; +} + +void ServiceDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); + } + } + method_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ServiceDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_method; + break; + } + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_method: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_method())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_method; + if (input->ExpectTag(26)) goto parse_options; + break; + } + + // optional .google.protobuf.ServiceOptions options = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ServiceDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + for (int i = 0; i < this->method_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->method(i), output); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 3, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + for (int i = 0; i < this->method_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->method(i), target); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 3, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ServiceDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional .google.protobuf.ServiceOptions options = 3; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + // repeated .google.protobuf.MethodDescriptorProto method = 2; + total_size += 1 * this->method_size(); + for (int i = 0; i < this->method_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->method(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ServiceDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + method_.MergeFrom(from.method_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ServiceDescriptorProto::IsInitialized() const { + + for (int i = 0; i < method_size(); i++) { + if (!this->method(i).IsInitialized()) return false; + } + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + method_.Swap(&other->method_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ServiceDescriptorProto_descriptor_; + metadata.reflection = ServiceDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int MethodDescriptorProto::kNameFieldNumber; +const int MethodDescriptorProto::kInputTypeFieldNumber; +const int MethodDescriptorProto::kOutputTypeFieldNumber; +const int MethodDescriptorProto::kOptionsFieldNumber; +#endif // !_MSC_VER + +MethodDescriptorProto::MethodDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void MethodDescriptorProto::InitAsDefaultInstance() { + options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance()); +} + +MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void MethodDescriptorProto::SharedCtor() { + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + options_ = NULL; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +MethodDescriptorProto::~MethodDescriptorProto() { + SharedDtor(); +} + +void MethodDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (input_type_ != &::google::protobuf::internal::kEmptyString) { + delete input_type_; + } + if (output_type_ != &::google::protobuf::internal::kEmptyString) { + delete output_type_; + } + if (this != default_instance_) { + delete options_; + } +} + +void MethodDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* MethodDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return MethodDescriptorProto_descriptor_; +} + +const MethodDescriptorProto& MethodDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +MethodDescriptorProto* MethodDescriptorProto::default_instance_ = NULL; + +MethodDescriptorProto* MethodDescriptorProto::New() const { + return new MethodDescriptorProto; +} + +void MethodDescriptorProto::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + } + if (has_input_type()) { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { + input_type_->clear(); + } + } + if (has_output_type()) { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { + output_type_->clear(); + } + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool MethodDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_input_type; + break; + } + + // optional string input_type = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_input_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_input_type())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_output_type; + break; + } + + // optional string output_type = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_output_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_output_type())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_options; + break; + } + + // optional .google.protobuf.MethodOptions options = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_options())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void MethodDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name(), output); + } + + // optional string input_type = 2; + if (has_input_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 2, this->input_type(), output); + } + + // optional string output_type = 3; + if (has_output_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->output_type(), output); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (has_options()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 4, this->options(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + // optional string input_type = 2; + if (has_input_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->input_type().data(), this->input_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->input_type(), target); + } + + // optional string output_type = 3; + if (has_output_type()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->output_type().data(), this->output_type().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->output_type(), target); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (has_options()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 4, this->options(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int MethodDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + // optional string input_type = 2; + if (has_input_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->input_type()); + } + + // optional string output_type = 3; + if (has_output_type()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->output_type()); + } + + // optional .google.protobuf.MethodOptions options = 4; + if (has_options()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->options()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const MethodDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + if (from.has_input_type()) { + set_input_type(from.input_type()); + } + if (from.has_output_type()) { + set_output_type(from.output_type()); + } + if (from.has_options()) { + mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MethodDescriptorProto::IsInitialized() const { + + if (has_options()) { + if (!this->options().IsInitialized()) return false; + } + return true; +} + +void MethodDescriptorProto::Swap(MethodDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(input_type_, other->input_type_); + std::swap(output_type_, other->output_type_); + std::swap(options_, other->options_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = MethodDescriptorProto_descriptor_; + metadata.reflection = MethodDescriptorProto_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileOptions_OptimizeMode_descriptor_; +} +bool FileOptions_OptimizeMode_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FileOptions_OptimizeMode FileOptions::SPEED; +const FileOptions_OptimizeMode FileOptions::CODE_SIZE; +const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; +const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; +const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; +const int FileOptions::OptimizeMode_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int FileOptions::kJavaPackageFieldNumber; +const int FileOptions::kJavaOuterClassnameFieldNumber; +const int FileOptions::kJavaMultipleFilesFieldNumber; +const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber; +const int FileOptions::kOptimizeForFieldNumber; +const int FileOptions::kGoPackageFieldNumber; +const int FileOptions::kCcGenericServicesFieldNumber; +const int FileOptions::kJavaGenericServicesFieldNumber; +const int FileOptions::kPyGenericServicesFieldNumber; +const int FileOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +FileOptions::FileOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FileOptions::InitAsDefaultInstance() { +} + +FileOptions::FileOptions(const FileOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FileOptions::SharedCtor() { + _cached_size_ = 0; + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + java_multiple_files_ = false; + java_generate_equals_and_hash_ = false; + optimize_for_ = 1; + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + cc_generic_services_ = false; + java_generic_services_ = false; + py_generic_services_ = false; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FileOptions::~FileOptions() { + SharedDtor(); +} + +void FileOptions::SharedDtor() { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { + delete java_package_; + } + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { + delete java_outer_classname_; + } + if (go_package_ != &::google::protobuf::internal::kEmptyString) { + delete go_package_; + } + if (this != default_instance_) { + } +} + +void FileOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FileOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileOptions_descriptor_; +} + +const FileOptions& FileOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +FileOptions* FileOptions::default_instance_ = NULL; + +FileOptions* FileOptions::New() const { + return new FileOptions; +} + +void FileOptions::Clear() { + _extensions_.Clear(); + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_java_package()) { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { + java_package_->clear(); + } + } + if (has_java_outer_classname()) { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { + java_outer_classname_->clear(); + } + } + java_multiple_files_ = false; + java_generate_equals_and_hash_ = false; + optimize_for_ = 1; + if (has_go_package()) { + if (go_package_ != &::google::protobuf::internal::kEmptyString) { + go_package_->clear(); + } + } + cc_generic_services_ = false; + java_generic_services_ = false; + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + py_generic_services_ = false; + } + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FileOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string java_package = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_java_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(66)) goto parse_java_outer_classname; + break; + } + + // optional string java_outer_classname = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_java_outer_classname: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_java_outer_classname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(72)) goto parse_optimize_for; + break; + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_optimize_for: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) { + set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value)); + } else { + mutable_unknown_fields()->AddVarint(9, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_java_multiple_files; + break; + } + + // optional bool java_multiple_files = 10 [default = false]; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_java_multiple_files: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_multiple_files_))); + set_has_java_multiple_files(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(90)) goto parse_go_package; + break; + } + + // optional string go_package = 11; + case 11: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_go_package: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_go_package())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(128)) goto parse_cc_generic_services; + break; + } + + // optional bool cc_generic_services = 16 [default = false]; + case 16: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_cc_generic_services: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &cc_generic_services_))); + set_has_cc_generic_services(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(136)) goto parse_java_generic_services; + break; + } + + // optional bool java_generic_services = 17 [default = false]; + case 17: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_java_generic_services: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_generic_services_))); + set_has_java_generic_services(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(144)) goto parse_py_generic_services; + break; + } + + // optional bool py_generic_services = 18 [default = false]; + case 18: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_py_generic_services: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &py_generic_services_))); + set_has_py_generic_services(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash; + break; + } + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + case 20: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_java_generate_equals_and_hash: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_generate_equals_and_hash_))); + set_has_java_generate_equals_and_hash(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FileOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional string java_package = 1; + if (has_java_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->java_package(), output); + } + + // optional string java_outer_classname = 8; + if (has_java_outer_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 8, this->java_outer_classname(), output); + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (has_optimize_for()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 9, this->optimize_for(), output); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (has_java_multiple_files()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output); + } + + // optional string go_package = 11; + if (has_go_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 11, this->go_package(), output); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output); + } + + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output); + } + + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output); + } + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional string java_package = 1; + if (has_java_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_package().data(), this->java_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->java_package(), target); + } + + // optional string java_outer_classname = 8; + if (has_java_outer_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->java_outer_classname().data(), this->java_outer_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 8, this->java_outer_classname(), target); + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (has_optimize_for()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 9, this->optimize_for(), target); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (has_java_multiple_files()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target); + } + + // optional string go_package = 11; + if (has_go_package()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->go_package().data(), this->go_package().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 11, this->go_package(), target); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target); + } + + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target); + } + + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target); + } + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FileOptions::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string java_package = 1; + if (has_java_package()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->java_package()); + } + + // optional string java_outer_classname = 8; + if (has_java_outer_classname()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->java_outer_classname()); + } + + // optional bool java_multiple_files = 10 [default = false]; + if (has_java_multiple_files()) { + total_size += 1 + 1; + } + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + total_size += 2 + 1; + } + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + if (has_optimize_for()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for()); + } + + // optional string go_package = 11; + if (has_go_package()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->go_package()); + } + + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { + total_size += 2 + 1; + } + + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { + total_size += 2 + 1; + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { + total_size += 2 + 1; + } + + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FileOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FileOptions::MergeFrom(const FileOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_java_package()) { + set_java_package(from.java_package()); + } + if (from.has_java_outer_classname()) { + set_java_outer_classname(from.java_outer_classname()); + } + if (from.has_java_multiple_files()) { + set_java_multiple_files(from.java_multiple_files()); + } + if (from.has_java_generate_equals_and_hash()) { + set_java_generate_equals_and_hash(from.java_generate_equals_and_hash()); + } + if (from.has_optimize_for()) { + set_optimize_for(from.optimize_for()); + } + if (from.has_go_package()) { + set_go_package(from.go_package()); + } + if (from.has_cc_generic_services()) { + set_cc_generic_services(from.cc_generic_services()); + } + if (from.has_java_generic_services()) { + set_java_generic_services(from.java_generic_services()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_py_generic_services()) { + set_py_generic_services(from.py_generic_services()); + } + } + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FileOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FileOptions::CopyFrom(const FileOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FileOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void FileOptions::Swap(FileOptions* other) { + if (other != this) { + std::swap(java_package_, other->java_package_); + std::swap(java_outer_classname_, other->java_outer_classname_); + std::swap(java_multiple_files_, other->java_multiple_files_); + std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_); + std::swap(optimize_for_, other->optimize_for_); + std::swap(go_package_, other->go_package_); + std::swap(cc_generic_services_, other->cc_generic_services_); + std::swap(java_generic_services_, other->java_generic_services_); + std::swap(py_generic_services_, other->py_generic_services_); + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata FileOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FileOptions_descriptor_; + metadata.reflection = FileOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int MessageOptions::kMessageSetWireFormatFieldNumber; +const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber; +const int MessageOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +MessageOptions::MessageOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void MessageOptions::InitAsDefaultInstance() { +} + +MessageOptions::MessageOptions(const MessageOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void MessageOptions::SharedCtor() { + _cached_size_ = 0; + message_set_wire_format_ = false; + no_standard_descriptor_accessor_ = false; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +MessageOptions::~MessageOptions() { + SharedDtor(); +} + +void MessageOptions::SharedDtor() { + if (this != default_instance_) { + } +} + +void MessageOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* MessageOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return MessageOptions_descriptor_; +} + +const MessageOptions& MessageOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +MessageOptions* MessageOptions::default_instance_ = NULL; + +MessageOptions* MessageOptions::New() const { + return new MessageOptions; +} + +void MessageOptions::Clear() { + _extensions_.Clear(); + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + message_set_wire_format_ = false; + no_standard_descriptor_accessor_ = false; + } + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool MessageOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool message_set_wire_format = 1 [default = false]; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &message_set_wire_format_))); + set_has_message_set_wire_format(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor; + break; + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_no_standard_descriptor_accessor: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &no_standard_descriptor_accessor_))); + set_has_no_standard_descriptor_accessor(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void MessageOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional bool message_set_wire_format = 1 [default = false]; + if (has_message_set_wire_format()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (has_no_standard_descriptor_accessor()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional bool message_set_wire_format = 1 [default = false]; + if (has_message_set_wire_format()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (has_no_standard_descriptor_accessor()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int MessageOptions::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool message_set_wire_format = 1 [default = false]; + if (has_message_set_wire_format()) { + total_size += 1 + 1; + } + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + if (has_no_standard_descriptor_accessor()) { + total_size += 1 + 1; + } + + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const MessageOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void MessageOptions::MergeFrom(const MessageOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_message_set_wire_format()) { + set_message_set_wire_format(from.message_set_wire_format()); + } + if (from.has_no_standard_descriptor_accessor()) { + set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor()); + } + } + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void MessageOptions::CopyFrom(const MessageOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MessageOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void MessageOptions::Swap(MessageOptions* other) { + if (other != this) { + std::swap(message_set_wire_format_, other->message_set_wire_format_); + std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_); + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata MessageOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = MessageOptions_descriptor_; + metadata.reflection = MessageOptions_reflection_; + return metadata; +} + + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldOptions_CType_descriptor_; +} +bool FieldOptions_CType_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FieldOptions_CType FieldOptions::STRING; +const FieldOptions_CType FieldOptions::CORD; +const FieldOptions_CType FieldOptions::STRING_PIECE; +const FieldOptions_CType FieldOptions::CType_MIN; +const FieldOptions_CType FieldOptions::CType_MAX; +const int FieldOptions::CType_ARRAYSIZE; +#endif // _MSC_VER +#ifndef _MSC_VER +const int FieldOptions::kCtypeFieldNumber; +const int FieldOptions::kPackedFieldNumber; +const int FieldOptions::kLazyFieldNumber; +const int FieldOptions::kDeprecatedFieldNumber; +const int FieldOptions::kExperimentalMapKeyFieldNumber; +const int FieldOptions::kWeakFieldNumber; +const int FieldOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +FieldOptions::FieldOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void FieldOptions::InitAsDefaultInstance() { +} + +FieldOptions::FieldOptions(const FieldOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void FieldOptions::SharedCtor() { + _cached_size_ = 0; + ctype_ = 0; + packed_ = false; + lazy_ = false; + deprecated_ = false; + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + weak_ = false; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +FieldOptions::~FieldOptions() { + SharedDtor(); +} + +void FieldOptions::SharedDtor() { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { + delete experimental_map_key_; + } + if (this != default_instance_) { + } +} + +void FieldOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* FieldOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldOptions_descriptor_; +} + +const FieldOptions& FieldOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +FieldOptions* FieldOptions::default_instance_ = NULL; + +FieldOptions* FieldOptions::New() const { + return new FieldOptions; +} + +void FieldOptions::Clear() { + _extensions_.Clear(); + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + ctype_ = 0; + packed_ = false; + lazy_ = false; + deprecated_ = false; + if (has_experimental_map_key()) { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { + experimental_map_key_->clear(); + } + } + weak_ = false; + } + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool FieldOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::google::protobuf::FieldOptions_CType_IsValid(value)) { + set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value)); + } else { + mutable_unknown_fields()->AddVarint(1, value); + } + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_packed; + break; + } + + // optional bool packed = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_packed: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &packed_))); + set_has_packed(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(24)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 3 [default = false]; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_lazy; + break; + } + + // optional bool lazy = 5 [default = false]; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_lazy: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &lazy_))); + set_has_lazy(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(74)) goto parse_experimental_map_key; + break; + } + + // optional string experimental_map_key = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_experimental_map_key: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_experimental_map_key())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(80)) goto parse_weak; + break; + } + + // optional bool weak = 10 [default = false]; + case 10: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_weak: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &weak_))); + set_has_weak(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void FieldOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (has_ctype()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->ctype(), output); + } + + // optional bool packed = 2; + if (has_packed()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output); + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); + } + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output); + } + + // optional string experimental_map_key = 9; + if (has_experimental_map_key()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 9, this->experimental_map_key(), output); + } + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (has_ctype()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->ctype(), target); + } + + // optional bool packed = 2; + if (has_packed()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target); + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + } + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target); + } + + // optional string experimental_map_key = 9; + if (has_experimental_map_key()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->experimental_map_key().data(), this->experimental_map_key().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 9, this->experimental_map_key(), target); + } + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int FieldOptions::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + if (has_ctype()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->ctype()); + } + + // optional bool packed = 2; + if (has_packed()) { + total_size += 1 + 1; + } + + // optional bool lazy = 5 [default = false]; + if (has_lazy()) { + total_size += 1 + 1; + } + + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + + // optional string experimental_map_key = 9; + if (has_experimental_map_key()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->experimental_map_key()); + } + + // optional bool weak = 10 [default = false]; + if (has_weak()) { + total_size += 1 + 1; + } + + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const FieldOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void FieldOptions::MergeFrom(const FieldOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_ctype()) { + set_ctype(from.ctype()); + } + if (from.has_packed()) { + set_packed(from.packed()); + } + if (from.has_lazy()) { + set_lazy(from.lazy()); + } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + if (from.has_experimental_map_key()) { + set_experimental_map_key(from.experimental_map_key()); + } + if (from.has_weak()) { + set_weak(from.weak()); + } + } + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void FieldOptions::CopyFrom(const FieldOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void FieldOptions::Swap(FieldOptions* other) { + if (other != this) { + std::swap(ctype_, other->ctype_); + std::swap(packed_, other->packed_); + std::swap(lazy_, other->lazy_); + std::swap(deprecated_, other->deprecated_); + std::swap(experimental_map_key_, other->experimental_map_key_); + std::swap(weak_, other->weak_); + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata FieldOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = FieldOptions_descriptor_; + metadata.reflection = FieldOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EnumOptions::kAllowAliasFieldNumber; +const int EnumOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +EnumOptions::EnumOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EnumOptions::InitAsDefaultInstance() { +} + +EnumOptions::EnumOptions(const EnumOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EnumOptions::SharedCtor() { + _cached_size_ = 0; + allow_alias_ = true; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EnumOptions::~EnumOptions() { + SharedDtor(); +} + +void EnumOptions::SharedDtor() { + if (this != default_instance_) { + } +} + +void EnumOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EnumOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EnumOptions_descriptor_; +} + +const EnumOptions& EnumOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +EnumOptions* EnumOptions::default_instance_ = NULL; + +EnumOptions* EnumOptions::New() const { + return new EnumOptions; +} + +void EnumOptions::Clear() { + _extensions_.Clear(); + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + allow_alias_ = true; + } + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EnumOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool allow_alias = 2 [default = true]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &allow_alias_))); + set_has_allow_alias(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EnumOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // optional bool allow_alias = 2 [default = true]; + if (has_allow_alias()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // optional bool allow_alias = 2 [default = true]; + if (has_allow_alias()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target); + } + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EnumOptions::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool allow_alias = 2 [default = true]; + if (has_allow_alias()) { + total_size += 1 + 1; + } + + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EnumOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EnumOptions::MergeFrom(const EnumOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_allow_alias()) { + set_allow_alias(from.allow_alias()); + } + } + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EnumOptions::CopyFrom(const EnumOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void EnumOptions::Swap(EnumOptions* other) { + if (other != this) { + std::swap(allow_alias_, other->allow_alias_); + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata EnumOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumOptions_descriptor_; + metadata.reflection = EnumOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int EnumValueOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +EnumValueOptions::EnumValueOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void EnumValueOptions::InitAsDefaultInstance() { +} + +EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void EnumValueOptions::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +EnumValueOptions::~EnumValueOptions() { + SharedDtor(); +} + +void EnumValueOptions::SharedDtor() { + if (this != default_instance_) { + } +} + +void EnumValueOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* EnumValueOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return EnumValueOptions_descriptor_; +} + +const EnumValueOptions& EnumValueOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +EnumValueOptions* EnumValueOptions::default_instance_ = NULL; + +EnumValueOptions* EnumValueOptions::New() const { + return new EnumValueOptions; +} + +void EnumValueOptions::Clear() { + _extensions_.Clear(); + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool EnumValueOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void EnumValueOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* EnumValueOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int EnumValueOptions::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const EnumValueOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool EnumValueOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void EnumValueOptions::Swap(EnumValueOptions* other) { + if (other != this) { + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata EnumValueOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = EnumValueOptions_descriptor_; + metadata.reflection = EnumValueOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int ServiceOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +ServiceOptions::ServiceOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void ServiceOptions::InitAsDefaultInstance() { +} + +ServiceOptions::ServiceOptions(const ServiceOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void ServiceOptions::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +ServiceOptions::~ServiceOptions() { + SharedDtor(); +} + +void ServiceOptions::SharedDtor() { + if (this != default_instance_) { + } +} + +void ServiceOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* ServiceOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return ServiceOptions_descriptor_; +} + +const ServiceOptions& ServiceOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +ServiceOptions* ServiceOptions::default_instance_ = NULL; + +ServiceOptions* ServiceOptions::New() const { + return new ServiceOptions; +} + +void ServiceOptions::Clear() { + _extensions_.Clear(); + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool ServiceOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void ServiceOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* ServiceOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int ServiceOptions::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const ServiceOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void ServiceOptions::MergeFrom(const ServiceOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ServiceOptions::CopyFrom(const ServiceOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ServiceOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void ServiceOptions::Swap(ServiceOptions* other) { + if (other != this) { + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata ServiceOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = ServiceOptions_descriptor_; + metadata.reflection = ServiceOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int MethodOptions::kUninterpretedOptionFieldNumber; +#endif // !_MSC_VER + +MethodOptions::MethodOptions() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void MethodOptions::InitAsDefaultInstance() { +} + +MethodOptions::MethodOptions(const MethodOptions& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void MethodOptions::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +MethodOptions::~MethodOptions() { + SharedDtor(); +} + +void MethodOptions::SharedDtor() { + if (this != default_instance_) { + } +} + +void MethodOptions::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* MethodOptions::descriptor() { + protobuf_AssignDescriptorsOnce(); + return MethodOptions_descriptor_; +} + +const MethodOptions& MethodOptions::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +MethodOptions* MethodOptions::default_instance_ = NULL; + +MethodOptions* MethodOptions::New() const { + return new MethodOptions; +} + +void MethodOptions::Clear() { + _extensions_.Clear(); + uninterpreted_option_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool MethodOptions::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + case 999: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_uninterpreted_option())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if ((8000u <= tag)) { + DO_(_extensions_.ParseField(tag, input, default_instance_, + mutable_unknown_fields())); + continue; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void MethodOptions::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 999, this->uninterpreted_option(i), output); + } + + // Extension range [1000, 536870912) + _extensions_.SerializeWithCachedSizes( + 1000, 536870912, output); + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* MethodOptions::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 999, this->uninterpreted_option(i), target); + } + + // Extension range [1000, 536870912) + target = _extensions_.SerializeWithCachedSizesToArray( + 1000, 536870912, target); + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int MethodOptions::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + total_size += 2 * this->uninterpreted_option_size(); + for (int i = 0; i < this->uninterpreted_option_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->uninterpreted_option(i)); + } + + total_size += _extensions_.ByteSize(); + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const MethodOptions* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void MethodOptions::MergeFrom(const MethodOptions& from) { + GOOGLE_CHECK_NE(&from, this); + uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + _extensions_.MergeFrom(from._extensions_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void MethodOptions::CopyFrom(const MethodOptions& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MethodOptions::IsInitialized() const { + + for (int i = 0; i < uninterpreted_option_size(); i++) { + if (!this->uninterpreted_option(i).IsInitialized()) return false; + } + + if (!_extensions_.IsInitialized()) return false; return true; +} + +void MethodOptions::Swap(MethodOptions* other) { + if (other != this) { + uninterpreted_option_.Swap(&other->uninterpreted_option_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + _extensions_.Swap(&other->_extensions_); + } +} + +::google::protobuf::Metadata MethodOptions::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = MethodOptions_descriptor_; + metadata.reflection = MethodOptions_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int UninterpretedOption_NamePart::kNamePartFieldNumber; +const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; +#endif // !_MSC_VER + +UninterpretedOption_NamePart::UninterpretedOption_NamePart() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void UninterpretedOption_NamePart::InitAsDefaultInstance() { +} + +UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void UninterpretedOption_NamePart::SharedCtor() { + _cached_size_ = 0; + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + is_extension_ = false; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { + SharedDtor(); +} + +void UninterpretedOption_NamePart::SharedDtor() { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { + delete name_part_; + } + if (this != default_instance_) { + } +} + +void UninterpretedOption_NamePart::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* UninterpretedOption_NamePart::descriptor() { + protobuf_AssignDescriptorsOnce(); + return UninterpretedOption_NamePart_descriptor_; +} + +const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +UninterpretedOption_NamePart* UninterpretedOption_NamePart::default_instance_ = NULL; + +UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const { + return new UninterpretedOption_NamePart; +} + +void UninterpretedOption_NamePart::Clear() { + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (has_name_part()) { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { + name_part_->clear(); + } + } + is_extension_ = false; + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool UninterpretedOption_NamePart::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // required string name_part = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name_part())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(16)) goto parse_is_extension; + break; + } + + // required bool is_extension = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_is_extension: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &is_extension_))); + set_has_is_extension(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void UninterpretedOption_NamePart::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // required string name_part = 1; + if (has_name_part()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 1, this->name_part(), output); + } + + // required bool is_extension = 2; + if (has_is_extension()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // required string name_part = 1; + if (has_name_part()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->name_part().data(), this->name_part().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name_part(), target); + } + + // required bool is_extension = 2; + if (has_is_extension()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int UninterpretedOption_NamePart::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // required string name_part = 1; + if (has_name_part()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name_part()); + } + + // required bool is_extension = 2; + if (has_is_extension()) { + total_size += 1 + 1; + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const UninterpretedOption_NamePart* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name_part()) { + set_name_part(from.name_part()); + } + if (from.has_is_extension()) { + set_is_extension(from.is_extension()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UninterpretedOption_NamePart::IsInitialized() const { + if ((_has_bits_[0] & 0x00000003) != 0x00000003) return false; + + return true; +} + +void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) { + if (other != this) { + std::swap(name_part_, other->name_part_); + std::swap(is_extension_, other->is_extension_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = UninterpretedOption_NamePart_descriptor_; + metadata.reflection = UninterpretedOption_NamePart_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int UninterpretedOption::kNameFieldNumber; +const int UninterpretedOption::kIdentifierValueFieldNumber; +const int UninterpretedOption::kPositiveIntValueFieldNumber; +const int UninterpretedOption::kNegativeIntValueFieldNumber; +const int UninterpretedOption::kDoubleValueFieldNumber; +const int UninterpretedOption::kStringValueFieldNumber; +const int UninterpretedOption::kAggregateValueFieldNumber; +#endif // !_MSC_VER + +UninterpretedOption::UninterpretedOption() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void UninterpretedOption::InitAsDefaultInstance() { +} + +UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void UninterpretedOption::SharedCtor() { + _cached_size_ = 0; + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + positive_int_value_ = GOOGLE_ULONGLONG(0); + negative_int_value_ = GOOGLE_LONGLONG(0); + double_value_ = 0; + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +UninterpretedOption::~UninterpretedOption() { + SharedDtor(); +} + +void UninterpretedOption::SharedDtor() { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { + delete identifier_value_; + } + if (string_value_ != &::google::protobuf::internal::kEmptyString) { + delete string_value_; + } + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + delete aggregate_value_; + } + if (this != default_instance_) { + } +} + +void UninterpretedOption::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* UninterpretedOption::descriptor() { + protobuf_AssignDescriptorsOnce(); + return UninterpretedOption_descriptor_; +} + +const UninterpretedOption& UninterpretedOption::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +UninterpretedOption* UninterpretedOption::default_instance_ = NULL; + +UninterpretedOption* UninterpretedOption::New() const { + return new UninterpretedOption; +} + +void UninterpretedOption::Clear() { + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { + if (has_identifier_value()) { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { + identifier_value_->clear(); + } + } + positive_int_value_ = GOOGLE_ULONGLONG(0); + negative_int_value_ = GOOGLE_LONGLONG(0); + double_value_ = 0; + if (has_string_value()) { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { + string_value_->clear(); + } + } + if (has_aggregate_value()) { + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + aggregate_value_->clear(); + } + } + } + name_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool UninterpretedOption::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_name())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_name; + if (input->ExpectTag(26)) goto parse_identifier_value; + break; + } + + // optional string identifier_value = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_identifier_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_identifier_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(32)) goto parse_positive_int_value; + break; + } + + // optional uint64 positive_int_value = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_positive_int_value: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( + input, &positive_int_value_))); + set_has_positive_int_value(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(40)) goto parse_negative_int_value; + break; + } + + // optional int64 negative_int_value = 5; + case 5: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + parse_negative_int_value: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( + input, &negative_int_value_))); + set_has_negative_int_value(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(49)) goto parse_double_value; + break; + } + + // optional double double_value = 6; + case 6: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + parse_double_value: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &double_value_))); + set_has_double_value(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(58)) goto parse_string_value; + break; + } + + // optional bytes string_value = 7; + case 7: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_string_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( + input, this->mutable_string_value())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(66)) goto parse_aggregate_value; + break; + } + + // optional string aggregate_value = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_aggregate_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_aggregate_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void UninterpretedOption::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + for (int i = 0; i < this->name_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 2, this->name(i), output); + } + + // optional string identifier_value = 3; + if (has_identifier_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->identifier_value(), output); + } + + // optional uint64 positive_int_value = 4; + if (has_positive_int_value()) { + ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output); + } + + // optional int64 negative_int_value = 5; + if (has_negative_int_value()) { + ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output); + } + + // optional double double_value = 6; + if (has_double_value()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output); + } + + // optional bytes string_value = 7; + if (has_string_value()) { + ::google::protobuf::internal::WireFormatLite::WriteBytes( + 7, this->string_value(), output); + } + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 8, this->aggregate_value(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* UninterpretedOption::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + for (int i = 0; i < this->name_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 2, this->name(i), target); + } + + // optional string identifier_value = 3; + if (has_identifier_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->identifier_value().data(), this->identifier_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->identifier_value(), target); + } + + // optional uint64 positive_int_value = 4; + if (has_positive_int_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target); + } + + // optional int64 negative_int_value = 5; + if (has_negative_int_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target); + } + + // optional double double_value = 6; + if (has_double_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target); + } + + // optional bytes string_value = 7; + if (has_string_value()) { + target = + ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( + 7, this->string_value(), target); + } + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 8, this->aggregate_value(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int UninterpretedOption::ByteSize() const { + int total_size = 0; + + if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { + // optional string identifier_value = 3; + if (has_identifier_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->identifier_value()); + } + + // optional uint64 positive_int_value = 4; + if (has_positive_int_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::UInt64Size( + this->positive_int_value()); + } + + // optional int64 negative_int_value = 5; + if (has_negative_int_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int64Size( + this->negative_int_value()); + } + + // optional double double_value = 6; + if (has_double_value()) { + total_size += 1 + 8; + } + + // optional bytes string_value = 7; + if (has_string_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::BytesSize( + this->string_value()); + } + + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->aggregate_value()); + } + + } + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + total_size += 1 * this->name_size(); + for (int i = 0; i < this->name_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->name(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const UninterpretedOption* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { + GOOGLE_CHECK_NE(&from, this); + name_.MergeFrom(from.name_); + if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { + if (from.has_identifier_value()) { + set_identifier_value(from.identifier_value()); + } + if (from.has_positive_int_value()) { + set_positive_int_value(from.positive_int_value()); + } + if (from.has_negative_int_value()) { + set_negative_int_value(from.negative_int_value()); + } + if (from.has_double_value()) { + set_double_value(from.double_value()); + } + if (from.has_string_value()) { + set_string_value(from.string_value()); + } + if (from.has_aggregate_value()) { + set_aggregate_value(from.aggregate_value()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UninterpretedOption::IsInitialized() const { + + for (int i = 0; i < name_size(); i++) { + if (!this->name(i).IsInitialized()) return false; + } + return true; +} + +void UninterpretedOption::Swap(UninterpretedOption* other) { + if (other != this) { + name_.Swap(&other->name_); + std::swap(identifier_value_, other->identifier_value_); + std::swap(positive_int_value_, other->positive_int_value_); + std::swap(negative_int_value_, other->negative_int_value_); + std::swap(double_value_, other->double_value_); + std::swap(string_value_, other->string_value_); + std::swap(aggregate_value_, other->aggregate_value_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata UninterpretedOption::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = UninterpretedOption_descriptor_; + metadata.reflection = UninterpretedOption_reflection_; + return metadata; +} + + +// =================================================================== + +#ifndef _MSC_VER +const int SourceCodeInfo_Location::kPathFieldNumber; +const int SourceCodeInfo_Location::kSpanFieldNumber; +const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber; +const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo_Location::SourceCodeInfo_Location() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SourceCodeInfo_Location::InitAsDefaultInstance() { +} + +SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SourceCodeInfo_Location::SharedCtor() { + _cached_size_ = 0; + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo_Location::~SourceCodeInfo_Location() { + SharedDtor(); +} + +void SourceCodeInfo_Location::SharedDtor() { + if (leading_comments_ != &::google::protobuf::internal::kEmptyString) { + delete leading_comments_; + } + if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) { + delete trailing_comments_; + } + if (this != default_instance_) { + } +} + +void SourceCodeInfo_Location::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_Location_descriptor_; +} + +const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL; + +SourceCodeInfo_Location* SourceCodeInfo_Location::New() const { + return new SourceCodeInfo_Location; +} + +void SourceCodeInfo_Location::Clear() { + if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) { + if (has_leading_comments()) { + if (leading_comments_ != &::google::protobuf::internal::kEmptyString) { + leading_comments_->clear(); + } + } + if (has_trailing_comments()) { + if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) { + trailing_comments_->clear(); + } + } + } + path_.Clear(); + span_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo_Location::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated int32 path = 1 [packed = true]; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_path()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 10, input, this->mutable_path()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(18)) goto parse_span; + break; + } + + // repeated int32 span = 2 [packed = true]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_span: + DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, this->mutable_span()))); + } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) + == ::google::protobuf::internal::WireFormatLite:: + WIRETYPE_VARINT) { + DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + 1, 18, input, this->mutable_span()))); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(26)) goto parse_leading_comments; + break; + } + + // optional string leading_comments = 3; + case 3: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_leading_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_leading_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(34)) goto parse_trailing_comments; + break; + } + + // optional string trailing_comments = 4; + case 4: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_trailing_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_trailing_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SourceCodeInfo_Location::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated int32 path = 1 [packed = true]; + if (this->path_size() > 0) { + ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(_path_cached_byte_size_); + } + for (int i = 0; i < this->path_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->path(i), output); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(_span_cached_byte_size_); + } + for (int i = 0; i < this->span_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->span(i), output); + } + + // optional string leading_comments = 3; + if (has_leading_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 3, this->leading_comments(), output); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 4, this->trailing_comments(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated int32 path = 1 [packed = true]; + if (this->path_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 1, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _path_cached_byte_size_, target); + } + for (int i = 0; i < this->path_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->path(i), target); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 2, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _span_cached_byte_size_, target); + } + for (int i = 0; i < this->span_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->span(i), target); + } + + // optional string leading_comments = 3; + if (has_leading_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->leading_comments().data(), this->leading_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->leading_comments(), target); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->trailing_comments().data(), this->trailing_comments().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 4, this->trailing_comments(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SourceCodeInfo_Location::ByteSize() const { + int total_size = 0; + + if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) { + // optional string leading_comments = 3; + if (has_leading_comments()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->leading_comments()); + } + + // optional string trailing_comments = 4; + if (has_trailing_comments()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->trailing_comments()); + } + + } + // repeated int32 path = 1 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->path_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->path(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _path_cached_byte_size_ = data_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + total_size += data_size; + } + + // repeated int32 span = 2 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->span_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->span(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _span_cached_byte_size_ = data_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + total_size += data_size; + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo_Location* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { + GOOGLE_CHECK_NE(&from, this); + path_.MergeFrom(from.path_); + span_.MergeFrom(from.span_); + if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) { + if (from.has_leading_comments()) { + set_leading_comments(from.leading_comments()); + } + if (from.has_trailing_comments()) { + set_trailing_comments(from.trailing_comments()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo_Location::IsInitialized() const { + + return true; +} + +void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) { + if (other != this) { + path_.Swap(&other->path_); + span_.Swap(&other->span_); + std::swap(leading_comments_, other->leading_comments_); + std::swap(trailing_comments_, other->trailing_comments_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_Location_descriptor_; + metadata.reflection = SourceCodeInfo_Location_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int SourceCodeInfo::kLocationFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo::SourceCodeInfo() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SourceCodeInfo::InitAsDefaultInstance() { +} + +SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SourceCodeInfo::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo::~SourceCodeInfo() { + SharedDtor(); +} + +void SourceCodeInfo::SharedDtor() { + if (this != default_instance_) { + } +} + +void SourceCodeInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_descriptor_; +} + +const SourceCodeInfo& SourceCodeInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL; + +SourceCodeInfo* SourceCodeInfo::New() const { + return new SourceCodeInfo; +} + +void SourceCodeInfo::Clear() { + location_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + case 1: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_location: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_location())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_location; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SourceCodeInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->location(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->location(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SourceCodeInfo::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + total_size += 1 * this->location_size(); + for (int i = 0; i < this->location_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->location(i)); + } + + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { + GOOGLE_CHECK_NE(&from, this); + location_.MergeFrom(from.location_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo::IsInitialized() const { + + return true; +} + +void SourceCodeInfo::Swap(SourceCodeInfo* other) { + if (other != this) { + location_.Swap(&other->location_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_descriptor_; + metadata.reflection = SourceCodeInfo_reflection_; + return metadata; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.h new file mode 100644 index 000000000..07cf8077c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.pb.h @@ -0,0 +1,5992 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/descriptor.proto + +#ifndef PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED +#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 2005000 +#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 2005000 < 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 +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { + +// Internal implementation detail -- do not call these. +void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); +void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); +void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + +class FileDescriptorSet; +class FileDescriptorProto; +class DescriptorProto; +class DescriptorProto_ExtensionRange; +class FieldDescriptorProto; +class EnumDescriptorProto; +class EnumValueDescriptorProto; +class ServiceDescriptorProto; +class MethodDescriptorProto; +class FileOptions; +class MessageOptions; +class FieldOptions; +class EnumOptions; +class EnumValueOptions; +class ServiceOptions; +class MethodOptions; +class UninterpretedOption; +class UninterpretedOption_NamePart; +class SourceCodeInfo; +class SourceCodeInfo_Location; + +enum FieldDescriptorProto_Type { + FieldDescriptorProto_Type_TYPE_DOUBLE = 1, + FieldDescriptorProto_Type_TYPE_FLOAT = 2, + FieldDescriptorProto_Type_TYPE_INT64 = 3, + FieldDescriptorProto_Type_TYPE_UINT64 = 4, + FieldDescriptorProto_Type_TYPE_INT32 = 5, + FieldDescriptorProto_Type_TYPE_FIXED64 = 6, + FieldDescriptorProto_Type_TYPE_FIXED32 = 7, + FieldDescriptorProto_Type_TYPE_BOOL = 8, + FieldDescriptorProto_Type_TYPE_STRING = 9, + FieldDescriptorProto_Type_TYPE_GROUP = 10, + FieldDescriptorProto_Type_TYPE_MESSAGE = 11, + FieldDescriptorProto_Type_TYPE_BYTES = 12, + FieldDescriptorProto_Type_TYPE_UINT32 = 13, + FieldDescriptorProto_Type_TYPE_ENUM = 14, + FieldDescriptorProto_Type_TYPE_SFIXED32 = 15, + FieldDescriptorProto_Type_TYPE_SFIXED64 = 16, + FieldDescriptorProto_Type_TYPE_SINT32 = 17, + FieldDescriptorProto_Type_TYPE_SINT64 = 18 +}; +LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value); +const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE; +const FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64; +const int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor(); +inline const ::std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) { + return ::google::protobuf::internal::NameOfEnum( + FieldDescriptorProto_Type_descriptor(), value); +} +inline bool FieldDescriptorProto_Type_Parse( + const ::std::string& name, FieldDescriptorProto_Type* value) { + return ::google::protobuf::internal::ParseNamedEnum( + FieldDescriptorProto_Type_descriptor(), name, value); +} +enum FieldDescriptorProto_Label { + FieldDescriptorProto_Label_LABEL_OPTIONAL = 1, + FieldDescriptorProto_Label_LABEL_REQUIRED = 2, + FieldDescriptorProto_Label_LABEL_REPEATED = 3 +}; +LIBPROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value); +const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL; +const FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED; +const int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor(); +inline const ::std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) { + return ::google::protobuf::internal::NameOfEnum( + FieldDescriptorProto_Label_descriptor(), value); +} +inline bool FieldDescriptorProto_Label_Parse( + const ::std::string& name, FieldDescriptorProto_Label* value) { + return ::google::protobuf::internal::ParseNamedEnum( + FieldDescriptorProto_Label_descriptor(), name, value); +} +enum FileOptions_OptimizeMode { + FileOptions_OptimizeMode_SPEED = 1, + FileOptions_OptimizeMode_CODE_SIZE = 2, + FileOptions_OptimizeMode_LITE_RUNTIME = 3 +}; +LIBPROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value); +const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED; +const FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME; +const int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor(); +inline const ::std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) { + return ::google::protobuf::internal::NameOfEnum( + FileOptions_OptimizeMode_descriptor(), value); +} +inline bool FileOptions_OptimizeMode_Parse( + const ::std::string& name, FileOptions_OptimizeMode* value) { + return ::google::protobuf::internal::ParseNamedEnum( + FileOptions_OptimizeMode_descriptor(), name, value); +} +enum FieldOptions_CType { + FieldOptions_CType_STRING = 0, + FieldOptions_CType_CORD = 1, + FieldOptions_CType_STRING_PIECE = 2 +}; +LIBPROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value); +const FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING; +const FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE; +const int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor(); +inline const ::std::string& FieldOptions_CType_Name(FieldOptions_CType value) { + return ::google::protobuf::internal::NameOfEnum( + FieldOptions_CType_descriptor(), value); +} +inline bool FieldOptions_CType_Parse( + const ::std::string& name, FieldOptions_CType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + FieldOptions_CType_descriptor(), name, value); +} +// =================================================================== + +class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message { + public: + FileDescriptorSet(); + virtual ~FileDescriptorSet(); + + FileDescriptorSet(const FileDescriptorSet& from); + + inline FileDescriptorSet& operator=(const FileDescriptorSet& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FileDescriptorSet& default_instance(); + + void Swap(FileDescriptorSet* other); + + // implements Message ---------------------------------------------- + + FileDescriptorSet* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FileDescriptorSet& from); + void MergeFrom(const FileDescriptorSet& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.FileDescriptorProto file = 1; + inline int file_size() const; + inline void clear_file(); + static const int kFileFieldNumber = 1; + inline const ::google::protobuf::FileDescriptorProto& file(int index) const; + inline ::google::protobuf::FileDescriptorProto* mutable_file(int index); + inline ::google::protobuf::FileDescriptorProto* add_file(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + file() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + mutable_file(); + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static FileDescriptorSet* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Message { + public: + FileDescriptorProto(); + virtual ~FileDescriptorProto(); + + FileDescriptorProto(const FileDescriptorProto& from); + + inline FileDescriptorProto& operator=(const FileDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FileDescriptorProto& default_instance(); + + void Swap(FileDescriptorProto* other); + + // implements Message ---------------------------------------------- + + FileDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FileDescriptorProto& from); + void MergeFrom(const FileDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // optional string package = 2; + inline bool has_package() const; + inline void clear_package(); + static const int kPackageFieldNumber = 2; + inline const ::std::string& package() const; + inline void set_package(const ::std::string& value); + inline void set_package(const char* value); + inline void set_package(const char* value, size_t size); + inline ::std::string* mutable_package(); + inline ::std::string* release_package(); + inline void set_allocated_package(::std::string* package); + + // repeated string dependency = 3; + inline int dependency_size() const; + inline void clear_dependency(); + static const int kDependencyFieldNumber = 3; + inline const ::std::string& dependency(int index) const; + inline ::std::string* mutable_dependency(int index); + inline void set_dependency(int index, const ::std::string& value); + inline void set_dependency(int index, const char* value); + inline void set_dependency(int index, const char* value, size_t size); + inline ::std::string* add_dependency(); + inline void add_dependency(const ::std::string& value); + inline void add_dependency(const char* value); + inline void add_dependency(const char* value, size_t size); + inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; + inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); + + // repeated int32 public_dependency = 10; + inline int public_dependency_size() const; + inline void clear_public_dependency(); + static const int kPublicDependencyFieldNumber = 10; + inline ::google::protobuf::int32 public_dependency(int index) const; + inline void set_public_dependency(int index, ::google::protobuf::int32 value); + inline void add_public_dependency(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + public_dependency() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_public_dependency(); + + // repeated int32 weak_dependency = 11; + inline int weak_dependency_size() const; + inline void clear_weak_dependency(); + static const int kWeakDependencyFieldNumber = 11; + inline ::google::protobuf::int32 weak_dependency(int index) const; + inline void set_weak_dependency(int index, ::google::protobuf::int32 value); + inline void add_weak_dependency(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + weak_dependency() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_weak_dependency(); + + // repeated .google.protobuf.DescriptorProto message_type = 4; + inline int message_type_size() const; + inline void clear_message_type(); + static const int kMessageTypeFieldNumber = 4; + inline const ::google::protobuf::DescriptorProto& message_type(int index) const; + inline ::google::protobuf::DescriptorProto* mutable_message_type(int index); + inline ::google::protobuf::DescriptorProto* add_message_type(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + message_type() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + mutable_message_type(); + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + inline int enum_type_size() const; + inline void clear_enum_type(); + static const int kEnumTypeFieldNumber = 5; + inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + enum_type() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + mutable_enum_type(); + + // repeated .google.protobuf.ServiceDescriptorProto service = 6; + inline int service_size() const; + inline void clear_service(); + static const int kServiceFieldNumber = 6; + inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const; + inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); + inline ::google::protobuf::ServiceDescriptorProto* add_service(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& + service() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* + mutable_service(); + + // repeated .google.protobuf.FieldDescriptorProto extension = 7; + inline int extension_size() const; + inline void clear_extension(); + static const int kExtensionFieldNumber = 7; + inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + inline ::google::protobuf::FieldDescriptorProto* add_extension(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + extension() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + mutable_extension(); + + // optional .google.protobuf.FileOptions options = 8; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 8; + inline const ::google::protobuf::FileOptions& options() const; + inline ::google::protobuf::FileOptions* mutable_options(); + inline ::google::protobuf::FileOptions* release_options(); + inline void set_allocated_options(::google::protobuf::FileOptions* options); + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + inline bool has_source_code_info() const; + inline void clear_source_code_info(); + static const int kSourceCodeInfoFieldNumber = 9; + inline const ::google::protobuf::SourceCodeInfo& source_code_info() const; + inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); + inline ::google::protobuf::SourceCodeInfo* release_source_code_info(); + inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); + + // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_package(); + inline void clear_has_package(); + inline void set_has_options(); + inline void clear_has_options(); + inline void set_has_source_code_info(); + inline void clear_has_source_code_info(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::std::string* package_; + ::google::protobuf::RepeatedPtrField< ::std::string> dependency_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; + ::google::protobuf::FileOptions* options_; + ::google::protobuf::SourceCodeInfo* source_code_info_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static FileDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::protobuf::Message { + public: + DescriptorProto_ExtensionRange(); + virtual ~DescriptorProto_ExtensionRange(); + + DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from); + + inline DescriptorProto_ExtensionRange& operator=(const DescriptorProto_ExtensionRange& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const DescriptorProto_ExtensionRange& default_instance(); + + void Swap(DescriptorProto_ExtensionRange* other); + + // implements Message ---------------------------------------------- + + DescriptorProto_ExtensionRange* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const DescriptorProto_ExtensionRange& from); + void MergeFrom(const DescriptorProto_ExtensionRange& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional int32 start = 1; + inline bool has_start() const; + inline void clear_start(); + static const int kStartFieldNumber = 1; + inline ::google::protobuf::int32 start() const; + inline void set_start(::google::protobuf::int32 value); + + // optional int32 end = 2; + inline bool has_end() const; + inline void clear_end(); + static const int kEndFieldNumber = 2; + inline ::google::protobuf::int32 end() const; + inline void set_end(::google::protobuf::int32 value); + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) + private: + inline void set_has_start(); + inline void clear_has_start(); + inline void set_has_end(); + inline void clear_has_end(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::int32 start_; + ::google::protobuf::int32 end_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static DescriptorProto_ExtensionRange* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { + public: + DescriptorProto(); + virtual ~DescriptorProto(); + + DescriptorProto(const DescriptorProto& from); + + inline DescriptorProto& operator=(const DescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const DescriptorProto& default_instance(); + + void Swap(DescriptorProto* other); + + // implements Message ---------------------------------------------- + + DescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const DescriptorProto& from); + void MergeFrom(const DescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef DescriptorProto_ExtensionRange ExtensionRange; + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // repeated .google.protobuf.FieldDescriptorProto field = 2; + inline int field_size() const; + inline void clear_field(); + static const int kFieldFieldNumber = 2; + inline const ::google::protobuf::FieldDescriptorProto& field(int index) const; + inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index); + inline ::google::protobuf::FieldDescriptorProto* add_field(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + field() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + mutable_field(); + + // repeated .google.protobuf.FieldDescriptorProto extension = 6; + inline int extension_size() const; + inline void clear_extension(); + static const int kExtensionFieldNumber = 6; + inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + inline ::google::protobuf::FieldDescriptorProto* add_extension(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + extension() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + mutable_extension(); + + // repeated .google.protobuf.DescriptorProto nested_type = 3; + inline int nested_type_size() const; + inline void clear_nested_type(); + static const int kNestedTypeFieldNumber = 3; + inline const ::google::protobuf::DescriptorProto& nested_type(int index) const; + inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index); + inline ::google::protobuf::DescriptorProto* add_nested_type(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + nested_type() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + mutable_nested_type(); + + // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + inline int enum_type_size() const; + inline void clear_enum_type(); + static const int kEnumTypeFieldNumber = 4; + inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + enum_type() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + mutable_enum_type(); + + // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + inline int extension_range_size() const; + inline void clear_extension_range(); + static const int kExtensionRangeFieldNumber = 5; + inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; + inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); + inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& + extension_range() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* + mutable_extension_range(); + + // optional .google.protobuf.MessageOptions options = 7; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 7; + inline const ::google::protobuf::MessageOptions& options() const; + inline ::google::protobuf::MessageOptions* mutable_options(); + inline ::google::protobuf::MessageOptions* release_options(); + inline void set_allocated_options(::google::protobuf::MessageOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_; + ::google::protobuf::MessageOptions* options_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static DescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Message { + public: + FieldDescriptorProto(); + virtual ~FieldDescriptorProto(); + + FieldDescriptorProto(const FieldDescriptorProto& from); + + inline FieldDescriptorProto& operator=(const FieldDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FieldDescriptorProto& default_instance(); + + void Swap(FieldDescriptorProto* other); + + // implements Message ---------------------------------------------- + + FieldDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FieldDescriptorProto& from); + void MergeFrom(const FieldDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef FieldDescriptorProto_Type Type; + static const Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE; + static const Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT; + static const Type TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64; + static const Type TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64; + static const Type TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32; + static const Type TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64; + static const Type TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32; + static const Type TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL; + static const Type TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING; + static const Type TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP; + static const Type TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE; + static const Type TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES; + static const Type TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32; + static const Type TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM; + static const Type TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32; + static const Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64; + static const Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32; + static const Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64; + static inline bool Type_IsValid(int value) { + return FieldDescriptorProto_Type_IsValid(value); + } + static const Type Type_MIN = + FieldDescriptorProto_Type_Type_MIN; + static const Type Type_MAX = + FieldDescriptorProto_Type_Type_MAX; + static const int Type_ARRAYSIZE = + FieldDescriptorProto_Type_Type_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Type_descriptor() { + return FieldDescriptorProto_Type_descriptor(); + } + static inline const ::std::string& Type_Name(Type value) { + return FieldDescriptorProto_Type_Name(value); + } + static inline bool Type_Parse(const ::std::string& name, + Type* value) { + return FieldDescriptorProto_Type_Parse(name, value); + } + + typedef FieldDescriptorProto_Label Label; + static const Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL; + static const Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED; + static const Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED; + static inline bool Label_IsValid(int value) { + return FieldDescriptorProto_Label_IsValid(value); + } + static const Label Label_MIN = + FieldDescriptorProto_Label_Label_MIN; + static const Label Label_MAX = + FieldDescriptorProto_Label_Label_MAX; + static const int Label_ARRAYSIZE = + FieldDescriptorProto_Label_Label_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + Label_descriptor() { + return FieldDescriptorProto_Label_descriptor(); + } + static inline const ::std::string& Label_Name(Label value) { + return FieldDescriptorProto_Label_Name(value); + } + static inline bool Label_Parse(const ::std::string& name, + Label* value) { + return FieldDescriptorProto_Label_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // optional int32 number = 3; + inline bool has_number() const; + inline void clear_number(); + static const int kNumberFieldNumber = 3; + inline ::google::protobuf::int32 number() const; + inline void set_number(::google::protobuf::int32 value); + + // optional .google.protobuf.FieldDescriptorProto.Label label = 4; + inline bool has_label() const; + inline void clear_label(); + static const int kLabelFieldNumber = 4; + inline ::google::protobuf::FieldDescriptorProto_Label label() const; + inline void set_label(::google::protobuf::FieldDescriptorProto_Label value); + + // optional .google.protobuf.FieldDescriptorProto.Type type = 5; + inline bool has_type() const; + inline void clear_type(); + static const int kTypeFieldNumber = 5; + inline ::google::protobuf::FieldDescriptorProto_Type type() const; + inline void set_type(::google::protobuf::FieldDescriptorProto_Type value); + + // optional string type_name = 6; + inline bool has_type_name() const; + inline void clear_type_name(); + static const int kTypeNameFieldNumber = 6; + inline const ::std::string& type_name() const; + inline void set_type_name(const ::std::string& value); + inline void set_type_name(const char* value); + inline void set_type_name(const char* value, size_t size); + inline ::std::string* mutable_type_name(); + inline ::std::string* release_type_name(); + inline void set_allocated_type_name(::std::string* type_name); + + // optional string extendee = 2; + inline bool has_extendee() const; + inline void clear_extendee(); + static const int kExtendeeFieldNumber = 2; + inline const ::std::string& extendee() const; + inline void set_extendee(const ::std::string& value); + inline void set_extendee(const char* value); + inline void set_extendee(const char* value, size_t size); + inline ::std::string* mutable_extendee(); + inline ::std::string* release_extendee(); + inline void set_allocated_extendee(::std::string* extendee); + + // optional string default_value = 7; + inline bool has_default_value() const; + inline void clear_default_value(); + static const int kDefaultValueFieldNumber = 7; + inline const ::std::string& default_value() const; + inline void set_default_value(const ::std::string& value); + inline void set_default_value(const char* value); + inline void set_default_value(const char* value, size_t size); + inline ::std::string* mutable_default_value(); + inline ::std::string* release_default_value(); + inline void set_allocated_default_value(::std::string* default_value); + + // optional .google.protobuf.FieldOptions options = 8; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 8; + inline const ::google::protobuf::FieldOptions& options() const; + inline ::google::protobuf::FieldOptions* mutable_options(); + inline ::google::protobuf::FieldOptions* release_options(); + inline void set_allocated_options(::google::protobuf::FieldOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_label(); + inline void clear_has_label(); + inline void set_has_type(); + inline void clear_has_type(); + inline void set_has_type_name(); + inline void clear_has_type_name(); + inline void set_has_extendee(); + inline void clear_has_extendee(); + inline void set_has_default_value(); + inline void clear_has_default_value(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::google::protobuf::int32 number_; + int label_; + ::std::string* type_name_; + ::std::string* extendee_; + ::std::string* default_value_; + ::google::protobuf::FieldOptions* options_; + int type_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static FieldDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Message { + public: + EnumDescriptorProto(); + virtual ~EnumDescriptorProto(); + + EnumDescriptorProto(const EnumDescriptorProto& from); + + inline EnumDescriptorProto& operator=(const EnumDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EnumDescriptorProto& default_instance(); + + void Swap(EnumDescriptorProto* other); + + // implements Message ---------------------------------------------- + + EnumDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EnumDescriptorProto& from); + void MergeFrom(const EnumDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // repeated .google.protobuf.EnumValueDescriptorProto value = 2; + inline int value_size() const; + inline void clear_value(); + static const int kValueFieldNumber = 2; + inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; + inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); + inline ::google::protobuf::EnumValueDescriptorProto* add_value(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& + value() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* + mutable_value(); + + // optional .google.protobuf.EnumOptions options = 3; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 3; + inline const ::google::protobuf::EnumOptions& options() const; + inline ::google::protobuf::EnumOptions* mutable_options(); + inline ::google::protobuf::EnumOptions* release_options(); + inline void set_allocated_options(::google::protobuf::EnumOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; + ::google::protobuf::EnumOptions* options_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static EnumDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::Message { + public: + EnumValueDescriptorProto(); + virtual ~EnumValueDescriptorProto(); + + EnumValueDescriptorProto(const EnumValueDescriptorProto& from); + + inline EnumValueDescriptorProto& operator=(const EnumValueDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EnumValueDescriptorProto& default_instance(); + + void Swap(EnumValueDescriptorProto* other); + + // implements Message ---------------------------------------------- + + EnumValueDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EnumValueDescriptorProto& from); + void MergeFrom(const EnumValueDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // optional int32 number = 2; + inline bool has_number() const; + inline void clear_number(); + static const int kNumberFieldNumber = 2; + inline ::google::protobuf::int32 number() const; + inline void set_number(::google::protobuf::int32 value); + + // optional .google.protobuf.EnumValueOptions options = 3; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 3; + inline const ::google::protobuf::EnumValueOptions& options() const; + inline ::google::protobuf::EnumValueOptions* mutable_options(); + inline ::google::protobuf::EnumValueOptions* release_options(); + inline void set_allocated_options(::google::protobuf::EnumValueOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::google::protobuf::EnumValueOptions* options_; + ::google::protobuf::int32 number_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static EnumValueDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Message { + public: + ServiceDescriptorProto(); + virtual ~ServiceDescriptorProto(); + + ServiceDescriptorProto(const ServiceDescriptorProto& from); + + inline ServiceDescriptorProto& operator=(const ServiceDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ServiceDescriptorProto& default_instance(); + + void Swap(ServiceDescriptorProto* other); + + // implements Message ---------------------------------------------- + + ServiceDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ServiceDescriptorProto& from); + void MergeFrom(const ServiceDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // repeated .google.protobuf.MethodDescriptorProto method = 2; + inline int method_size() const; + inline void clear_method(); + static const int kMethodFieldNumber = 2; + inline const ::google::protobuf::MethodDescriptorProto& method(int index) const; + inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index); + inline ::google::protobuf::MethodDescriptorProto* add_method(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& + method() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* + mutable_method(); + + // optional .google.protobuf.ServiceOptions options = 3; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 3; + inline const ::google::protobuf::ServiceOptions& options() const; + inline ::google::protobuf::ServiceOptions* mutable_options(); + inline ::google::protobuf::ServiceOptions* release_options(); + inline void set_allocated_options(::google::protobuf::ServiceOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; + ::google::protobuf::ServiceOptions* options_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static ServiceDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Message { + public: + MethodDescriptorProto(); + virtual ~MethodDescriptorProto(); + + MethodDescriptorProto(const MethodDescriptorProto& from); + + inline MethodDescriptorProto& operator=(const MethodDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const MethodDescriptorProto& default_instance(); + + void Swap(MethodDescriptorProto* other); + + // implements Message ---------------------------------------------- + + MethodDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const MethodDescriptorProto& from); + void MergeFrom(const MethodDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // optional string input_type = 2; + inline bool has_input_type() const; + inline void clear_input_type(); + static const int kInputTypeFieldNumber = 2; + inline const ::std::string& input_type() const; + inline void set_input_type(const ::std::string& value); + inline void set_input_type(const char* value); + inline void set_input_type(const char* value, size_t size); + inline ::std::string* mutable_input_type(); + inline ::std::string* release_input_type(); + inline void set_allocated_input_type(::std::string* input_type); + + // optional string output_type = 3; + inline bool has_output_type() const; + inline void clear_output_type(); + static const int kOutputTypeFieldNumber = 3; + inline const ::std::string& output_type() const; + inline void set_output_type(const ::std::string& value); + inline void set_output_type(const char* value); + inline void set_output_type(const char* value, size_t size); + inline ::std::string* mutable_output_type(); + inline ::std::string* release_output_type(); + inline void set_allocated_output_type(::std::string* output_type); + + // optional .google.protobuf.MethodOptions options = 4; + inline bool has_options() const; + inline void clear_options(); + static const int kOptionsFieldNumber = 4; + inline const ::google::protobuf::MethodOptions& options() const; + inline ::google::protobuf::MethodOptions* mutable_options(); + inline ::google::protobuf::MethodOptions* release_options(); + inline void set_allocated_options(::google::protobuf::MethodOptions* options); + + // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_input_type(); + inline void clear_has_input_type(); + inline void set_has_output_type(); + inline void clear_has_output_type(); + inline void set_has_options(); + inline void clear_has_options(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_; + ::std::string* input_type_; + ::std::string* output_type_; + ::google::protobuf::MethodOptions* options_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static MethodDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { + public: + FileOptions(); + virtual ~FileOptions(); + + FileOptions(const FileOptions& from); + + inline FileOptions& operator=(const FileOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FileOptions& default_instance(); + + void Swap(FileOptions* other); + + // implements Message ---------------------------------------------- + + FileOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FileOptions& from); + void MergeFrom(const FileOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef FileOptions_OptimizeMode OptimizeMode; + static const OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED; + static const OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE; + static const OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME; + static inline bool OptimizeMode_IsValid(int value) { + return FileOptions_OptimizeMode_IsValid(value); + } + static const OptimizeMode OptimizeMode_MIN = + FileOptions_OptimizeMode_OptimizeMode_MIN; + static const OptimizeMode OptimizeMode_MAX = + FileOptions_OptimizeMode_OptimizeMode_MAX; + static const int OptimizeMode_ARRAYSIZE = + FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + OptimizeMode_descriptor() { + return FileOptions_OptimizeMode_descriptor(); + } + static inline const ::std::string& OptimizeMode_Name(OptimizeMode value) { + return FileOptions_OptimizeMode_Name(value); + } + static inline bool OptimizeMode_Parse(const ::std::string& name, + OptimizeMode* value) { + return FileOptions_OptimizeMode_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // optional string java_package = 1; + inline bool has_java_package() const; + inline void clear_java_package(); + static const int kJavaPackageFieldNumber = 1; + inline const ::std::string& java_package() const; + inline void set_java_package(const ::std::string& value); + inline void set_java_package(const char* value); + inline void set_java_package(const char* value, size_t size); + inline ::std::string* mutable_java_package(); + inline ::std::string* release_java_package(); + inline void set_allocated_java_package(::std::string* java_package); + + // optional string java_outer_classname = 8; + inline bool has_java_outer_classname() const; + inline void clear_java_outer_classname(); + static const int kJavaOuterClassnameFieldNumber = 8; + inline const ::std::string& java_outer_classname() const; + inline void set_java_outer_classname(const ::std::string& value); + inline void set_java_outer_classname(const char* value); + inline void set_java_outer_classname(const char* value, size_t size); + inline ::std::string* mutable_java_outer_classname(); + inline ::std::string* release_java_outer_classname(); + inline void set_allocated_java_outer_classname(::std::string* java_outer_classname); + + // optional bool java_multiple_files = 10 [default = false]; + inline bool has_java_multiple_files() const; + inline void clear_java_multiple_files(); + static const int kJavaMultipleFilesFieldNumber = 10; + inline bool java_multiple_files() const; + inline void set_java_multiple_files(bool value); + + // optional bool java_generate_equals_and_hash = 20 [default = false]; + inline bool has_java_generate_equals_and_hash() const; + inline void clear_java_generate_equals_and_hash(); + static const int kJavaGenerateEqualsAndHashFieldNumber = 20; + inline bool java_generate_equals_and_hash() const; + inline void set_java_generate_equals_and_hash(bool value); + + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + inline bool has_optimize_for() const; + inline void clear_optimize_for(); + static const int kOptimizeForFieldNumber = 9; + inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; + inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); + + // optional string go_package = 11; + inline bool has_go_package() const; + inline void clear_go_package(); + static const int kGoPackageFieldNumber = 11; + inline const ::std::string& go_package() const; + inline void set_go_package(const ::std::string& value); + inline void set_go_package(const char* value); + inline void set_go_package(const char* value, size_t size); + inline ::std::string* mutable_go_package(); + inline ::std::string* release_go_package(); + inline void set_allocated_go_package(::std::string* go_package); + + // optional bool cc_generic_services = 16 [default = false]; + inline bool has_cc_generic_services() const; + inline void clear_cc_generic_services(); + static const int kCcGenericServicesFieldNumber = 16; + inline bool cc_generic_services() const; + inline void set_cc_generic_services(bool value); + + // optional bool java_generic_services = 17 [default = false]; + inline bool has_java_generic_services() const; + inline void clear_java_generic_services(); + static const int kJavaGenericServicesFieldNumber = 17; + inline bool java_generic_services() const; + inline void set_java_generic_services(bool value); + + // optional bool py_generic_services = 18 [default = false]; + inline bool has_py_generic_services() const; + inline void clear_py_generic_services(); + static const int kPyGenericServicesFieldNumber = 18; + inline bool py_generic_services() const; + inline void set_py_generic_services(bool value); + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) + private: + inline void set_has_java_package(); + inline void clear_has_java_package(); + inline void set_has_java_outer_classname(); + inline void clear_has_java_outer_classname(); + inline void set_has_java_multiple_files(); + inline void clear_has_java_multiple_files(); + inline void set_has_java_generate_equals_and_hash(); + inline void clear_has_java_generate_equals_and_hash(); + inline void set_has_optimize_for(); + inline void clear_has_optimize_for(); + inline void set_has_go_package(); + inline void clear_has_go_package(); + inline void set_has_cc_generic_services(); + inline void clear_has_cc_generic_services(); + inline void set_has_java_generic_services(); + inline void clear_has_java_generic_services(); + inline void set_has_py_generic_services(); + inline void clear_has_py_generic_services(); + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* java_package_; + ::std::string* java_outer_classname_; + int optimize_for_; + bool java_multiple_files_; + bool java_generate_equals_and_hash_; + bool cc_generic_services_; + bool java_generic_services_; + ::std::string* go_package_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool py_generic_services_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static FileOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { + public: + MessageOptions(); + virtual ~MessageOptions(); + + MessageOptions(const MessageOptions& from); + + inline MessageOptions& operator=(const MessageOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const MessageOptions& default_instance(); + + void Swap(MessageOptions* other); + + // implements Message ---------------------------------------------- + + MessageOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const MessageOptions& from); + void MergeFrom(const MessageOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional bool message_set_wire_format = 1 [default = false]; + inline bool has_message_set_wire_format() const; + inline void clear_message_set_wire_format(); + static const int kMessageSetWireFormatFieldNumber = 1; + inline bool message_set_wire_format() const; + inline void set_message_set_wire_format(bool value); + + // optional bool no_standard_descriptor_accessor = 2 [default = false]; + inline bool has_no_standard_descriptor_accessor() const; + inline void clear_no_standard_descriptor_accessor(); + static const int kNoStandardDescriptorAccessorFieldNumber = 2; + inline bool no_standard_descriptor_accessor() const; + inline void set_no_standard_descriptor_accessor(bool value); + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) + private: + inline void set_has_message_set_wire_format(); + inline void clear_has_message_set_wire_format(); + inline void set_has_no_standard_descriptor_accessor(); + inline void clear_has_no_standard_descriptor_accessor(); + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool message_set_wire_format_; + bool no_standard_descriptor_accessor_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static MessageOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { + public: + FieldOptions(); + virtual ~FieldOptions(); + + FieldOptions(const FieldOptions& from); + + inline FieldOptions& operator=(const FieldOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const FieldOptions& default_instance(); + + void Swap(FieldOptions* other); + + // implements Message ---------------------------------------------- + + FieldOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const FieldOptions& from); + void MergeFrom(const FieldOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef FieldOptions_CType CType; + static const CType STRING = FieldOptions_CType_STRING; + static const CType CORD = FieldOptions_CType_CORD; + static const CType STRING_PIECE = FieldOptions_CType_STRING_PIECE; + static inline bool CType_IsValid(int value) { + return FieldOptions_CType_IsValid(value); + } + static const CType CType_MIN = + FieldOptions_CType_CType_MIN; + static const CType CType_MAX = + FieldOptions_CType_CType_MAX; + static const int CType_ARRAYSIZE = + FieldOptions_CType_CType_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + CType_descriptor() { + return FieldOptions_CType_descriptor(); + } + static inline const ::std::string& CType_Name(CType value) { + return FieldOptions_CType_Name(value); + } + static inline bool CType_Parse(const ::std::string& name, + CType* value) { + return FieldOptions_CType_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + inline bool has_ctype() const; + inline void clear_ctype(); + static const int kCtypeFieldNumber = 1; + inline ::google::protobuf::FieldOptions_CType ctype() const; + inline void set_ctype(::google::protobuf::FieldOptions_CType value); + + // optional bool packed = 2; + inline bool has_packed() const; + inline void clear_packed(); + static const int kPackedFieldNumber = 2; + inline bool packed() const; + inline void set_packed(bool value); + + // optional bool lazy = 5 [default = false]; + inline bool has_lazy() const; + inline void clear_lazy(); + static const int kLazyFieldNumber = 5; + inline bool lazy() const; + inline void set_lazy(bool value); + + // optional bool deprecated = 3 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 3; + inline bool deprecated() const; + inline void set_deprecated(bool value); + + // optional string experimental_map_key = 9; + inline bool has_experimental_map_key() const; + inline void clear_experimental_map_key(); + static const int kExperimentalMapKeyFieldNumber = 9; + inline const ::std::string& experimental_map_key() const; + inline void set_experimental_map_key(const ::std::string& value); + inline void set_experimental_map_key(const char* value); + inline void set_experimental_map_key(const char* value, size_t size); + inline ::std::string* mutable_experimental_map_key(); + inline ::std::string* release_experimental_map_key(); + inline void set_allocated_experimental_map_key(::std::string* experimental_map_key); + + // optional bool weak = 10 [default = false]; + inline bool has_weak() const; + inline void clear_weak(); + static const int kWeakFieldNumber = 10; + inline bool weak() const; + inline void set_weak(bool value); + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) + private: + inline void set_has_ctype(); + inline void clear_has_ctype(); + inline void set_has_packed(); + inline void clear_has_packed(); + inline void set_has_lazy(); + inline void clear_has_lazy(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + inline void set_has_experimental_map_key(); + inline void clear_has_experimental_map_key(); + inline void set_has_weak(); + inline void clear_has_weak(); + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + int ctype_; + bool packed_; + bool lazy_; + bool deprecated_; + bool weak_; + ::std::string* experimental_map_key_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static FieldOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { + public: + EnumOptions(); + virtual ~EnumOptions(); + + EnumOptions(const EnumOptions& from); + + inline EnumOptions& operator=(const EnumOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EnumOptions& default_instance(); + + void Swap(EnumOptions* other); + + // implements Message ---------------------------------------------- + + EnumOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EnumOptions& from); + void MergeFrom(const EnumOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional bool allow_alias = 2 [default = true]; + inline bool has_allow_alias() const; + inline void clear_allow_alias(); + static const int kAllowAliasFieldNumber = 2; + inline bool allow_alias() const; + inline void set_allow_alias(bool value); + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) + private: + inline void set_has_allow_alias(); + inline void clear_has_allow_alias(); + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool allow_alias_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static EnumOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { + public: + EnumValueOptions(); + virtual ~EnumValueOptions(); + + EnumValueOptions(const EnumValueOptions& from); + + inline EnumValueOptions& operator=(const EnumValueOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const EnumValueOptions& default_instance(); + + void Swap(EnumValueOptions* other); + + // implements Message ---------------------------------------------- + + EnumValueOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const EnumValueOptions& from); + void MergeFrom(const EnumValueOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) + private: + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static EnumValueOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { + public: + ServiceOptions(); + virtual ~ServiceOptions(); + + ServiceOptions(const ServiceOptions& from); + + inline ServiceOptions& operator=(const ServiceOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const ServiceOptions& default_instance(); + + void Swap(ServiceOptions* other); + + // implements Message ---------------------------------------------- + + ServiceOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const ServiceOptions& from); + void MergeFrom(const ServiceOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) + private: + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static ServiceOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { + public: + MethodOptions(); + virtual ~MethodOptions(); + + MethodOptions(const MethodOptions& from); + + inline MethodOptions& operator=(const MethodOptions& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const MethodOptions& default_instance(); + + void Swap(MethodOptions* other); + + // implements Message ---------------------------------------------- + + MethodOptions* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const MethodOptions& from); + void MergeFrom(const MethodOptions& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + inline int uninterpreted_option_size() const; + inline void clear_uninterpreted_option(); + static const int kUninterpretedOptionFieldNumber = 999; + inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + uninterpreted_option() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + mutable_uninterpreted_option(); + + GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) + // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) + private: + + ::google::protobuf::internal::ExtensionSet _extensions_; + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static MethodOptions* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobuf::Message { + public: + UninterpretedOption_NamePart(); + virtual ~UninterpretedOption_NamePart(); + + UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from); + + inline UninterpretedOption_NamePart& operator=(const UninterpretedOption_NamePart& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const UninterpretedOption_NamePart& default_instance(); + + void Swap(UninterpretedOption_NamePart* other); + + // implements Message ---------------------------------------------- + + UninterpretedOption_NamePart* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const UninterpretedOption_NamePart& from); + void MergeFrom(const UninterpretedOption_NamePart& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // required string name_part = 1; + inline bool has_name_part() const; + inline void clear_name_part(); + static const int kNamePartFieldNumber = 1; + inline const ::std::string& name_part() const; + inline void set_name_part(const ::std::string& value); + inline void set_name_part(const char* value); + inline void set_name_part(const char* value, size_t size); + inline ::std::string* mutable_name_part(); + inline ::std::string* release_name_part(); + inline void set_allocated_name_part(::std::string* name_part); + + // required bool is_extension = 2; + inline bool has_is_extension() const; + inline void clear_is_extension(); + static const int kIsExtensionFieldNumber = 2; + inline bool is_extension() const; + inline void set_is_extension(bool value); + + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) + private: + inline void set_has_name_part(); + inline void clear_has_name_part(); + inline void set_has_is_extension(); + inline void clear_has_is_extension(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::std::string* name_part_; + bool is_extension_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static UninterpretedOption_NamePart* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Message { + public: + UninterpretedOption(); + virtual ~UninterpretedOption(); + + UninterpretedOption(const UninterpretedOption& from); + + inline UninterpretedOption& operator=(const UninterpretedOption& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const UninterpretedOption& default_instance(); + + void Swap(UninterpretedOption* other); + + // implements Message ---------------------------------------------- + + UninterpretedOption* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const UninterpretedOption& from); + void MergeFrom(const UninterpretedOption& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef UninterpretedOption_NamePart NamePart; + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + inline int name_size() const; + inline void clear_name(); + static const int kNameFieldNumber = 2; + inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; + inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); + inline ::google::protobuf::UninterpretedOption_NamePart* add_name(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& + name() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* + mutable_name(); + + // optional string identifier_value = 3; + inline bool has_identifier_value() const; + inline void clear_identifier_value(); + static const int kIdentifierValueFieldNumber = 3; + inline const ::std::string& identifier_value() const; + inline void set_identifier_value(const ::std::string& value); + inline void set_identifier_value(const char* value); + inline void set_identifier_value(const char* value, size_t size); + inline ::std::string* mutable_identifier_value(); + inline ::std::string* release_identifier_value(); + inline void set_allocated_identifier_value(::std::string* identifier_value); + + // optional uint64 positive_int_value = 4; + inline bool has_positive_int_value() const; + inline void clear_positive_int_value(); + static const int kPositiveIntValueFieldNumber = 4; + inline ::google::protobuf::uint64 positive_int_value() const; + inline void set_positive_int_value(::google::protobuf::uint64 value); + + // optional int64 negative_int_value = 5; + inline bool has_negative_int_value() const; + inline void clear_negative_int_value(); + static const int kNegativeIntValueFieldNumber = 5; + inline ::google::protobuf::int64 negative_int_value() const; + inline void set_negative_int_value(::google::protobuf::int64 value); + + // optional double double_value = 6; + inline bool has_double_value() const; + inline void clear_double_value(); + static const int kDoubleValueFieldNumber = 6; + inline double double_value() const; + inline void set_double_value(double value); + + // optional bytes string_value = 7; + inline bool has_string_value() const; + inline void clear_string_value(); + static const int kStringValueFieldNumber = 7; + inline const ::std::string& string_value() const; + inline void set_string_value(const ::std::string& value); + inline void set_string_value(const char* value); + inline void set_string_value(const void* value, size_t size); + inline ::std::string* mutable_string_value(); + inline ::std::string* release_string_value(); + inline void set_allocated_string_value(::std::string* string_value); + + // optional string aggregate_value = 8; + inline bool has_aggregate_value() const; + inline void clear_aggregate_value(); + static const int kAggregateValueFieldNumber = 8; + inline const ::std::string& aggregate_value() const; + inline void set_aggregate_value(const ::std::string& value); + inline void set_aggregate_value(const char* value); + inline void set_aggregate_value(const char* value, size_t size); + inline ::std::string* mutable_aggregate_value(); + inline ::std::string* release_aggregate_value(); + inline void set_allocated_aggregate_value(::std::string* aggregate_value); + + // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) + private: + inline void set_has_identifier_value(); + inline void clear_has_identifier_value(); + inline void set_has_positive_int_value(); + inline void clear_has_positive_int_value(); + inline void set_has_negative_int_value(); + inline void clear_has_negative_int_value(); + inline void set_has_double_value(); + inline void clear_has_double_value(); + inline void set_has_string_value(); + inline void clear_has_string_value(); + inline void set_has_aggregate_value(); + inline void clear_has_aggregate_value(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; + ::std::string* identifier_value_; + ::google::protobuf::uint64 positive_int_value_; + ::google::protobuf::int64 negative_int_value_; + double double_value_; + ::std::string* string_value_; + ::std::string* aggregate_value_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static UninterpretedOption* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message { + public: + SourceCodeInfo_Location(); + virtual ~SourceCodeInfo_Location(); + + SourceCodeInfo_Location(const SourceCodeInfo_Location& from); + + inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceCodeInfo_Location& default_instance(); + + void Swap(SourceCodeInfo_Location* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo_Location* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo_Location& from); + void MergeFrom(const SourceCodeInfo_Location& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated int32 path = 1 [packed = true]; + inline int path_size() const; + inline void clear_path(); + static const int kPathFieldNumber = 1; + inline ::google::protobuf::int32 path(int index) const; + inline void set_path(int index, ::google::protobuf::int32 value); + inline void add_path(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + path() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_path(); + + // repeated int32 span = 2 [packed = true]; + inline int span_size() const; + inline void clear_span(); + static const int kSpanFieldNumber = 2; + inline ::google::protobuf::int32 span(int index) const; + inline void set_span(int index, ::google::protobuf::int32 value); + inline void add_span(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + span() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_span(); + + // optional string leading_comments = 3; + inline bool has_leading_comments() const; + inline void clear_leading_comments(); + static const int kLeadingCommentsFieldNumber = 3; + inline const ::std::string& leading_comments() const; + inline void set_leading_comments(const ::std::string& value); + inline void set_leading_comments(const char* value); + inline void set_leading_comments(const char* value, size_t size); + inline ::std::string* mutable_leading_comments(); + inline ::std::string* release_leading_comments(); + inline void set_allocated_leading_comments(::std::string* leading_comments); + + // optional string trailing_comments = 4; + inline bool has_trailing_comments() const; + inline void clear_trailing_comments(); + static const int kTrailingCommentsFieldNumber = 4; + inline const ::std::string& trailing_comments() const; + inline void set_trailing_comments(const ::std::string& value); + inline void set_trailing_comments(const char* value); + inline void set_trailing_comments(const char* value, size_t size); + inline ::std::string* mutable_trailing_comments(); + inline ::std::string* release_trailing_comments(); + inline void set_allocated_trailing_comments(::std::string* trailing_comments); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + private: + inline void set_has_leading_comments(); + inline void clear_has_leading_comments(); + inline void set_has_trailing_comments(); + inline void clear_has_trailing_comments(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_; + mutable int _path_cached_byte_size_; + ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_; + mutable int _span_cached_byte_size_; + ::std::string* leading_comments_; + ::std::string* trailing_comments_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static SourceCodeInfo_Location* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { + public: + SourceCodeInfo(); + virtual ~SourceCodeInfo(); + + SourceCodeInfo(const SourceCodeInfo& from); + + inline SourceCodeInfo& operator=(const SourceCodeInfo& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceCodeInfo& default_instance(); + + void Swap(SourceCodeInfo* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo& from); + void MergeFrom(const SourceCodeInfo& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + typedef SourceCodeInfo_Location Location; + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + inline int location_size() const; + inline void clear_location(); + static const int kLocationFieldNumber = 1; + inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; + inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); + inline ::google::protobuf::SourceCodeInfo_Location* add_location(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + location() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + mutable_location(); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; + + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static SourceCodeInfo* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// FileDescriptorSet + +// repeated .google.protobuf.FileDescriptorProto file = 1; +inline int FileDescriptorSet::file_size() const { + return file_.size(); +} +inline void FileDescriptorSet::clear_file() { + file_.Clear(); +} +inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { + return file_.Get(index); +} +inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + return file_.Mutable(index); +} +inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { + return file_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +FileDescriptorSet::file() const { + return file_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +FileDescriptorSet::mutable_file() { + return &file_; +} + +// ------------------------------------------------------------------- + +// FileDescriptorProto + +// optional string name = 1; +inline bool FileDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void FileDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& FileDescriptorProto::name() const { + return *name_; +} +inline void FileDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void FileDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void FileDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FileDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* FileDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FileDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string package = 2; +inline bool FileDescriptorProto::has_package() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileDescriptorProto::set_has_package() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileDescriptorProto::clear_has_package() { + _has_bits_[0] &= ~0x00000002u; +} +inline void FileDescriptorProto::clear_package() { + if (package_ != &::google::protobuf::internal::kEmptyString) { + package_->clear(); + } + clear_has_package(); +} +inline const ::std::string& FileDescriptorProto::package() const { + return *package_; +} +inline void FileDescriptorProto::set_package(const ::std::string& value) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + package_ = new ::std::string; + } + package_->assign(value); +} +inline void FileDescriptorProto::set_package(const char* value) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + package_ = new ::std::string; + } + package_->assign(value); +} +inline void FileDescriptorProto::set_package(const char* value, size_t size) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + package_ = new ::std::string; + } + package_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FileDescriptorProto::mutable_package() { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + package_ = new ::std::string; + } + return package_; +} +inline ::std::string* FileDescriptorProto::release_package() { + clear_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = package_; + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FileDescriptorProto::set_allocated_package(::std::string* package) { + if (package_ != &::google::protobuf::internal::kEmptyString) { + delete package_; + } + if (package) { + set_has_package(); + package_ = package; + } else { + clear_has_package(); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated string dependency = 3; +inline int FileDescriptorProto::dependency_size() const { + return dependency_.size(); +} +inline void FileDescriptorProto::clear_dependency() { + dependency_.Clear(); +} +inline const ::std::string& FileDescriptorProto::dependency(int index) const { + return dependency_.Get(index); +} +inline ::std::string* FileDescriptorProto::mutable_dependency(int index) { + return dependency_.Mutable(index); +} +inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { + dependency_.Mutable(index)->assign(value); +} +inline void FileDescriptorProto::set_dependency(int index, const char* value) { + dependency_.Mutable(index)->assign(value); +} +inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { + dependency_.Mutable(index)->assign( + reinterpret_cast(value), size); +} +inline ::std::string* FileDescriptorProto::add_dependency() { + return dependency_.Add(); +} +inline void FileDescriptorProto::add_dependency(const ::std::string& value) { + dependency_.Add()->assign(value); +} +inline void FileDescriptorProto::add_dependency(const char* value) { + dependency_.Add()->assign(value); +} +inline void FileDescriptorProto::add_dependency(const char* value, size_t size) { + dependency_.Add()->assign(reinterpret_cast(value), size); +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +FileDescriptorProto::dependency() const { + return dependency_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +FileDescriptorProto::mutable_dependency() { + return &dependency_; +} + +// repeated int32 public_dependency = 10; +inline int FileDescriptorProto::public_dependency_size() const { + return public_dependency_.size(); +} +inline void FileDescriptorProto::clear_public_dependency() { + public_dependency_.Clear(); +} +inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { + return public_dependency_.Get(index); +} +inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { + public_dependency_.Set(index, value); +} +inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { + public_dependency_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::public_dependency() const { + return public_dependency_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_public_dependency() { + return &public_dependency_; +} + +// repeated int32 weak_dependency = 11; +inline int FileDescriptorProto::weak_dependency_size() const { + return weak_dependency_.size(); +} +inline void FileDescriptorProto::clear_weak_dependency() { + weak_dependency_.Clear(); +} +inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { + return weak_dependency_.Get(index); +} +inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { + weak_dependency_.Set(index, value); +} +inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { + weak_dependency_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::weak_dependency() const { + return weak_dependency_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_weak_dependency() { + return &weak_dependency_; +} + +// repeated .google.protobuf.DescriptorProto message_type = 4; +inline int FileDescriptorProto::message_type_size() const { + return message_type_.size(); +} +inline void FileDescriptorProto::clear_message_type() { + message_type_.Clear(); +} +inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { + return message_type_.Get(index); +} +inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + return message_type_.Mutable(index); +} +inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { + return message_type_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +FileDescriptorProto::message_type() const { + return message_type_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +FileDescriptorProto::mutable_message_type() { + return &message_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 5; +inline int FileDescriptorProto::enum_type_size() const { + return enum_type_.size(); +} +inline void FileDescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} +inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + return enum_type_.Get(index); +} +inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + return enum_type_.Mutable(index); +} +inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + return enum_type_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + return enum_type_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +FileDescriptorProto::mutable_enum_type() { + return &enum_type_; +} + +// repeated .google.protobuf.ServiceDescriptorProto service = 6; +inline int FileDescriptorProto::service_size() const { + return service_.size(); +} +inline void FileDescriptorProto::clear_service() { + service_.Clear(); +} +inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + return service_.Get(index); +} +inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + return service_.Mutable(index); +} +inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { + return service_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + return service_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* +FileDescriptorProto::mutable_service() { + return &service_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 7; +inline int FileDescriptorProto::extension_size() const { + return extension_.size(); +} +inline void FileDescriptorProto::clear_extension() { + extension_.Clear(); +} +inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + return extension_.Get(index); +} +inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + return extension_.Mutable(index); +} +inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { + return extension_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + return extension_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +FileDescriptorProto::mutable_extension() { + return &extension_; +} + +// optional .google.protobuf.FileOptions options = 8; +inline bool FileDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} +inline void FileDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000200u; +} +inline void FileDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000200u; +} +inline void FileDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::FileOptions; + return options_; +} +inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FileOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; +inline bool FileDescriptorProto::has_source_code_info() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void FileDescriptorProto::set_has_source_code_info() { + _has_bits_[0] |= 0x00000400u; +} +inline void FileDescriptorProto::clear_has_source_code_info() { + _has_bits_[0] &= ~0x00000400u; +} +inline void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + clear_has_source_code_info(); +} +inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_; +} +inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + set_has_source_code_info(); + if (source_code_info_ == NULL) source_code_info_ = new ::google::protobuf::SourceCodeInfo; + return source_code_info_; +} +inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + clear_has_source_code_info(); + ::google::protobuf::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = NULL; + return temp; +} +inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { + delete source_code_info_; + source_code_info_ = source_code_info; + if (source_code_info) { + set_has_source_code_info(); + } else { + clear_has_source_code_info(); + } +} + +// ------------------------------------------------------------------- + +// DescriptorProto_ExtensionRange + +// optional int32 start = 1; +inline bool DescriptorProto_ExtensionRange::has_start() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto_ExtensionRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; +} +inline void DescriptorProto_ExtensionRange::clear_start() { + start_ = 0; + clear_has_start(); +} +inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { + return start_; +} +inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { + set_has_start(); + start_ = value; +} + +// optional int32 end = 2; +inline bool DescriptorProto_ExtensionRange::has_end() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} +inline void DescriptorProto_ExtensionRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; +} +inline void DescriptorProto_ExtensionRange::clear_end() { + end_ = 0; + clear_has_end(); +} +inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { + return end_; +} +inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { + set_has_end(); + end_ = value; +} + +// ------------------------------------------------------------------- + +// DescriptorProto + +// optional string name = 1; +inline bool DescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void DescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& DescriptorProto::name() const { + return *name_; +} +inline void DescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void DescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void DescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* DescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* DescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void DescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated .google.protobuf.FieldDescriptorProto field = 2; +inline int DescriptorProto::field_size() const { + return field_.size(); +} +inline void DescriptorProto::clear_field() { + field_.Clear(); +} +inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { + return field_.Get(index); +} +inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + return field_.Mutable(index); +} +inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { + return field_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::field() const { + return field_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_field() { + return &field_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 6; +inline int DescriptorProto::extension_size() const { + return extension_.size(); +} +inline void DescriptorProto::clear_extension() { + extension_.Clear(); +} +inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { + return extension_.Get(index); +} +inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + return extension_.Mutable(index); +} +inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { + return extension_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::extension() const { + return extension_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_extension() { + return &extension_; +} + +// repeated .google.protobuf.DescriptorProto nested_type = 3; +inline int DescriptorProto::nested_type_size() const { + return nested_type_.size(); +} +inline void DescriptorProto::clear_nested_type() { + nested_type_.Clear(); +} +inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { + return nested_type_.Get(index); +} +inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + return nested_type_.Mutable(index); +} +inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { + return nested_type_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +DescriptorProto::nested_type() const { + return nested_type_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +DescriptorProto::mutable_nested_type() { + return &nested_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 4; +inline int DescriptorProto::enum_type_size() const { + return enum_type_.size(); +} +inline void DescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} +inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + return enum_type_.Get(index); +} +inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + return enum_type_.Mutable(index); +} +inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { + return enum_type_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + return enum_type_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +DescriptorProto::mutable_enum_type() { + return &enum_type_; +} + +// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; +inline int DescriptorProto::extension_range_size() const { + return extension_range_.size(); +} +inline void DescriptorProto::clear_extension_range() { + extension_range_.Clear(); +} +inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + return extension_range_.Get(index); +} +inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + return extension_range_.Mutable(index); +} +inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + return extension_range_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& +DescriptorProto::extension_range() const { + return extension_range_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* +DescriptorProto::mutable_extension_range() { + return &extension_range_; +} + +// optional .google.protobuf.MessageOptions options = 7; +inline bool DescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void DescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000040u; +} +inline void DescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000040u; +} +inline void DescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions; + return options_; +} +inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MessageOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// FieldDescriptorProto + +// optional string name = 1; +inline bool FieldDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void FieldDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& FieldDescriptorProto::name() const { + return *name_; +} +inline void FieldDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void FieldDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void FieldDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FieldDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* FieldDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional int32 number = 3; +inline bool FieldDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} +inline void FieldDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} +inline ::google::protobuf::int32 FieldDescriptorProto::number() const { + return number_; +} +inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; +} + +// optional .google.protobuf.FieldDescriptorProto.Label label = 4; +inline bool FieldDescriptorProto::has_label() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldDescriptorProto::set_has_label() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldDescriptorProto::clear_has_label() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FieldDescriptorProto::clear_label() { + label_ = 1; + clear_has_label(); +} +inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); +} +inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { + assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); + set_has_label(); + label_ = value; +} + +// optional .google.protobuf.FieldDescriptorProto.Type type = 5; +inline bool FieldDescriptorProto::has_type() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldDescriptorProto::set_has_type() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldDescriptorProto::clear_has_type() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FieldDescriptorProto::clear_type() { + type_ = 1; + clear_has_type(); +} +inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); +} +inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { + assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); + set_has_type(); + type_ = value; +} + +// optional string type_name = 6; +inline bool FieldDescriptorProto::has_type_name() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FieldDescriptorProto::set_has_type_name() { + _has_bits_[0] |= 0x00000010u; +} +inline void FieldDescriptorProto::clear_has_type_name() { + _has_bits_[0] &= ~0x00000010u; +} +inline void FieldDescriptorProto::clear_type_name() { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { + type_name_->clear(); + } + clear_has_type_name(); +} +inline const ::std::string& FieldDescriptorProto::type_name() const { + return *type_name_; +} +inline void FieldDescriptorProto::set_type_name(const ::std::string& value) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + type_name_ = new ::std::string; + } + type_name_->assign(value); +} +inline void FieldDescriptorProto::set_type_name(const char* value) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + type_name_ = new ::std::string; + } + type_name_->assign(value); +} +inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + type_name_ = new ::std::string; + } + type_name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FieldDescriptorProto::mutable_type_name() { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + type_name_ = new ::std::string; + } + return type_name_; +} +inline ::std::string* FieldDescriptorProto::release_type_name() { + clear_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = type_name_; + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { + delete type_name_; + } + if (type_name) { + set_has_type_name(); + type_name_ = type_name; + } else { + clear_has_type_name(); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string extendee = 2; +inline bool FieldDescriptorProto::has_extendee() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FieldDescriptorProto::set_has_extendee() { + _has_bits_[0] |= 0x00000020u; +} +inline void FieldDescriptorProto::clear_has_extendee() { + _has_bits_[0] &= ~0x00000020u; +} +inline void FieldDescriptorProto::clear_extendee() { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { + extendee_->clear(); + } + clear_has_extendee(); +} +inline const ::std::string& FieldDescriptorProto::extendee() const { + return *extendee_; +} +inline void FieldDescriptorProto::set_extendee(const ::std::string& value) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + extendee_ = new ::std::string; + } + extendee_->assign(value); +} +inline void FieldDescriptorProto::set_extendee(const char* value) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + extendee_ = new ::std::string; + } + extendee_->assign(value); +} +inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + extendee_ = new ::std::string; + } + extendee_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FieldDescriptorProto::mutable_extendee() { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + extendee_ = new ::std::string; + } + return extendee_; +} +inline ::std::string* FieldDescriptorProto::release_extendee() { + clear_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = extendee_; + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { + delete extendee_; + } + if (extendee) { + set_has_extendee(); + extendee_ = extendee; + } else { + clear_has_extendee(); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string default_value = 7; +inline bool FieldDescriptorProto::has_default_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FieldDescriptorProto::set_has_default_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void FieldDescriptorProto::clear_has_default_value() { + _has_bits_[0] &= ~0x00000040u; +} +inline void FieldDescriptorProto::clear_default_value() { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { + default_value_->clear(); + } + clear_has_default_value(); +} +inline const ::std::string& FieldDescriptorProto::default_value() const { + return *default_value_; +} +inline void FieldDescriptorProto::set_default_value(const ::std::string& value) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + default_value_ = new ::std::string; + } + default_value_->assign(value); +} +inline void FieldDescriptorProto::set_default_value(const char* value) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + default_value_ = new ::std::string; + } + default_value_->assign(value); +} +inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + default_value_ = new ::std::string; + } + default_value_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FieldDescriptorProto::mutable_default_value() { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + default_value_ = new ::std::string; + } + return default_value_; +} +inline ::std::string* FieldDescriptorProto::release_default_value() { + clear_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = default_value_; + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { + delete default_value_; + } + if (default_value) { + set_has_default_value(); + default_value_ = default_value; + } else { + clear_has_default_value(); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional .google.protobuf.FieldOptions options = 8; +inline bool FieldDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FieldDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} +inline void FieldDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; +} +inline void FieldDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions; + return options_; +} +inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FieldOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// EnumDescriptorProto + +// optional string name = 1; +inline bool EnumDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& EnumDescriptorProto::name() const { + return *name_; +} +inline void EnumDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void EnumDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void EnumDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* EnumDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* EnumDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void EnumDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; +inline int EnumDescriptorProto::value_size() const { + return value_.size(); +} +inline void EnumDescriptorProto::clear_value() { + value_.Clear(); +} +inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + return value_.Get(index); +} +inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + return value_.Mutable(index); +} +inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + return value_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + return value_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* +EnumDescriptorProto::mutable_value() { + return &value_; +} + +// optional .google.protobuf.EnumOptions options = 3; +inline bool EnumDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} +inline void EnumDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions; + return options_; +} +inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// EnumValueDescriptorProto + +// optional string name = 1; +inline bool EnumValueDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumValueDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumValueDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumValueDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& EnumValueDescriptorProto::name() const { + return *name_; +} +inline void EnumValueDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void EnumValueDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* EnumValueDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* EnumValueDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional int32 number = 2; +inline bool EnumValueDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void EnumValueDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void EnumValueDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} +inline void EnumValueDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} +inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const { + return number_; +} +inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; +} + +// optional .google.protobuf.EnumValueOptions options = 3; +inline bool EnumValueDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumValueDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumValueDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} +inline void EnumValueDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions; + return options_; +} +inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumValueOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// ServiceDescriptorProto + +// optional string name = 1; +inline bool ServiceDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ServiceDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void ServiceDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ServiceDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& ServiceDescriptorProto::name() const { + return *name_; +} +inline void ServiceDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void ServiceDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* ServiceDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* ServiceDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// repeated .google.protobuf.MethodDescriptorProto method = 2; +inline int ServiceDescriptorProto::method_size() const { + return method_.size(); +} +inline void ServiceDescriptorProto::clear_method() { + method_.Clear(); +} +inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + return method_.Get(index); +} +inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + return method_.Mutable(index); +} +inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + return method_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + return method_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* +ServiceDescriptorProto::mutable_method() { + return &method_; +} + +// optional .google.protobuf.ServiceOptions options = 3; +inline bool ServiceDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ServiceDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void ServiceDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} +inline void ServiceDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions; + return options_; +} +inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::ServiceOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// MethodDescriptorProto + +// optional string name = 1; +inline bool MethodDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MethodDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void MethodDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void MethodDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::kEmptyString) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& MethodDescriptorProto::name() const { + return *name_; +} +inline void MethodDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void MethodDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(value); +} +inline void MethodDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); +} +inline ::std::string* MethodDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + name_ = new ::std::string; + } + return name_; +} +inline ::std::string* MethodDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::kEmptyString) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string input_type = 2; +inline bool MethodDescriptorProto::has_input_type() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MethodDescriptorProto::set_has_input_type() { + _has_bits_[0] |= 0x00000002u; +} +inline void MethodDescriptorProto::clear_has_input_type() { + _has_bits_[0] &= ~0x00000002u; +} +inline void MethodDescriptorProto::clear_input_type() { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { + input_type_->clear(); + } + clear_has_input_type(); +} +inline const ::std::string& MethodDescriptorProto::input_type() const { + return *input_type_; +} +inline void MethodDescriptorProto::set_input_type(const ::std::string& value) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + input_type_ = new ::std::string; + } + input_type_->assign(value); +} +inline void MethodDescriptorProto::set_input_type(const char* value) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + input_type_ = new ::std::string; + } + input_type_->assign(value); +} +inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + input_type_ = new ::std::string; + } + input_type_->assign(reinterpret_cast(value), size); +} +inline ::std::string* MethodDescriptorProto::mutable_input_type() { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + input_type_ = new ::std::string; + } + return input_type_; +} +inline ::std::string* MethodDescriptorProto::release_input_type() { + clear_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = input_type_; + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { + delete input_type_; + } + if (input_type) { + set_has_input_type(); + input_type_ = input_type; + } else { + clear_has_input_type(); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string output_type = 3; +inline bool MethodDescriptorProto::has_output_type() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void MethodDescriptorProto::set_has_output_type() { + _has_bits_[0] |= 0x00000004u; +} +inline void MethodDescriptorProto::clear_has_output_type() { + _has_bits_[0] &= ~0x00000004u; +} +inline void MethodDescriptorProto::clear_output_type() { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { + output_type_->clear(); + } + clear_has_output_type(); +} +inline const ::std::string& MethodDescriptorProto::output_type() const { + return *output_type_; +} +inline void MethodDescriptorProto::set_output_type(const ::std::string& value) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + output_type_ = new ::std::string; + } + output_type_->assign(value); +} +inline void MethodDescriptorProto::set_output_type(const char* value) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + output_type_ = new ::std::string; + } + output_type_->assign(value); +} +inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + output_type_ = new ::std::string; + } + output_type_->assign(reinterpret_cast(value), size); +} +inline ::std::string* MethodDescriptorProto::mutable_output_type() { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + output_type_ = new ::std::string; + } + return output_type_; +} +inline ::std::string* MethodDescriptorProto::release_output_type() { + clear_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = output_type_; + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { + delete output_type_; + } + if (output_type) { + set_has_output_type(); + output_type_ = output_type; + } else { + clear_has_output_type(); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional .google.protobuf.MethodOptions options = 4; +inline bool MethodDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void MethodDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000008u; +} +inline void MethodDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000008u; +} +inline void MethodDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); + clear_has_options(); +} +inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { + return options_ != NULL ? *options_ : *default_instance_->options_; +} +inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions; + return options_; +} +inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MethodOptions* temp = options_; + options_ = NULL; + return temp; +} +inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } +} + +// ------------------------------------------------------------------- + +// FileOptions + +// optional string java_package = 1; +inline bool FileOptions::has_java_package() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileOptions::set_has_java_package() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileOptions::clear_has_java_package() { + _has_bits_[0] &= ~0x00000001u; +} +inline void FileOptions::clear_java_package() { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { + java_package_->clear(); + } + clear_has_java_package(); +} +inline const ::std::string& FileOptions::java_package() const { + return *java_package_; +} +inline void FileOptions::set_java_package(const ::std::string& value) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + java_package_ = new ::std::string; + } + java_package_->assign(value); +} +inline void FileOptions::set_java_package(const char* value) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + java_package_ = new ::std::string; + } + java_package_->assign(value); +} +inline void FileOptions::set_java_package(const char* value, size_t size) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + java_package_ = new ::std::string; + } + java_package_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FileOptions::mutable_java_package() { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + java_package_ = new ::std::string; + } + return java_package_; +} +inline ::std::string* FileOptions::release_java_package() { + clear_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = java_package_; + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FileOptions::set_allocated_java_package(::std::string* java_package) { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { + delete java_package_; + } + if (java_package) { + set_has_java_package(); + java_package_ = java_package; + } else { + clear_has_java_package(); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string java_outer_classname = 8; +inline bool FileOptions::has_java_outer_classname() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileOptions::set_has_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileOptions::clear_has_java_outer_classname() { + _has_bits_[0] &= ~0x00000002u; +} +inline void FileOptions::clear_java_outer_classname() { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { + java_outer_classname_->clear(); + } + clear_has_java_outer_classname(); +} +inline const ::std::string& FileOptions::java_outer_classname() const { + return *java_outer_classname_; +} +inline void FileOptions::set_java_outer_classname(const ::std::string& value) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + java_outer_classname_ = new ::std::string; + } + java_outer_classname_->assign(value); +} +inline void FileOptions::set_java_outer_classname(const char* value) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + java_outer_classname_ = new ::std::string; + } + java_outer_classname_->assign(value); +} +inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + java_outer_classname_ = new ::std::string; + } + java_outer_classname_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FileOptions::mutable_java_outer_classname() { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + java_outer_classname_ = new ::std::string; + } + return java_outer_classname_; +} +inline ::std::string* FileOptions::release_java_outer_classname() { + clear_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = java_outer_classname_; + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { + delete java_outer_classname_; + } + if (java_outer_classname) { + set_has_java_outer_classname(); + java_outer_classname_ = java_outer_classname; + } else { + clear_has_java_outer_classname(); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional bool java_multiple_files = 10 [default = false]; +inline bool FileOptions::has_java_multiple_files() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FileOptions::set_has_java_multiple_files() { + _has_bits_[0] |= 0x00000004u; +} +inline void FileOptions::clear_has_java_multiple_files() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FileOptions::clear_java_multiple_files() { + java_multiple_files_ = false; + clear_has_java_multiple_files(); +} +inline bool FileOptions::java_multiple_files() const { + return java_multiple_files_; +} +inline void FileOptions::set_java_multiple_files(bool value) { + set_has_java_multiple_files(); + java_multiple_files_ = value; +} + +// optional bool java_generate_equals_and_hash = 20 [default = false]; +inline bool FileOptions::has_java_generate_equals_and_hash() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FileOptions::set_has_java_generate_equals_and_hash() { + _has_bits_[0] |= 0x00000008u; +} +inline void FileOptions::clear_has_java_generate_equals_and_hash() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FileOptions::clear_java_generate_equals_and_hash() { + java_generate_equals_and_hash_ = false; + clear_has_java_generate_equals_and_hash(); +} +inline bool FileOptions::java_generate_equals_and_hash() const { + return java_generate_equals_and_hash_; +} +inline void FileOptions::set_java_generate_equals_and_hash(bool value) { + set_has_java_generate_equals_and_hash(); + java_generate_equals_and_hash_ = value; +} + +// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; +inline bool FileOptions::has_optimize_for() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FileOptions::set_has_optimize_for() { + _has_bits_[0] |= 0x00000010u; +} +inline void FileOptions::clear_has_optimize_for() { + _has_bits_[0] &= ~0x00000010u; +} +inline void FileOptions::clear_optimize_for() { + optimize_for_ = 1; + clear_has_optimize_for(); +} +inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { + return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); +} +inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { + assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); + set_has_optimize_for(); + optimize_for_ = value; +} + +// optional string go_package = 11; +inline bool FileOptions::has_go_package() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FileOptions::set_has_go_package() { + _has_bits_[0] |= 0x00000020u; +} +inline void FileOptions::clear_has_go_package() { + _has_bits_[0] &= ~0x00000020u; +} +inline void FileOptions::clear_go_package() { + if (go_package_ != &::google::protobuf::internal::kEmptyString) { + go_package_->clear(); + } + clear_has_go_package(); +} +inline const ::std::string& FileOptions::go_package() const { + return *go_package_; +} +inline void FileOptions::set_go_package(const ::std::string& value) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::kEmptyString) { + go_package_ = new ::std::string; + } + go_package_->assign(value); +} +inline void FileOptions::set_go_package(const char* value) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::kEmptyString) { + go_package_ = new ::std::string; + } + go_package_->assign(value); +} +inline void FileOptions::set_go_package(const char* value, size_t size) { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::kEmptyString) { + go_package_ = new ::std::string; + } + go_package_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FileOptions::mutable_go_package() { + set_has_go_package(); + if (go_package_ == &::google::protobuf::internal::kEmptyString) { + go_package_ = new ::std::string; + } + return go_package_; +} +inline ::std::string* FileOptions::release_go_package() { + clear_has_go_package(); + if (go_package_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = go_package_; + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FileOptions::set_allocated_go_package(::std::string* go_package) { + if (go_package_ != &::google::protobuf::internal::kEmptyString) { + delete go_package_; + } + if (go_package) { + set_has_go_package(); + go_package_ = go_package; + } else { + clear_has_go_package(); + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional bool cc_generic_services = 16 [default = false]; +inline bool FileOptions::has_cc_generic_services() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FileOptions::set_has_cc_generic_services() { + _has_bits_[0] |= 0x00000040u; +} +inline void FileOptions::clear_has_cc_generic_services() { + _has_bits_[0] &= ~0x00000040u; +} +inline void FileOptions::clear_cc_generic_services() { + cc_generic_services_ = false; + clear_has_cc_generic_services(); +} +inline bool FileOptions::cc_generic_services() const { + return cc_generic_services_; +} +inline void FileOptions::set_cc_generic_services(bool value) { + set_has_cc_generic_services(); + cc_generic_services_ = value; +} + +// optional bool java_generic_services = 17 [default = false]; +inline bool FileOptions::has_java_generic_services() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FileOptions::set_has_java_generic_services() { + _has_bits_[0] |= 0x00000080u; +} +inline void FileOptions::clear_has_java_generic_services() { + _has_bits_[0] &= ~0x00000080u; +} +inline void FileOptions::clear_java_generic_services() { + java_generic_services_ = false; + clear_has_java_generic_services(); +} +inline bool FileOptions::java_generic_services() const { + return java_generic_services_; +} +inline void FileOptions::set_java_generic_services(bool value) { + set_has_java_generic_services(); + java_generic_services_ = value; +} + +// optional bool py_generic_services = 18 [default = false]; +inline bool FileOptions::has_py_generic_services() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void FileOptions::set_has_py_generic_services() { + _has_bits_[0] |= 0x00000100u; +} +inline void FileOptions::clear_has_py_generic_services() { + _has_bits_[0] &= ~0x00000100u; +} +inline void FileOptions::clear_py_generic_services() { + py_generic_services_ = false; + clear_has_py_generic_services(); +} +inline bool FileOptions::py_generic_services() const { + return py_generic_services_; +} +inline void FileOptions::set_py_generic_services(bool value) { + set_has_py_generic_services(); + py_generic_services_ = value; +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int FileOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void FileOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FileOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// MessageOptions + +// optional bool message_set_wire_format = 1 [default = false]; +inline bool MessageOptions::has_message_set_wire_format() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MessageOptions::set_has_message_set_wire_format() { + _has_bits_[0] |= 0x00000001u; +} +inline void MessageOptions::clear_has_message_set_wire_format() { + _has_bits_[0] &= ~0x00000001u; +} +inline void MessageOptions::clear_message_set_wire_format() { + message_set_wire_format_ = false; + clear_has_message_set_wire_format(); +} +inline bool MessageOptions::message_set_wire_format() const { + return message_set_wire_format_; +} +inline void MessageOptions::set_message_set_wire_format(bool value) { + set_has_message_set_wire_format(); + message_set_wire_format_ = value; +} + +// optional bool no_standard_descriptor_accessor = 2 [default = false]; +inline bool MessageOptions::has_no_standard_descriptor_accessor() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MessageOptions::set_has_no_standard_descriptor_accessor() { + _has_bits_[0] |= 0x00000002u; +} +inline void MessageOptions::clear_has_no_standard_descriptor_accessor() { + _has_bits_[0] &= ~0x00000002u; +} +inline void MessageOptions::clear_no_standard_descriptor_accessor() { + no_standard_descriptor_accessor_ = false; + clear_has_no_standard_descriptor_accessor(); +} +inline bool MessageOptions::no_standard_descriptor_accessor() const { + return no_standard_descriptor_accessor_; +} +inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + set_has_no_standard_descriptor_accessor(); + no_standard_descriptor_accessor_ = value; +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int MessageOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void MessageOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MessageOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// FieldOptions + +// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; +inline bool FieldOptions::has_ctype() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldOptions::set_has_ctype() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldOptions::clear_has_ctype() { + _has_bits_[0] &= ~0x00000001u; +} +inline void FieldOptions::clear_ctype() { + ctype_ = 0; + clear_has_ctype(); +} +inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { + return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); +} +inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { + assert(::google::protobuf::FieldOptions_CType_IsValid(value)); + set_has_ctype(); + ctype_ = value; +} + +// optional bool packed = 2; +inline bool FieldOptions::has_packed() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldOptions::set_has_packed() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldOptions::clear_has_packed() { + _has_bits_[0] &= ~0x00000002u; +} +inline void FieldOptions::clear_packed() { + packed_ = false; + clear_has_packed(); +} +inline bool FieldOptions::packed() const { + return packed_; +} +inline void FieldOptions::set_packed(bool value) { + set_has_packed(); + packed_ = value; +} + +// optional bool lazy = 5 [default = false]; +inline bool FieldOptions::has_lazy() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldOptions::set_has_lazy() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldOptions::clear_has_lazy() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FieldOptions::clear_lazy() { + lazy_ = false; + clear_has_lazy(); +} +inline bool FieldOptions::lazy() const { + return lazy_; +} +inline void FieldOptions::set_lazy(bool value) { + set_has_lazy(); + lazy_ = value; +} + +// optional bool deprecated = 3 [default = false]; +inline bool FieldOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FieldOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool FieldOptions::deprecated() const { + return deprecated_; +} +inline void FieldOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; +} + +// optional string experimental_map_key = 9; +inline bool FieldOptions::has_experimental_map_key() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FieldOptions::set_has_experimental_map_key() { + _has_bits_[0] |= 0x00000010u; +} +inline void FieldOptions::clear_has_experimental_map_key() { + _has_bits_[0] &= ~0x00000010u; +} +inline void FieldOptions::clear_experimental_map_key() { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { + experimental_map_key_->clear(); + } + clear_has_experimental_map_key(); +} +inline const ::std::string& FieldOptions::experimental_map_key() const { + return *experimental_map_key_; +} +inline void FieldOptions::set_experimental_map_key(const ::std::string& value) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + experimental_map_key_ = new ::std::string; + } + experimental_map_key_->assign(value); +} +inline void FieldOptions::set_experimental_map_key(const char* value) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + experimental_map_key_ = new ::std::string; + } + experimental_map_key_->assign(value); +} +inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + experimental_map_key_ = new ::std::string; + } + experimental_map_key_->assign(reinterpret_cast(value), size); +} +inline ::std::string* FieldOptions::mutable_experimental_map_key() { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + experimental_map_key_ = new ::std::string; + } + return experimental_map_key_; +} +inline ::std::string* FieldOptions::release_experimental_map_key() { + clear_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = experimental_map_key_; + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { + delete experimental_map_key_; + } + if (experimental_map_key) { + set_has_experimental_map_key(); + experimental_map_key_ = experimental_map_key; + } else { + clear_has_experimental_map_key(); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional bool weak = 10 [default = false]; +inline bool FieldOptions::has_weak() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FieldOptions::set_has_weak() { + _has_bits_[0] |= 0x00000020u; +} +inline void FieldOptions::clear_has_weak() { + _has_bits_[0] &= ~0x00000020u; +} +inline void FieldOptions::clear_weak() { + weak_ = false; + clear_has_weak(); +} +inline bool FieldOptions::weak() const { + return weak_; +} +inline void FieldOptions::set_weak(bool value) { + set_has_weak(); + weak_ = value; +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int FieldOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void FieldOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FieldOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// EnumOptions + +// optional bool allow_alias = 2 [default = true]; +inline bool EnumOptions::has_allow_alias() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumOptions::set_has_allow_alias() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumOptions::clear_has_allow_alias() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumOptions::clear_allow_alias() { + allow_alias_ = true; + clear_has_allow_alias(); +} +inline bool EnumOptions::allow_alias() const { + return allow_alias_; +} +inline void EnumOptions::set_allow_alias(bool value) { + set_has_allow_alias(); + allow_alias_ = value; +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int EnumOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void EnumOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// EnumValueOptions + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int EnumValueOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void EnumValueOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumValueOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// ServiceOptions + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int ServiceOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void ServiceOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +ServiceOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// MethodOptions + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; +inline int MethodOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} +inline void MethodOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + return uninterpreted_option_.Get(index); +} +inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + return uninterpreted_option_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + return uninterpreted_option_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + return uninterpreted_option_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MethodOptions::mutable_uninterpreted_option() { + return &uninterpreted_option_; +} + +// ------------------------------------------------------------------- + +// UninterpretedOption_NamePart + +// required string name_part = 1; +inline bool UninterpretedOption_NamePart::has_name_part() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_name_part() { + _has_bits_[0] |= 0x00000001u; +} +inline void UninterpretedOption_NamePart::clear_has_name_part() { + _has_bits_[0] &= ~0x00000001u; +} +inline void UninterpretedOption_NamePart::clear_name_part() { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { + name_part_->clear(); + } + clear_has_name_part(); +} +inline const ::std::string& UninterpretedOption_NamePart::name_part() const { + return *name_part_; +} +inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + name_part_ = new ::std::string; + } + name_part_->assign(value); +} +inline void UninterpretedOption_NamePart::set_name_part(const char* value) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + name_part_ = new ::std::string; + } + name_part_->assign(value); +} +inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + name_part_ = new ::std::string; + } + name_part_->assign(reinterpret_cast(value), size); +} +inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + name_part_ = new ::std::string; + } + return name_part_; +} +inline ::std::string* UninterpretedOption_NamePart::release_name_part() { + clear_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_part_; + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { + delete name_part_; + } + if (name_part) { + set_has_name_part(); + name_part_ = name_part; + } else { + clear_has_name_part(); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// required bool is_extension = 2; +inline bool UninterpretedOption_NamePart::has_is_extension() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_is_extension() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption_NamePart::clear_has_is_extension() { + _has_bits_[0] &= ~0x00000002u; +} +inline void UninterpretedOption_NamePart::clear_is_extension() { + is_extension_ = false; + clear_has_is_extension(); +} +inline bool UninterpretedOption_NamePart::is_extension() const { + return is_extension_; +} +inline void UninterpretedOption_NamePart::set_is_extension(bool value) { + set_has_is_extension(); + is_extension_ = value; +} + +// ------------------------------------------------------------------- + +// UninterpretedOption + +// repeated .google.protobuf.UninterpretedOption.NamePart name = 2; +inline int UninterpretedOption::name_size() const { + return name_.size(); +} +inline void UninterpretedOption::clear_name() { + name_.Clear(); +} +inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + return name_.Get(index); +} +inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + return name_.Mutable(index); +} +inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + return name_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + return name_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* +UninterpretedOption::mutable_name() { + return &name_; +} + +// optional string identifier_value = 3; +inline bool UninterpretedOption::has_identifier_value() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption::set_has_identifier_value() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption::clear_has_identifier_value() { + _has_bits_[0] &= ~0x00000002u; +} +inline void UninterpretedOption::clear_identifier_value() { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { + identifier_value_->clear(); + } + clear_has_identifier_value(); +} +inline const ::std::string& UninterpretedOption::identifier_value() const { + return *identifier_value_; +} +inline void UninterpretedOption::set_identifier_value(const ::std::string& value) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + identifier_value_ = new ::std::string; + } + identifier_value_->assign(value); +} +inline void UninterpretedOption::set_identifier_value(const char* value) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + identifier_value_ = new ::std::string; + } + identifier_value_->assign(value); +} +inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + identifier_value_ = new ::std::string; + } + identifier_value_->assign(reinterpret_cast(value), size); +} +inline ::std::string* UninterpretedOption::mutable_identifier_value() { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + identifier_value_ = new ::std::string; + } + return identifier_value_; +} +inline ::std::string* UninterpretedOption::release_identifier_value() { + clear_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = identifier_value_; + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { + delete identifier_value_; + } + if (identifier_value) { + set_has_identifier_value(); + identifier_value_ = identifier_value; + } else { + clear_has_identifier_value(); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional uint64 positive_int_value = 4; +inline bool UninterpretedOption::has_positive_int_value() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void UninterpretedOption::set_has_positive_int_value() { + _has_bits_[0] |= 0x00000004u; +} +inline void UninterpretedOption::clear_has_positive_int_value() { + _has_bits_[0] &= ~0x00000004u; +} +inline void UninterpretedOption::clear_positive_int_value() { + positive_int_value_ = GOOGLE_ULONGLONG(0); + clear_has_positive_int_value(); +} +inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { + return positive_int_value_; +} +inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { + set_has_positive_int_value(); + positive_int_value_ = value; +} + +// optional int64 negative_int_value = 5; +inline bool UninterpretedOption::has_negative_int_value() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void UninterpretedOption::set_has_negative_int_value() { + _has_bits_[0] |= 0x00000008u; +} +inline void UninterpretedOption::clear_has_negative_int_value() { + _has_bits_[0] &= ~0x00000008u; +} +inline void UninterpretedOption::clear_negative_int_value() { + negative_int_value_ = GOOGLE_LONGLONG(0); + clear_has_negative_int_value(); +} +inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { + return negative_int_value_; +} +inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { + set_has_negative_int_value(); + negative_int_value_ = value; +} + +// optional double double_value = 6; +inline bool UninterpretedOption::has_double_value() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void UninterpretedOption::set_has_double_value() { + _has_bits_[0] |= 0x00000010u; +} +inline void UninterpretedOption::clear_has_double_value() { + _has_bits_[0] &= ~0x00000010u; +} +inline void UninterpretedOption::clear_double_value() { + double_value_ = 0; + clear_has_double_value(); +} +inline double UninterpretedOption::double_value() const { + return double_value_; +} +inline void UninterpretedOption::set_double_value(double value) { + set_has_double_value(); + double_value_ = value; +} + +// optional bytes string_value = 7; +inline bool UninterpretedOption::has_string_value() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void UninterpretedOption::set_has_string_value() { + _has_bits_[0] |= 0x00000020u; +} +inline void UninterpretedOption::clear_has_string_value() { + _has_bits_[0] &= ~0x00000020u; +} +inline void UninterpretedOption::clear_string_value() { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { + string_value_->clear(); + } + clear_has_string_value(); +} +inline const ::std::string& UninterpretedOption::string_value() const { + return *string_value_; +} +inline void UninterpretedOption::set_string_value(const ::std::string& value) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + string_value_ = new ::std::string; + } + string_value_->assign(value); +} +inline void UninterpretedOption::set_string_value(const char* value) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + string_value_ = new ::std::string; + } + string_value_->assign(value); +} +inline void UninterpretedOption::set_string_value(const void* value, size_t size) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + string_value_ = new ::std::string; + } + string_value_->assign(reinterpret_cast(value), size); +} +inline ::std::string* UninterpretedOption::mutable_string_value() { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + string_value_ = new ::std::string; + } + return string_value_; +} +inline ::std::string* UninterpretedOption::release_string_value() { + clear_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = string_value_; + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { + delete string_value_; + } + if (string_value) { + set_has_string_value(); + string_value_ = string_value; + } else { + clear_has_string_value(); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string aggregate_value = 8; +inline bool UninterpretedOption::has_aggregate_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void UninterpretedOption::set_has_aggregate_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void UninterpretedOption::clear_has_aggregate_value() { + _has_bits_[0] &= ~0x00000040u; +} +inline void UninterpretedOption::clear_aggregate_value() { + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + aggregate_value_->clear(); + } + clear_has_aggregate_value(); +} +inline const ::std::string& UninterpretedOption::aggregate_value() const { + return *aggregate_value_; +} +inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); +} +inline void UninterpretedOption::set_aggregate_value(const char* value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); +} +inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(reinterpret_cast(value), size); +} +inline ::std::string* UninterpretedOption::mutable_aggregate_value() { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + return aggregate_value_; +} +inline ::std::string* UninterpretedOption::release_aggregate_value() { + clear_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = aggregate_value_; + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + delete aggregate_value_; + } + if (aggregate_value) { + set_has_aggregate_value(); + aggregate_value_ = aggregate_value; + } else { + clear_has_aggregate_value(); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; +inline int SourceCodeInfo_Location::path_size() const { + return path_.size(); +} +inline void SourceCodeInfo_Location::clear_path() { + path_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + return path_.Get(index); +} +inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { + path_.Set(index, value); +} +inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { + path_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::path() const { + return path_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_path() { + return &path_; +} + +// repeated int32 span = 2 [packed = true]; +inline int SourceCodeInfo_Location::span_size() const { + return span_.size(); +} +inline void SourceCodeInfo_Location::clear_span() { + span_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + return span_.Get(index); +} +inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { + span_.Set(index, value); +} +inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { + span_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::span() const { + return span_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_span() { + return &span_; +} + +// optional string leading_comments = 3; +inline bool SourceCodeInfo_Location::has_leading_comments() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void SourceCodeInfo_Location::set_has_leading_comments() { + _has_bits_[0] |= 0x00000004u; +} +inline void SourceCodeInfo_Location::clear_has_leading_comments() { + _has_bits_[0] &= ~0x00000004u; +} +inline void SourceCodeInfo_Location::clear_leading_comments() { + if (leading_comments_ != &::google::protobuf::internal::kEmptyString) { + leading_comments_->clear(); + } + clear_has_leading_comments(); +} +inline const ::std::string& SourceCodeInfo_Location::leading_comments() const { + return *leading_comments_; +} +inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::kEmptyString) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(value); +} +inline void SourceCodeInfo_Location::set_leading_comments(const char* value) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::kEmptyString) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(value); +} +inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::kEmptyString) { + leading_comments_ = new ::std::string; + } + leading_comments_->assign(reinterpret_cast(value), size); +} +inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { + set_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::kEmptyString) { + leading_comments_ = new ::std::string; + } + return leading_comments_; +} +inline ::std::string* SourceCodeInfo_Location::release_leading_comments() { + clear_has_leading_comments(); + if (leading_comments_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = leading_comments_; + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { + if (leading_comments_ != &::google::protobuf::internal::kEmptyString) { + delete leading_comments_; + } + if (leading_comments) { + set_has_leading_comments(); + leading_comments_ = leading_comments; + } else { + clear_has_leading_comments(); + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// optional string trailing_comments = 4; +inline bool SourceCodeInfo_Location::has_trailing_comments() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void SourceCodeInfo_Location::set_has_trailing_comments() { + _has_bits_[0] |= 0x00000008u; +} +inline void SourceCodeInfo_Location::clear_has_trailing_comments() { + _has_bits_[0] &= ~0x00000008u; +} +inline void SourceCodeInfo_Location::clear_trailing_comments() { + if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) { + trailing_comments_->clear(); + } + clear_has_trailing_comments(); +} +inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const { + return *trailing_comments_; +} +inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(value); +} +inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(value); +} +inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) { + trailing_comments_ = new ::std::string; + } + trailing_comments_->assign(reinterpret_cast(value), size); +} +inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + set_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) { + trailing_comments_ = new ::std::string; + } + return trailing_comments_; +} +inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() { + clear_has_trailing_comments(); + if (trailing_comments_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = trailing_comments_; + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} +inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { + if (trailing_comments_ != &::google::protobuf::internal::kEmptyString) { + delete trailing_comments_; + } + if (trailing_comments) { + set_has_trailing_comments(); + trailing_comments_ = trailing_comments; + } else { + clear_has_trailing_comments(); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + } +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; +inline int SourceCodeInfo::location_size() const { + return location_.size(); +} +inline void SourceCodeInfo::clear_location() { + location_.Clear(); +} +inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + return location_.Get(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + return location_.Mutable(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + return location_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + return location_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + return &location_; +} + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace protobuf +} // namespace google + +#ifndef SWIG +namespace google { +namespace protobuf { + +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() { + return ::google::protobuf::FieldDescriptorProto_Type_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() { + return ::google::protobuf::FieldDescriptorProto_Label_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() { + return ::google::protobuf::FileOptions_OptimizeMode_descriptor(); +} +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { + return ::google::protobuf::FieldOptions_CType_descriptor(); +} + +} // namespace google +} // namespace protobuf +#endif // SWIG + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.proto b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.proto new file mode 100644 index 000000000..a785f79fa --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor.proto @@ -0,0 +1,620 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// The messages in this file describe the definitions found in .proto files. +// A valid .proto file can be translated directly to a FileDescriptorProto +// without any other information (e.g. without reading its imports). + + + +package google.protobuf; +option java_package = "com.google.protobuf"; +option java_outer_classname = "DescriptorProtos"; + +// descriptor.proto must be optimized for speed because reflection-based +// algorithms don't work during bootstrapping. +option optimize_for = SPEED; + +// The protocol compiler can output a FileDescriptorSet containing the .proto +// files it parses. +message FileDescriptorSet { + repeated FileDescriptorProto file = 1; +} + +// Describes a complete .proto file. +message FileDescriptorProto { + optional string name = 1; // file name, relative to root of source tree + optional string package = 2; // e.g. "foo", "foo.bar", etc. + + // Names of files imported by this file. + repeated string dependency = 3; + // Indexes of the public imported files in the dependency list above. + repeated int32 public_dependency = 10; + // Indexes of the weak imported files in the dependency list. + // For Google-internal migration only. Do not use. + repeated int32 weak_dependency = 11; + + // All top-level definitions in this file. + repeated DescriptorProto message_type = 4; + repeated EnumDescriptorProto enum_type = 5; + repeated ServiceDescriptorProto service = 6; + repeated FieldDescriptorProto extension = 7; + + optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; +} + +// Describes a message type. +message DescriptorProto { + optional string name = 1; + + repeated FieldDescriptorProto field = 2; + repeated FieldDescriptorProto extension = 6; + + repeated DescriptorProto nested_type = 3; + repeated EnumDescriptorProto enum_type = 4; + + message ExtensionRange { + optional int32 start = 1; + optional int32 end = 2; + } + repeated ExtensionRange extension_range = 5; + + optional MessageOptions options = 7; +} + +// Describes a field within a message. +message FieldDescriptorProto { + enum Type { + // 0 is reserved for errors. + // Order is weird for historical reasons. + TYPE_DOUBLE = 1; + TYPE_FLOAT = 2; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if + // negative values are likely. + TYPE_INT64 = 3; + TYPE_UINT64 = 4; + // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if + // negative values are likely. + TYPE_INT32 = 5; + TYPE_FIXED64 = 6; + TYPE_FIXED32 = 7; + TYPE_BOOL = 8; + TYPE_STRING = 9; + TYPE_GROUP = 10; // Tag-delimited aggregate. + TYPE_MESSAGE = 11; // Length-delimited aggregate. + + // New in version 2. + TYPE_BYTES = 12; + TYPE_UINT32 = 13; + TYPE_ENUM = 14; + TYPE_SFIXED32 = 15; + TYPE_SFIXED64 = 16; + TYPE_SINT32 = 17; // Uses ZigZag encoding. + TYPE_SINT64 = 18; // Uses ZigZag encoding. + }; + + enum Label { + // 0 is reserved for errors + LABEL_OPTIONAL = 1; + LABEL_REQUIRED = 2; + LABEL_REPEATED = 3; + // TODO(sanjay): Should we add LABEL_MAP? + }; + + optional string name = 1; + optional int32 number = 3; + optional Label label = 4; + + // If type_name is set, this need not be set. If both this and type_name + // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + optional Type type = 5; + + // For message and enum types, this is the name of the type. If the name + // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping + // rules are used to find the type (i.e. first the nested types within this + // message are searched, then within the parent, on up to the root + // namespace). + optional string type_name = 6; + + // For extensions, this is the name of the type being extended. It is + // resolved in the same manner as type_name. + optional string extendee = 2; + + // For numeric types, contains the original text representation of the value. + // For booleans, "true" or "false". + // For strings, contains the default text contents (not escaped in any way). + // For bytes, contains the C escaped value. All bytes >= 128 are escaped. + // TODO(kenton): Base-64 encode? + optional string default_value = 7; + + optional FieldOptions options = 8; +} + +// Describes an enum type. +message EnumDescriptorProto { + optional string name = 1; + + repeated EnumValueDescriptorProto value = 2; + + optional EnumOptions options = 3; +} + +// Describes a value within an enum. +message EnumValueDescriptorProto { + optional string name = 1; + optional int32 number = 2; + + optional EnumValueOptions options = 3; +} + +// Describes a service. +message ServiceDescriptorProto { + optional string name = 1; + repeated MethodDescriptorProto method = 2; + + optional ServiceOptions options = 3; +} + +// Describes a method of a service. +message MethodDescriptorProto { + optional string name = 1; + + // Input and output type names. These are resolved in the same way as + // FieldDescriptorProto.type_name, but must refer to a message type. + optional string input_type = 2; + optional string output_type = 3; + + optional MethodOptions options = 4; +} + + +// =================================================================== +// Options + +// Each of the definitions above may have "options" attached. These are +// just annotations which may cause code to be generated slightly differently +// or may contain hints for code that manipulates protocol messages. +// +// Clients may define custom options as extensions of the *Options messages. +// These extensions may not yet be known at parsing time, so the parser cannot +// store the values in them. Instead it stores them in a field in the *Options +// message called uninterpreted_option. This field must have the same name +// across all *Options messages. We then use this field to populate the +// extensions when we build a descriptor, at which point all protos have been +// parsed and so all extensions are known. +// +// Extension numbers for custom options may be chosen as follows: +// * For options which will only be used within a single application or +// organization, or for experimental options, use field numbers 50000 +// through 99999. It is up to you to ensure that you do not use the +// same number for multiple options. +// * For options which will be published and used publicly by multiple +// independent entities, e-mail protobuf-global-extension-registry@google.com +// to reserve extension numbers. Simply provide your project name (e.g. +// Object-C plugin) and your porject website (if available) -- there's no need +// to explain how you intend to use them. Usually you only need one extension +// number. You can declare multiple options with only one extension number by +// putting them in a sub-message. See the Custom Options section of the docs +// for examples: +// http://code.google.com/apis/protocolbuffers/docs/proto.html#options +// If this turns out to be popular, a web service will be set up +// to automatically assign option numbers. + + +message FileOptions { + + // Sets the Java package where classes generated from this .proto will be + // placed. By default, the proto package is used, but this is often + // inappropriate because proto packages do not normally start with backwards + // domain names. + optional string java_package = 1; + + + // If set, all the classes from the .proto file are wrapped in a single + // outer class with the given name. This applies to both Proto1 + // (equivalent to the old "--one_java_file" option) and Proto2 (where + // a .proto always translates to a single class, but you may want to + // explicitly choose the class name). + optional string java_outer_classname = 8; + + // If set true, then the Java code generator will generate a separate .java + // file for each top-level message, enum, and service defined in the .proto + // file. Thus, these types will *not* be nested inside the outer class + // named by java_outer_classname. However, the outer class will still be + // generated to contain the file's getDescriptor() method as well as any + // top-level extensions defined in the file. + optional bool java_multiple_files = 10 [default=false]; + + // If set true, then the Java code generator will generate equals() and + // hashCode() methods for all messages defined in the .proto file. This is + // purely a speed optimization, as the AbstractMessage base class includes + // reflection-based implementations of these methods. + optional bool java_generate_equals_and_hash = 20 [default=false]; + + // Generated classes can be optimized for speed or code size. + enum OptimizeMode { + SPEED = 1; // Generate complete code for parsing, serialization, + // etc. + CODE_SIZE = 2; // Use ReflectionOps to implement these methods. + LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. + } + optional OptimizeMode optimize_for = 9 [default=SPEED]; + + // Sets the Go package where structs generated from this .proto will be + // placed. There is no default. + optional string go_package = 11; + + + + // Should generic services be generated in each language? "Generic" services + // are not specific to any particular RPC system. They are generated by the + // main code generators in each language (without additional plugins). + // Generic services were the only kind of service generation supported by + // early versions of proto2. + // + // Generic services are now considered deprecated in favor of using plugins + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MessageOptions { + // Set true to use the old proto1 MessageSet wire format for extensions. + // This is provided for backwards-compatibility with the MessageSet wire + // format. You should not use this for any other reason: It's less + // efficient, has fewer features, and is more complicated. + // + // The message must be defined exactly as follows: + // message Foo { + // option message_set_wire_format = true; + // extensions 4 to max; + // } + // Note that the message cannot have any defined fields; MessageSets only + // have extensions. + // + // All extensions of your type must be singular messages; e.g. they cannot + // be int32s, enums, or repeated messages. + // + // Because this is an option, the above two restrictions are not enforced by + // the protocol compiler. + optional bool message_set_wire_format = 1 [default=false]; + + // Disables the generation of the standard "descriptor()" accessor, which can + // conflict with a field of the same name. This is meant to make migration + // from proto1 easier; new code should avoid fields named "descriptor". + optional bool no_standard_descriptor_accessor = 2 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message FieldOptions { + // The ctype option instructs the C++ code generator to use a different + // representation of the field than it normally would. See the specific + // options below. This option is not yet implemented in the open source + // release -- sorry, we'll try to include it in a future version! + optional CType ctype = 1 [default = STRING]; + enum CType { + // Default mode. + STRING = 0; + + CORD = 1; + + STRING_PIECE = 2; + } + // The packed option can be enabled for repeated primitive fields to enable + // a more efficient representation on the wire. Rather than repeatedly + // writing the tag and type for each element, the entire array is encoded as + // a single length-delimited blob. + optional bool packed = 2; + + + + // Should this field be parsed lazily? Lazy applies only to message-type + // fields. It means that when the outer message is initially parsed, the + // inner message's contents will not be parsed but instead stored in encoded + // form. The inner message will actually be parsed when it is first accessed. + // + // This is only a hint. Implementations are free to choose whether to use + // eager or lazy parsing regardless of the value of this option. However, + // setting this option true suggests that the protocol author believes that + // using lazy parsing on this field is worth the additional bookkeeping + // overhead typically needed to implement it. + // + // This option does not affect the public interface of any generated code; + // all method signatures remain the same. Furthermore, thread-safety of the + // interface is not affected by this option; const methods remain safe to + // call from multiple threads concurrently, while non-const methods continue + // to require exclusive access. + // + // + // Note that implementations may choose not to check required fields within + // a lazy sub-message. That is, calling IsInitialized() on the outher message + // may return true even if the inner message has missing required fields. + // This is necessary because otherwise the inner message would have to be + // parsed in order to perform the check, defeating the purpose of lazy + // parsing. An implementation which chooses not to check required fields + // must be consistent about it. That is, for any particular sub-message, the + // implementation must either *always* check its required fields, or *never* + // check its required fields, regardless of whether or not the message has + // been parsed. + optional bool lazy = 5 [default=false]; + + // Is this field deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for accessors, or it will be completely ignored; in the very least, this + // is a formalization for deprecating fields. + optional bool deprecated = 3 [default=false]; + + // EXPERIMENTAL. DO NOT USE. + // For "map" fields, the name of the field in the enclosed type that + // is the key for this map. For example, suppose we have: + // message Item { + // required string name = 1; + // required string value = 2; + // } + // message Config { + // repeated Item items = 1 [experimental_map_key="name"]; + // } + // In this situation, the map key for Item will be set to "name". + // TODO: Fully-implement this, then remove the "experimental_" prefix. + optional string experimental_map_key = 9; + + // For Google-internal migration only. Do not use. + optional bool weak = 10 [default=false]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumOptions { + + // Set this option to false to disallow mapping different tag names to a same + // value. + optional bool allow_alias = 2 [default=true]; + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message EnumValueOptions { + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message ServiceOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + +message MethodOptions { + + // Note: Field numbers 1 through 32 are reserved for Google's internal RPC + // framework. We apologize for hoarding these numbers to ourselves, but + // we were already using them long before we decided to release Protocol + // Buffers. + + // The parser stores options it doesn't recognize here. See above. + repeated UninterpretedOption uninterpreted_option = 999; + + // Clients can define custom options in extensions of this message. See above. + extensions 1000 to max; +} + + +// A message representing a option the parser does not recognize. This only +// appears in options protos created by the compiler::Parser class. +// DescriptorPool resolves these when building Descriptor objects. Therefore, +// options protos in descriptor objects (e.g. returned by Descriptor::options(), +// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions +// in them. +message UninterpretedOption { + // The name of the uninterpreted option. Each string represents a segment in + // a dot-separated name. is_extension is true iff a segment represents an + // extension (denoted with parentheses in options specs in .proto files). + // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents + // "foo.(bar.baz).qux". + message NamePart { + required string name_part = 1; + required bool is_extension = 2; + } + repeated NamePart name = 2; + + // The value of the uninterpreted option, in whatever type the tokenizer + // identified it as during parsing. Exactly one of these should be set. + optional string identifier_value = 3; + optional uint64 positive_int_value = 4; + optional int64 negative_int_value = 5; + optional double double_value = 6; + optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // If this SourceCodeInfo represents a complete declaration, these are any + // comments appearing before and after the declaration which appear to be + // attached to the declaration. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is provided; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk + // will be stripped from the beginning of each line other than the first. + // Newlines are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + optional string leading_comments = 3; + optional string trailing_comments = 4; + } +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.cc new file mode 100644 index 000000000..35e459d53 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.cc @@ -0,0 +1,541 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { + +DescriptorDatabase::~DescriptorDatabase() {} + +// =================================================================== + +template +bool SimpleDescriptorDatabase::DescriptorIndex::AddFile( + const FileDescriptorProto& file, + Value value) { + if (!InsertIfNotPresent(&by_name_, file.name(), value)) { + GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name(); + return false; + } + + // We must be careful here -- calling file.package() if file.has_package() is + // false could access an uninitialized static-storage variable if we are being + // run at startup time. + string path = file.has_package() ? file.package() : string(); + if (!path.empty()) path += '.'; + + for (int i = 0; i < file.message_type_size(); i++) { + if (!AddSymbol(path + file.message_type(i).name(), value)) return false; + if (!AddNestedExtensions(file.message_type(i), value)) return false; + } + for (int i = 0; i < file.enum_type_size(); i++) { + if (!AddSymbol(path + file.enum_type(i).name(), value)) return false; + } + for (int i = 0; i < file.extension_size(); i++) { + if (!AddSymbol(path + file.extension(i).name(), value)) return false; + if (!AddExtension(file.extension(i), value)) return false; + } + for (int i = 0; i < file.service_size(); i++) { + if (!AddSymbol(path + file.service(i).name(), value)) return false; + } + + return true; +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::AddSymbol( + const string& name, Value value) { + // We need to make sure not to violate our map invariant. + + // If the symbol name is invalid it could break our lookup algorithm (which + // relies on the fact that '.' sorts before all other characters that are + // valid in symbol names). + if (!ValidateSymbolName(name)) { + GOOGLE_LOG(ERROR) << "Invalid symbol name: " << name; + return false; + } + + // Try to look up the symbol to make sure a super-symbol doesn't already + // exist. + typename map::iterator iter = FindLastLessOrEqual(name); + + if (iter == by_symbol_.end()) { + // Apparently the map is currently empty. Just insert and be done with it. + by_symbol_.insert(typename map::value_type(name, value)); + return true; + } + + if (IsSubSymbol(iter->first, name)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing " + "symbol \"" << iter->first << "\"."; + return false; + } + + // OK, that worked. Now we have to make sure that no symbol in the map is + // a sub-symbol of the one we are inserting. The only symbol which could + // be so is the first symbol that is greater than the new symbol. Since + // |iter| points at the last symbol that is less than or equal, we just have + // to increment it. + ++iter; + + if (iter != by_symbol_.end() && IsSubSymbol(name, iter->first)) { + GOOGLE_LOG(ERROR) << "Symbol name \"" << name << "\" conflicts with the existing " + "symbol \"" << iter->first << "\"."; + return false; + } + + // OK, no conflicts. + + // Insert the new symbol using the iterator as a hint, the new entry will + // appear immediately before the one the iterator is pointing at. + by_symbol_.insert(iter, typename map::value_type(name, value)); + + return true; +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::AddNestedExtensions( + const DescriptorProto& message_type, + Value value) { + for (int i = 0; i < message_type.nested_type_size(); i++) { + if (!AddNestedExtensions(message_type.nested_type(i), value)) return false; + } + for (int i = 0; i < message_type.extension_size(); i++) { + if (!AddExtension(message_type.extension(i), value)) return false; + } + return true; +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( + const FieldDescriptorProto& field, + Value value) { + if (!field.extendee().empty() && field.extendee()[0] == '.') { + // The extension is fully-qualified. We can use it as a lookup key in + // the by_symbol_ table. + if (!InsertIfNotPresent(&by_extension_, + make_pair(field.extendee().substr(1), + field.number()), + value)) { + GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " + "extend " << field.extendee() << " { " + << field.name() << " = " << field.number() << " }"; + return false; + } + } else { + // Not fully-qualified. We can't really do anything here, unfortunately. + // We don't consider this an error, though, because the descriptor is + // valid. + } + return true; +} + +template +Value SimpleDescriptorDatabase::DescriptorIndex::FindFile( + const string& filename) { + return FindWithDefault(by_name_, filename, Value()); +} + +template +Value SimpleDescriptorDatabase::DescriptorIndex::FindSymbol( + const string& name) { + typename map::iterator iter = FindLastLessOrEqual(name); + + return (iter != by_symbol_.end() && IsSubSymbol(iter->first, name)) ? + iter->second : Value(); +} + +template +Value SimpleDescriptorDatabase::DescriptorIndex::FindExtension( + const string& containing_type, + int field_number) { + return FindWithDefault(by_extension_, + make_pair(containing_type, field_number), + Value()); +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( + const string& containing_type, + vector* output) { + typename map, Value >::const_iterator it = + by_extension_.lower_bound(make_pair(containing_type, 0)); + bool success = false; + + for (; it != by_extension_.end() && it->first.first == containing_type; + ++it) { + output->push_back(it->first.second); + success = true; + } + + return success; +} + +template +typename map::iterator +SimpleDescriptorDatabase::DescriptorIndex::FindLastLessOrEqual( + const string& name) { + // Find the last key in the map which sorts less than or equal to the + // symbol name. Since upper_bound() returns the *first* key that sorts + // *greater* than the input, we want the element immediately before that. + typename map::iterator iter = by_symbol_.upper_bound(name); + if (iter != by_symbol_.begin()) --iter; + return iter; +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::IsSubSymbol( + const string& sub_symbol, const string& super_symbol) { + return sub_symbol == super_symbol || + (HasPrefixString(super_symbol, sub_symbol) && + super_symbol[sub_symbol.size()] == '.'); +} + +template +bool SimpleDescriptorDatabase::DescriptorIndex::ValidateSymbolName( + const string& name) { + for (int i = 0; i < name.size(); i++) { + // I don't trust ctype.h due to locales. :( + if (name[i] != '.' && name[i] != '_' && + (name[i] < '0' || name[i] > '9') && + (name[i] < 'A' || name[i] > 'Z') && + (name[i] < 'a' || name[i] > 'z')) { + return false; + } + } + return true; +} + +// ------------------------------------------------------------------- + +SimpleDescriptorDatabase::SimpleDescriptorDatabase() {} +SimpleDescriptorDatabase::~SimpleDescriptorDatabase() { + STLDeleteElements(&files_to_delete_); +} + +bool SimpleDescriptorDatabase::Add(const FileDescriptorProto& file) { + FileDescriptorProto* new_file = new FileDescriptorProto; + new_file->CopyFrom(file); + return AddAndOwn(new_file); +} + +bool SimpleDescriptorDatabase::AddAndOwn(const FileDescriptorProto* file) { + files_to_delete_.push_back(file); + return index_.AddFile(*file, file); +} + +bool SimpleDescriptorDatabase::FindFileByName( + const string& filename, + FileDescriptorProto* output) { + return MaybeCopy(index_.FindFile(filename), output); +} + +bool SimpleDescriptorDatabase::FindFileContainingSymbol( + const string& symbol_name, + FileDescriptorProto* output) { + return MaybeCopy(index_.FindSymbol(symbol_name), output); +} + +bool SimpleDescriptorDatabase::FindFileContainingExtension( + const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return MaybeCopy(index_.FindExtension(containing_type, field_number), output); +} + +bool SimpleDescriptorDatabase::FindAllExtensionNumbers( + const string& extendee_type, + vector* output) { + return index_.FindAllExtensionNumbers(extendee_type, output); +} + +bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, + FileDescriptorProto* output) { + if (file == NULL) return false; + output->CopyFrom(*file); + return true; +} + +// ------------------------------------------------------------------- + +EncodedDescriptorDatabase::EncodedDescriptorDatabase() {} +EncodedDescriptorDatabase::~EncodedDescriptorDatabase() { + for (int i = 0; i < files_to_delete_.size(); i++) { + operator delete(files_to_delete_[i]); + } +} + +bool EncodedDescriptorDatabase::Add( + const void* encoded_file_descriptor, int size) { + FileDescriptorProto file; + if (file.ParseFromArray(encoded_file_descriptor, size)) { + return index_.AddFile(file, make_pair(encoded_file_descriptor, size)); + } else { + GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " + "EncodedDescriptorDatabase::Add()."; + return false; + } +} + +bool EncodedDescriptorDatabase::AddCopy( + const void* encoded_file_descriptor, int size) { + void* copy = operator new(size); + memcpy(copy, encoded_file_descriptor, size); + files_to_delete_.push_back(copy); + return Add(copy, size); +} + +bool EncodedDescriptorDatabase::FindFileByName( + const string& filename, + FileDescriptorProto* output) { + return MaybeParse(index_.FindFile(filename), output); +} + +bool EncodedDescriptorDatabase::FindFileContainingSymbol( + const string& symbol_name, + FileDescriptorProto* output) { + return MaybeParse(index_.FindSymbol(symbol_name), output); +} + +bool EncodedDescriptorDatabase::FindNameOfFileContainingSymbol( + const string& symbol_name, + string* output) { + pair encoded_file = index_.FindSymbol(symbol_name); + if (encoded_file.first == NULL) return false; + + // Optimization: The name should be the first field in the encoded message. + // Try to just read it directly. + io::CodedInputStream input(reinterpret_cast(encoded_file.first), + encoded_file.second); + + const uint32 kNameTag = internal::WireFormatLite::MakeTag( + FileDescriptorProto::kNameFieldNumber, + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + if (input.ReadTag() == kNameTag) { + // Success! + return internal::WireFormatLite::ReadString(&input, output); + } else { + // Slow path. Parse whole message. + FileDescriptorProto file_proto; + if (!file_proto.ParseFromArray(encoded_file.first, encoded_file.second)) { + return false; + } + *output = file_proto.name(); + return true; + } +} + +bool EncodedDescriptorDatabase::FindFileContainingExtension( + const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return MaybeParse(index_.FindExtension(containing_type, field_number), + output); +} + +bool EncodedDescriptorDatabase::FindAllExtensionNumbers( + const string& extendee_type, + vector* output) { + return index_.FindAllExtensionNumbers(extendee_type, output); +} + +bool EncodedDescriptorDatabase::MaybeParse( + pair encoded_file, + FileDescriptorProto* output) { + if (encoded_file.first == NULL) return false; + return output->ParseFromArray(encoded_file.first, encoded_file.second); +} + +// =================================================================== + +DescriptorPoolDatabase::DescriptorPoolDatabase(const DescriptorPool& pool) + : pool_(pool) {} +DescriptorPoolDatabase::~DescriptorPoolDatabase() {} + +bool DescriptorPoolDatabase::FindFileByName( + const string& filename, + FileDescriptorProto* output) { + const FileDescriptor* file = pool_.FindFileByName(filename); + if (file == NULL) return false; + output->Clear(); + file->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindFileContainingSymbol( + const string& symbol_name, + FileDescriptorProto* output) { + const FileDescriptor* file = pool_.FindFileContainingSymbol(symbol_name); + if (file == NULL) return false; + output->Clear(); + file->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindFileContainingExtension( + const string& containing_type, + int field_number, + FileDescriptorProto* output) { + const Descriptor* extendee = pool_.FindMessageTypeByName(containing_type); + if (extendee == NULL) return false; + + const FieldDescriptor* extension = + pool_.FindExtensionByNumber(extendee, field_number); + if (extension == NULL) return false; + + output->Clear(); + extension->file()->CopyTo(output); + return true; +} + +bool DescriptorPoolDatabase::FindAllExtensionNumbers( + const string& extendee_type, + vector* output) { + const Descriptor* extendee = pool_.FindMessageTypeByName(extendee_type); + if (extendee == NULL) return false; + + vector extensions; + pool_.FindAllExtensions(extendee, &extensions); + + for (int i = 0; i < extensions.size(); ++i) { + output->push_back(extensions[i]->number()); + } + + return true; +} + +// =================================================================== + +MergedDescriptorDatabase::MergedDescriptorDatabase( + DescriptorDatabase* source1, + DescriptorDatabase* source2) { + sources_.push_back(source1); + sources_.push_back(source2); +} +MergedDescriptorDatabase::MergedDescriptorDatabase( + const vector& sources) + : sources_(sources) {} +MergedDescriptorDatabase::~MergedDescriptorDatabase() {} + +bool MergedDescriptorDatabase::FindFileByName( + const string& filename, + FileDescriptorProto* output) { + for (int i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileByName(filename, output)) { + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindFileContainingSymbol( + const string& symbol_name, + FileDescriptorProto* output) { + for (int i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileContainingSymbol(symbol_name, output)) { + // The symbol was found in source i. However, if one of the previous + // sources defines a file with the same name (which presumably doesn't + // contain the symbol, since it wasn't found in that source), then we + // must hide it from the caller. + FileDescriptorProto temp; + for (int j = 0; j < i; j++) { + if (sources_[j]->FindFileByName(output->name(), &temp)) { + // Found conflicting file in a previous source. + return false; + } + } + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindFileContainingExtension( + const string& containing_type, + int field_number, + FileDescriptorProto* output) { + for (int i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindFileContainingExtension( + containing_type, field_number, output)) { + // The symbol was found in source i. However, if one of the previous + // sources defines a file with the same name (which presumably doesn't + // contain the symbol, since it wasn't found in that source), then we + // must hide it from the caller. + FileDescriptorProto temp; + for (int j = 0; j < i; j++) { + if (sources_[j]->FindFileByName(output->name(), &temp)) { + // Found conflicting file in a previous source. + return false; + } + } + return true; + } + } + return false; +} + +bool MergedDescriptorDatabase::FindAllExtensionNumbers( + const string& extendee_type, + vector* output) { + set merged_results; + vector results; + bool success = false; + + for (int i = 0; i < sources_.size(); i++) { + if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) { + copy(results.begin(), results.end(), + insert_iterator >(merged_results, merged_results.begin())); + success = true; + } + results.clear(); + } + + copy(merged_results.begin(), merged_results.end(), + insert_iterator >(*output, output->end())); + + return success; +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.h new file mode 100644 index 000000000..2ccb14583 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database.h @@ -0,0 +1,367 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Interface for manipulating databases of descriptors. + +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ +#define GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +// Defined in this file. +class DescriptorDatabase; +class SimpleDescriptorDatabase; +class EncodedDescriptorDatabase; +class DescriptorPoolDatabase; +class MergedDescriptorDatabase; + +// Abstract interface for a database of descriptors. +// +// This is useful if you want to create a DescriptorPool which loads +// descriptors on-demand from some sort of large database. If the database +// is large, it may be inefficient to enumerate every .proto file inside it +// calling DescriptorPool::BuildFile() for each one. Instead, a DescriptorPool +// can be created which wraps a DescriptorDatabase and only builds particular +// descriptors when they are needed. +class LIBPROTOBUF_EXPORT DescriptorDatabase { + public: + inline DescriptorDatabase() {} + virtual ~DescriptorDatabase(); + + // Find a file by file name. Fills in in *output and returns true if found. + // Otherwise, returns false, leaving the contents of *output undefined. + virtual bool FindFileByName(const string& filename, + FileDescriptorProto* output) = 0; + + // Find the file that declares the given fully-qualified symbol name. + // If found, fills in *output and returns true, otherwise returns false + // and leaves *output undefined. + virtual bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) = 0; + + // Find the file which defines an extension extending the given message type + // with the given field number. If found, fills in *output and returns true, + // otherwise returns false and leaves *output undefined. containing_type + // must be a fully-qualified type name. + virtual bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) = 0; + + // Finds the tag numbers used by all known extensions of + // extendee_type, and appends them to output in an undefined + // order. This method is best-effort: it's not guaranteed that the + // database will find all extensions, and it's not guaranteed that + // FindFileContainingExtension will return true on all of the found + // numbers. Returns true if the search was successful, otherwise + // returns false and leaves output unchanged. + // + // This method has a default implementation that always returns + // false. + virtual bool FindAllExtensionNumbers(const string& extendee_type, + vector* output) { + return false; + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase); +}; + +// A DescriptorDatabase into which you can insert files manually. +// +// FindFileContainingSymbol() is fully-implemented. When you add a file, its +// symbols will be indexed for this purpose. Note that the implementation +// may return false positives, but only if it isn't possible for the symbol +// to be defined in any other file. In particular, if a file defines a symbol +// "Foo", then searching for "Foo.[anything]" will match that file. This way, +// the database does not need to aggressively index all children of a symbol. +// +// FindFileContainingExtension() is mostly-implemented. It works if and only +// if the original FieldDescriptorProto defining the extension has a +// fully-qualified type name in its "extendee" field (i.e. starts with a '.'). +// If the extendee is a relative name, SimpleDescriptorDatabase will not +// attempt to resolve the type, so it will not know what type the extension is +// extending. Therefore, calling FindFileContainingExtension() with the +// extension's containing type will never actually find that extension. Note +// that this is an unlikely problem, as all FileDescriptorProtos created by the +// protocol compiler (as well as ones created by calling +// FileDescriptor::CopyTo()) will always use fully-qualified names for all +// types. You only need to worry if you are constructing FileDescriptorProtos +// yourself, or are calling compiler::Parser directly. +class LIBPROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { + public: + SimpleDescriptorDatabase(); + ~SimpleDescriptorDatabase(); + + // Adds the FileDescriptorProto to the database, making a copy. The object + // can be deleted after Add() returns. Returns false if the file conflicted + // with a file already in the database, in which case an error will have + // been written to GOOGLE_LOG(ERROR). + bool Add(const FileDescriptorProto& file); + + // Adds the FileDescriptorProto to the database and takes ownership of it. + bool AddAndOwn(const FileDescriptorProto* file); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output); + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output); + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output); + bool FindAllExtensionNumbers(const string& extendee_type, + vector* output); + + private: + // So that it can use DescriptorIndex. + friend class EncodedDescriptorDatabase; + + // An index mapping file names, symbol names, and extension numbers to + // some sort of values. + template + class DescriptorIndex { + public: + // Helpers to recursively add particular descriptors and all their contents + // to the index. + bool AddFile(const FileDescriptorProto& file, + Value value); + bool AddSymbol(const string& name, Value value); + bool AddNestedExtensions(const DescriptorProto& message_type, + Value value); + bool AddExtension(const FieldDescriptorProto& field, + Value value); + + Value FindFile(const string& filename); + Value FindSymbol(const string& name); + Value FindExtension(const string& containing_type, int field_number); + bool FindAllExtensionNumbers(const string& containing_type, + vector* output); + + private: + map by_name_; + map by_symbol_; + map, Value> by_extension_; + + // Invariant: The by_symbol_ map does not contain any symbols which are + // prefixes of other symbols in the map. For example, "foo.bar" is a + // prefix of "foo.bar.baz" (but is not a prefix of "foo.barbaz"). + // + // This invariant is important because it means that given a symbol name, + // we can find a key in the map which is a prefix of the symbol in O(lg n) + // time, and we know that there is at most one such key. + // + // The prefix lookup algorithm works like so: + // 1) Find the last key in the map which is less than or equal to the + // search key. + // 2) If the found key is a prefix of the search key, then return it. + // Otherwise, there is no match. + // + // I am sure this algorithm has been described elsewhere, but since I + // wasn't able to find it quickly I will instead prove that it works + // myself. The key to the algorithm is that if a match exists, step (1) + // will find it. Proof: + // 1) Define the "search key" to be the key we are looking for, the "found + // key" to be the key found in step (1), and the "match key" to be the + // key which actually matches the serach key (i.e. the key we're trying + // to find). + // 2) The found key must be less than or equal to the search key by + // definition. + // 3) The match key must also be less than or equal to the search key + // (because it is a prefix). + // 4) The match key cannot be greater than the found key, because if it + // were, then step (1) of the algorithm would have returned the match + // key instead (since it finds the *greatest* key which is less than or + // equal to the search key). + // 5) Therefore, the found key must be between the match key and the search + // key, inclusive. + // 6) Since the search key must be a sub-symbol of the match key, if it is + // not equal to the match key, then search_key[match_key.size()] must + // be '.'. + // 7) Since '.' sorts before any other character that is valid in a symbol + // name, then if the found key is not equal to the match key, then + // found_key[match_key.size()] must also be '.', because any other value + // would make it sort after the search key. + // 8) Therefore, if the found key is not equal to the match key, then the + // found key must be a sub-symbol of the match key. However, this would + // contradict our map invariant which says that no symbol in the map is + // a sub-symbol of any other. + // 9) Therefore, the found key must match the match key. + // + // The above proof assumes the match key exists. In the case that the + // match key does not exist, then step (1) will return some other symbol. + // That symbol cannot be a super-symbol of the search key since if it were, + // then it would be a match, and we're assuming the match key doesn't exist. + // Therefore, step 2 will correctly return no match. + + // Find the last entry in the by_symbol_ map whose key is less than or + // equal to the given name. + typename map::iterator FindLastLessOrEqual( + const string& name); + + // True if either the arguments are equal or super_symbol identifies a + // parent symbol of sub_symbol (e.g. "foo.bar" is a parent of + // "foo.bar.baz", but not a parent of "foo.barbaz"). + bool IsSubSymbol(const string& sub_symbol, const string& super_symbol); + + // Returns true if and only if all characters in the name are alphanumerics, + // underscores, or periods. + bool ValidateSymbolName(const string& name); + }; + + + DescriptorIndex index_; + vector files_to_delete_; + + // If file is non-NULL, copy it into *output and return true, otherwise + // return false. + bool MaybeCopy(const FileDescriptorProto* file, + FileDescriptorProto* output); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase); +}; + +// Very similar to SimpleDescriptorDatabase, but stores all the descriptors +// as raw bytes and generally tries to use as little memory as possible. +// +// The same caveats regarding FindFileContainingExtension() apply as with +// SimpleDescriptorDatabase. +class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { + public: + EncodedDescriptorDatabase(); + ~EncodedDescriptorDatabase(); + + // Adds the FileDescriptorProto to the database. The descriptor is provided + // in encoded form. The database does not make a copy of the bytes, nor + // does it take ownership; it's up to the caller to make sure the bytes + // remain valid for the life of the database. Returns false and logs an error + // if the bytes are not a valid FileDescriptorProto or if the file conflicted + // with a file already in the database. + bool Add(const void* encoded_file_descriptor, int size); + + // Like Add(), but makes a copy of the data, so that the caller does not + // need to keep it around. + bool AddCopy(const void* encoded_file_descriptor, int size); + + // Like FindFileContainingSymbol but returns only the name of the file. + bool FindNameOfFileContainingSymbol(const string& symbol_name, + string* output); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output); + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output); + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output); + bool FindAllExtensionNumbers(const string& extendee_type, + vector* output); + + private: + SimpleDescriptorDatabase::DescriptorIndex > index_; + vector files_to_delete_; + + // If encoded_file.first is non-NULL, parse the data into *output and return + // true, otherwise return false. + bool MaybeParse(pair encoded_file, + FileDescriptorProto* output); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase); +}; + +// A DescriptorDatabase that fetches files from a given pool. +class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { + public: + DescriptorPoolDatabase(const DescriptorPool& pool); + ~DescriptorPoolDatabase(); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output); + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output); + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output); + bool FindAllExtensionNumbers(const string& extendee_type, + vector* output); + + private: + const DescriptorPool& pool_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase); +}; + +// A DescriptorDatabase that wraps two or more others. It first searches the +// first database and, if that fails, tries the second, and so on. +class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { + public: + // Merge just two databases. The sources remain property of the caller. + MergedDescriptorDatabase(DescriptorDatabase* source1, + DescriptorDatabase* source2); + // Merge more than two databases. The sources remain property of the caller. + // The vector may be deleted after the constructor returns but the + // DescriptorDatabases need to stick around. + MergedDescriptorDatabase(const vector& sources); + ~MergedDescriptorDatabase(); + + // implements DescriptorDatabase ----------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output); + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output); + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output); + // Merges the results of calling all databases. Returns true iff any + // of the databases returned true. + bool FindAllExtensionNumbers(const string& extendee_type, + vector* output); + + private: + vector sources_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database_unittest.cc new file mode 100644 index 000000000..ac72ddcdb --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_database_unittest.cc @@ -0,0 +1,748 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 makes extensive use of RFC 3092. :) + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace { + +static void AddToDatabase(SimpleDescriptorDatabase* database, + const char* file_text) { + FileDescriptorProto file_proto; + EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + database->Add(file_proto); +} + +static void ExpectContainsType(const FileDescriptorProto& proto, + const string& type_name) { + for (int i = 0; i < proto.message_type_size(); i++) { + if (proto.message_type(i).name() == type_name) return; + } + ADD_FAILURE() << "\"" << proto.name() + << "\" did not contain expected type \"" + << type_name << "\"."; +} + +// =================================================================== + +#if GTEST_HAS_PARAM_TEST + +// SimpleDescriptorDatabase, EncodedDescriptorDatabase, and +// DescriptorPoolDatabase call for very similar tests. Instead of writing +// three nearly-identical sets of tests, we use parameterized tests to apply +// the same code to all three. + +// The parameterized test runs against a DescriptarDatabaseTestCase. We have +// implementations for each of the three classes we want to test. +class DescriptorDatabaseTestCase { + public: + virtual ~DescriptorDatabaseTestCase() {} + + virtual DescriptorDatabase* GetDatabase() = 0; + virtual bool AddToDatabase(const FileDescriptorProto& file) = 0; +}; + +// Factory function type. +typedef DescriptorDatabaseTestCase* DescriptorDatabaseTestCaseFactory(); + +// Specialization for SimpleDescriptorDatabase. +class SimpleDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase { + public: + static DescriptorDatabaseTestCase* New() { + return new SimpleDescriptorDatabaseTestCase; + } + + virtual ~SimpleDescriptorDatabaseTestCase() {} + + virtual DescriptorDatabase* GetDatabase() { + return &database_; + } + virtual bool AddToDatabase(const FileDescriptorProto& file) { + return database_.Add(file); + } + + private: + SimpleDescriptorDatabase database_; +}; + +// Specialization for EncodedDescriptorDatabase. +class EncodedDescriptorDatabaseTestCase : public DescriptorDatabaseTestCase { + public: + static DescriptorDatabaseTestCase* New() { + return new EncodedDescriptorDatabaseTestCase; + } + + virtual ~EncodedDescriptorDatabaseTestCase() {} + + virtual DescriptorDatabase* GetDatabase() { + return &database_; + } + virtual bool AddToDatabase(const FileDescriptorProto& file) { + string data; + file.SerializeToString(&data); + return database_.AddCopy(data.data(), data.size()); + } + + private: + EncodedDescriptorDatabase database_; +}; + +// Specialization for DescriptorPoolDatabase. +class DescriptorPoolDatabaseTestCase : public DescriptorDatabaseTestCase { + public: + static DescriptorDatabaseTestCase* New() { + return new EncodedDescriptorDatabaseTestCase; + } + + DescriptorPoolDatabaseTestCase() : database_(pool_) {} + virtual ~DescriptorPoolDatabaseTestCase() {} + + virtual DescriptorDatabase* GetDatabase() { + return &database_; + } + virtual bool AddToDatabase(const FileDescriptorProto& file) { + return pool_.BuildFile(file); + } + + private: + DescriptorPool pool_; + DescriptorPoolDatabase database_; +}; + +// ------------------------------------------------------------------- + +class DescriptorDatabaseTest + : public testing::TestWithParam { + protected: + virtual void SetUp() { + test_case_.reset(GetParam()()); + database_ = test_case_->GetDatabase(); + } + + void AddToDatabase(const char* file_descriptor_text) { + FileDescriptorProto file_proto; + EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto)); + EXPECT_TRUE(test_case_->AddToDatabase(file_proto)); + } + + void AddToDatabaseWithError(const char* file_descriptor_text) { + FileDescriptorProto file_proto; + EXPECT_TRUE(TextFormat::ParseFromString(file_descriptor_text, &file_proto)); + EXPECT_FALSE(test_case_->AddToDatabase(file_proto)); + } + + scoped_ptr test_case_; + DescriptorDatabase* database_; +}; + +TEST_P(DescriptorDatabaseTest, FindFileByName) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { name:\"Foo\" }"); + AddToDatabase( + "name: \"bar.proto\" " + "message_type { name:\"Bar\" }"); + + { + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileByName("foo.proto", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileByName("bar.proto", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // Fails to find undefined files. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileByName("baz.proto", &file)); + } +} + +TEST_P(DescriptorDatabaseTest, FindFileContainingSymbol) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " field { name:\"qux\" }" + " nested_type { name: \"Grault\" } " + " enum_type { name: \"Garply\" } " + "} " + "enum_type { " + " name: \"Waldo\" " + " value { name:\"FRED\" } " + "} " + "extension { name: \"plugh\" } " + "service { " + " name: \"Xyzzy\" " + " method { name: \"Thud\" } " + "}" + ); + AddToDatabase( + "name: \"bar.proto\" " + "package: \"corge\" " + "message_type { name: \"Bar\" }"); + + { + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Foo", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find fields. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.qux", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find nested types. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Grault", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find nested enums. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Foo.Garply", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find enum types. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find enum values. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Waldo.FRED", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find extensions. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("plugh", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find services. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find methods. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("Xyzzy.Thud", &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + // Can find things in packages. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingSymbol("corge.Bar", &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Fails to find undefined symbols. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileContainingSymbol("Baz", &file)); + } + + { + // Names must be fully-qualified. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileContainingSymbol("Bar", &file)); + } +} + +TEST_P(DescriptorDatabaseTest, FindFileContainingExtension) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }" + "}"); + AddToDatabase( + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" extendee: \".Foo\" number:32 } " + "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " + "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); + + { + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 5, &file)); + EXPECT_EQ("foo.proto", file.name()); + } + + { + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingExtension("Foo", 32, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can find extensions for qualified type names. + FileDescriptorProto file; + EXPECT_TRUE(database_->FindFileContainingExtension("corge.Bar", 70, &file)); + EXPECT_EQ("bar.proto", file.name()); + } + + { + // Can't find extensions whose extendee was not fully-qualified in the + // FileDescriptorProto. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 56, &file)); + EXPECT_FALSE( + database_->FindFileContainingExtension("corge.Bar", 56, &file)); + } + + { + // Can't find non-existent extension numbers. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileContainingExtension("Foo", 12, &file)); + } + + { + // Can't find extensions for non-existent types. + FileDescriptorProto file; + EXPECT_FALSE( + database_->FindFileContainingExtension("NoSuchType", 5, &file)); + } + + { + // Can't find extensions for unqualified type names. + FileDescriptorProto file; + EXPECT_FALSE(database_->FindFileContainingExtension("Bar", 70, &file)); + } +} + +TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + " extension_range { start: 1 end: 1000 } " + " extension { name:\"qux\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }" + "}"); + AddToDatabase( + "name: \"bar.proto\" " + "package: \"corge\" " + "dependency: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + " extension_range { start: 1 end: 1000 } " + "} " + "extension { name:\"grault\" extendee: \".Foo\" number:32 } " + "extension { name:\"garply\" extendee: \".corge.Bar\" number:70 } " + "extension { name:\"waldo\" extendee: \"Bar\" number:56 } "); + + { + vector numbers; + EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers)); + ASSERT_EQ(2, numbers.size()); + sort(numbers.begin(), numbers.end()); + EXPECT_EQ(5, numbers[0]); + EXPECT_EQ(32, numbers[1]); + } + + { + vector numbers; + EXPECT_TRUE(database_->FindAllExtensionNumbers("corge.Bar", &numbers)); + // Note: won't find extension 56 due to the name not being fully qualified. + ASSERT_EQ(1, numbers.size()); + EXPECT_EQ(70, numbers[0]); + } + + { + // Can't find extensions for non-existent types. + vector numbers; + EXPECT_FALSE(database_->FindAllExtensionNumbers("NoSuchType", &numbers)); + } + + { + // Can't find extensions for unqualified types. + vector numbers; + EXPECT_FALSE(database_->FindAllExtensionNumbers("Bar", &numbers)); + } +} + +TEST_P(DescriptorDatabaseTest, ConflictingFileError) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); + AddToDatabaseWithError( + "name: \"foo.proto\" " + "message_type { " + " name: \"Bar\" " + "}"); +} + +TEST_P(DescriptorDatabaseTest, ConflictingTypeError) { + AddToDatabase( + "name: \"foo.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); + AddToDatabaseWithError( + "name: \"bar.proto\" " + "message_type { " + " name: \"Foo\" " + "}"); +} + +TEST_P(DescriptorDatabaseTest, ConflictingExtensionError) { + AddToDatabase( + "name: \"foo.proto\" " + "extension { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }"); + AddToDatabaseWithError( + "name: \"bar.proto\" " + "extension { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 " + " extendee: \".Foo\" }"); +} + +INSTANTIATE_TEST_CASE_P(Simple, DescriptorDatabaseTest, + testing::Values(&SimpleDescriptorDatabaseTestCase::New)); +INSTANTIATE_TEST_CASE_P(MemoryConserving, DescriptorDatabaseTest, + testing::Values(&EncodedDescriptorDatabaseTestCase::New)); +INSTANTIATE_TEST_CASE_P(Pool, DescriptorDatabaseTest, + testing::Values(&DescriptorPoolDatabaseTestCase::New)); + +#endif // GTEST_HAS_PARAM_TEST + +TEST(EncodedDescriptorDatabaseExtraTest, FindNameOfFileContainingSymbol) { + // Create two files, one of which is in two parts. + FileDescriptorProto file1, file2a, file2b; + file1.set_name("foo.proto"); + file1.set_package("foo"); + file1.add_message_type()->set_name("Foo"); + file2a.set_name("bar.proto"); + file2b.set_package("bar"); + file2b.add_message_type()->set_name("Bar"); + + // Normal serialization allows our optimization to kick in. + string data1 = file1.SerializeAsString(); + + // Force out-of-order serialization to test slow path. + string data2 = file2b.SerializeAsString() + file2a.SerializeAsString(); + + // Create EncodedDescriptorDatabase containing both files. + EncodedDescriptorDatabase db; + db.Add(data1.data(), data1.size()); + db.Add(data2.data(), data2.size()); + + // Test! + string filename; + EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo", &filename)); + EXPECT_EQ("foo.proto", filename); + EXPECT_TRUE(db.FindNameOfFileContainingSymbol("foo.Foo.Blah", &filename)); + EXPECT_EQ("foo.proto", filename); + EXPECT_TRUE(db.FindNameOfFileContainingSymbol("bar.Bar", &filename)); + EXPECT_EQ("bar.proto", filename); + EXPECT_FALSE(db.FindNameOfFileContainingSymbol("foo", &filename)); + EXPECT_FALSE(db.FindNameOfFileContainingSymbol("bar", &filename)); + EXPECT_FALSE(db.FindNameOfFileContainingSymbol("baz.Baz", &filename)); +} + +// =================================================================== + +class MergedDescriptorDatabaseTest : public testing::Test { + protected: + MergedDescriptorDatabaseTest() + : forward_merged_(&database1_, &database2_), + reverse_merged_(&database2_, &database1_) {} + + virtual void SetUp() { + AddToDatabase(&database1_, + "name: \"foo.proto\" " + "message_type { name:\"Foo\" extension_range { start: 1 end: 100 } } " + "extension { name:\"foo_ext\" extendee: \".Foo\" number:3 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase(&database2_, + "name: \"bar.proto\" " + "message_type { name:\"Bar\" extension_range { start: 1 end: 100 } } " + "extension { name:\"bar_ext\" extendee: \".Bar\" number:5 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + + // baz.proto exists in both pools, with different definitions. + AddToDatabase(&database1_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool1\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } " + "extension { name:\"database1_only_ext\" extendee: \".Baz\" number:13 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + AddToDatabase(&database2_, + "name: \"baz.proto\" " + "message_type { name:\"Baz\" extension_range { start: 1 end: 100 } } " + "message_type { name:\"FromPool2\" } " + "extension { name:\"baz_ext\" extendee: \".Baz\" number:12 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + } + + SimpleDescriptorDatabase database1_; + SimpleDescriptorDatabase database2_; + + MergedDescriptorDatabase forward_merged_; + MergedDescriptorDatabase reverse_merged_; +}; + +TEST_F(MergedDescriptorDatabaseTest, FindFileByName) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("foo.proto", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("bar.proto", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileByName("baz.proto", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(reverse_merged_.FindFileByName("baz.proto", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // Can't find non-existent file. + FileDescriptorProto file; + EXPECT_FALSE(forward_merged_.FindFileByName("no_such.proto", &file)); + } +} + +TEST_F(MergedDescriptorDatabaseTest, FindFileContainingSymbol) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Foo", &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Bar", &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("Baz", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE(reverse_merged_.FindFileContainingSymbol("Baz", &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // FromPool1 only shows up in forward_merged_ because it is masked by + // database2_'s baz.proto in reverse_merged_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingSymbol("FromPool1", &file)); + EXPECT_FALSE(reverse_merged_.FindFileContainingSymbol("FromPool1", &file)); + } + + { + // Can't find non-existent symbol. + FileDescriptorProto file; + EXPECT_FALSE( + forward_merged_.FindFileContainingSymbol("NoSuchType", &file)); + } +} + +TEST_F(MergedDescriptorDatabaseTest, FindFileContainingExtension) { + { + // Can find file that is only in database1_. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Foo", 3, &file)); + EXPECT_EQ("foo.proto", file.name()); + ExpectContainsType(file, "Foo"); + } + + { + // Can find file that is only in database2_. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Bar", 5, &file)); + EXPECT_EQ("bar.proto", file.name()); + ExpectContainsType(file, "Bar"); + } + + { + // In forward_merged_, database1_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE( + forward_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool1"); + } + + { + // In reverse_merged_, database2_'s baz.proto takes precedence. + FileDescriptorProto file; + EXPECT_TRUE( + reverse_merged_.FindFileContainingExtension("Baz", 12, &file)); + EXPECT_EQ("baz.proto", file.name()); + ExpectContainsType(file, "FromPool2"); + } + + { + // Baz's extension 13 only shows up in forward_merged_ because it is + // masked by database2_'s baz.proto in reverse_merged_. + FileDescriptorProto file; + EXPECT_TRUE(forward_merged_.FindFileContainingExtension("Baz", 13, &file)); + EXPECT_FALSE(reverse_merged_.FindFileContainingExtension("Baz", 13, &file)); + } + + { + // Can't find non-existent extension. + FileDescriptorProto file; + EXPECT_FALSE( + forward_merged_.FindFileContainingExtension("Foo", 6, &file)); + } +} + +TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { + { + // Message only has extension in database1_ + vector numbers; + EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Foo", &numbers)); + ASSERT_EQ(1, numbers.size()); + EXPECT_EQ(3, numbers[0]); + } + + { + // Message only has extension in database2_ + vector numbers; + EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Bar", &numbers)); + ASSERT_EQ(1, numbers.size()); + EXPECT_EQ(5, numbers[0]); + } + + { + // Merge results from the two databases. + vector numbers; + EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers)); + ASSERT_EQ(2, numbers.size()); + sort(numbers.begin(), numbers.end()); + EXPECT_EQ(12, numbers[0]); + EXPECT_EQ(13, numbers[1]); + } + + { + vector numbers; + EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers)); + ASSERT_EQ(2, numbers.size()); + sort(numbers.begin(), numbers.end()); + EXPECT_EQ(12, numbers[0]); + EXPECT_EQ(13, numbers[1]); + } + + { + // Can't find extensions for a non-existent message. + vector numbers; + EXPECT_FALSE(reverse_merged_.FindAllExtensionNumbers("Blah", &numbers)); + } +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_unittest.cc new file mode 100644 index 000000000..86e6a49d8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/descriptor_unittest.cc @@ -0,0 +1,4656 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 makes extensive use of RFC 3092. :) + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { + +// Can't use an anonymous namespace here due to brokenness of Tru64 compiler. +namespace descriptor_unittest { + +// Some helpers to make assembling descriptors faster. +DescriptorProto* AddMessage(FileDescriptorProto* file, const string& name) { + DescriptorProto* result = file->add_message_type(); + result->set_name(name); + return result; +} + +DescriptorProto* AddNestedMessage(DescriptorProto* parent, const string& name) { + DescriptorProto* result = parent->add_nested_type(); + result->set_name(name); + return result; +} + +EnumDescriptorProto* AddEnum(FileDescriptorProto* file, const string& name) { + EnumDescriptorProto* result = file->add_enum_type(); + result->set_name(name); + return result; +} + +EnumDescriptorProto* AddNestedEnum(DescriptorProto* parent, + const string& name) { + EnumDescriptorProto* result = parent->add_enum_type(); + result->set_name(name); + return result; +} + +ServiceDescriptorProto* AddService(FileDescriptorProto* file, + const string& name) { + ServiceDescriptorProto* result = file->add_service(); + result->set_name(name); + return result; +} + +FieldDescriptorProto* AddField(DescriptorProto* parent, + const string& name, int number, + FieldDescriptorProto::Label label, + FieldDescriptorProto::Type type) { + FieldDescriptorProto* result = parent->add_field(); + result->set_name(name); + result->set_number(number); + result->set_label(label); + result->set_type(type); + return result; +} + +FieldDescriptorProto* AddExtension(FileDescriptorProto* file, + const string& extendee, + const string& name, int number, + FieldDescriptorProto::Label label, + FieldDescriptorProto::Type type) { + FieldDescriptorProto* result = file->add_extension(); + result->set_name(name); + result->set_number(number); + result->set_label(label); + result->set_type(type); + result->set_extendee(extendee); + return result; +} + +FieldDescriptorProto* AddNestedExtension(DescriptorProto* parent, + const string& extendee, + const string& name, int number, + FieldDescriptorProto::Label label, + FieldDescriptorProto::Type type) { + FieldDescriptorProto* result = parent->add_extension(); + result->set_name(name); + result->set_number(number); + result->set_label(label); + result->set_type(type); + result->set_extendee(extendee); + return result; +} + +DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent, + int start, int end) { + DescriptorProto::ExtensionRange* result = parent->add_extension_range(); + result->set_start(start); + result->set_end(end); + return result; +} + +EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, + const string& name, int number) { + EnumValueDescriptorProto* result = enum_proto->add_value(); + result->set_name(name); + result->set_number(number); + return result; +} + +MethodDescriptorProto* AddMethod(ServiceDescriptorProto* service, + const string& name, + const string& input_type, + const string& output_type) { + MethodDescriptorProto* result = service->add_method(); + result->set_name(name); + result->set_input_type(input_type); + result->set_output_type(output_type); + return result; +} + +// Empty enums technically aren't allowed. We need to insert a dummy value +// into them. +void AddEmptyEnum(FileDescriptorProto* file, const string& name) { + AddEnumValue(AddEnum(file, name), name + "_DUMMY", 1); +} + +// =================================================================== + +// Test simple files. +class FileDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // // in "foo.proto" + // message FooMessage { extensions 1; } + // enum FooEnum {FOO_ENUM_VALUE = 1;} + // service FooService {} + // extend FooMessage { optional int32 foo_extension = 1; } + // + // // in "bar.proto" + // package bar_package; + // message BarMessage { extensions 1; } + // enum BarEnum {BAR_ENUM_VALUE = 1;} + // service BarService {} + // extend BarMessage { optional int32 bar_extension = 1; } + // + // Also, we have an empty file "baz.proto". This file's purpose is to + // make sure that even though it has the same package as foo.proto, + // searching it for members of foo.proto won't work. + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + AddExtensionRange(AddMessage(&foo_file, "FooMessage"), 1, 2); + AddEnumValue(AddEnum(&foo_file, "FooEnum"), "FOO_ENUM_VALUE", 1); + AddService(&foo_file, "FooService"); + AddExtension(&foo_file, "FooMessage", "foo_extension", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + FileDescriptorProto bar_file; + bar_file.set_name("bar.proto"); + bar_file.set_package("bar_package"); + bar_file.add_dependency("foo.proto"); + AddExtensionRange(AddMessage(&bar_file, "BarMessage"), 1, 2); + AddEnumValue(AddEnum(&bar_file, "BarEnum"), "BAR_ENUM_VALUE", 1); + AddService(&bar_file, "BarService"); + AddExtension(&bar_file, "bar_package.BarMessage", "bar_extension", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + FileDescriptorProto baz_file; + baz_file.set_name("baz.proto"); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + bar_file_ = pool_.BuildFile(bar_file); + ASSERT_TRUE(bar_file_ != NULL); + + baz_file_ = pool_.BuildFile(baz_file); + ASSERT_TRUE(baz_file_ != NULL); + + ASSERT_EQ(1, foo_file_->message_type_count()); + foo_message_ = foo_file_->message_type(0); + ASSERT_EQ(1, foo_file_->enum_type_count()); + foo_enum_ = foo_file_->enum_type(0); + ASSERT_EQ(1, foo_enum_->value_count()); + foo_enum_value_ = foo_enum_->value(0); + ASSERT_EQ(1, foo_file_->service_count()); + foo_service_ = foo_file_->service(0); + ASSERT_EQ(1, foo_file_->extension_count()); + foo_extension_ = foo_file_->extension(0); + + ASSERT_EQ(1, bar_file_->message_type_count()); + bar_message_ = bar_file_->message_type(0); + ASSERT_EQ(1, bar_file_->enum_type_count()); + bar_enum_ = bar_file_->enum_type(0); + ASSERT_EQ(1, bar_enum_->value_count()); + bar_enum_value_ = bar_enum_->value(0); + ASSERT_EQ(1, bar_file_->service_count()); + bar_service_ = bar_file_->service(0); + ASSERT_EQ(1, bar_file_->extension_count()); + bar_extension_ = bar_file_->extension(0); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + const FileDescriptor* bar_file_; + const FileDescriptor* baz_file_; + + const Descriptor* foo_message_; + const EnumDescriptor* foo_enum_; + const EnumValueDescriptor* foo_enum_value_; + const ServiceDescriptor* foo_service_; + const FieldDescriptor* foo_extension_; + + const Descriptor* bar_message_; + const EnumDescriptor* bar_enum_; + const EnumValueDescriptor* bar_enum_value_; + const ServiceDescriptor* bar_service_; + const FieldDescriptor* bar_extension_; +}; + +TEST_F(FileDescriptorTest, Name) { + EXPECT_EQ("foo.proto", foo_file_->name()); + EXPECT_EQ("bar.proto", bar_file_->name()); + EXPECT_EQ("baz.proto", baz_file_->name()); +} + +TEST_F(FileDescriptorTest, Package) { + EXPECT_EQ("", foo_file_->package()); + EXPECT_EQ("bar_package", bar_file_->package()); +} + +TEST_F(FileDescriptorTest, Dependencies) { + EXPECT_EQ(0, foo_file_->dependency_count()); + EXPECT_EQ(1, bar_file_->dependency_count()); + EXPECT_EQ(foo_file_, bar_file_->dependency(0)); +} + +TEST_F(FileDescriptorTest, FindMessageTypeByName) { + EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage")); + EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage")); + + EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL); + EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL); + EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL); + + EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL); + EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL); +} + +TEST_F(FileDescriptorTest, FindEnumTypeByName) { + EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum")); + EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum")); + + EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL); + EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL); + EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL); + + EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL); + EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL); +} + +TEST_F(FileDescriptorTest, FindEnumValueByName) { + EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE")); + EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE")); + + EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL); + EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL); + EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL); + + EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL); +} + +TEST_F(FileDescriptorTest, FindServiceByName) { + EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService")); + EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService")); + + EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL); + EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL); + EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL); + + EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL); + EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL); +} + +TEST_F(FileDescriptorTest, FindExtensionByName) { + EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension")); + EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension")); + + EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL); + EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL); + EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL); + + EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL); + EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL); +} + +TEST_F(FileDescriptorTest, FindExtensionByNumber) { + EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1)); + EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1)); + + EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL); +} + +TEST_F(FileDescriptorTest, BuildAgain) { + // Test that if te call BuildFile again on the same input we get the same + // FileDescriptor back. + FileDescriptorProto file; + foo_file_->CopyTo(&file); + EXPECT_EQ(foo_file_, pool_.BuildFile(file)); + + // But if we change the file then it won't work. + file.set_package("some.other.package"); + EXPECT_TRUE(pool_.BuildFile(file) == NULL); +} + +// =================================================================== + +// Test simple flat messages and fields. +class DescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // // in "foo.proto" + // message TestForeign {} + // enum TestEnum {} + // + // message TestMessage { + // required string foo = 1; + // optional TestEnum bar = 6; + // repeated TestForeign baz = 500000000; + // optional group qux = 15 {} + // } + // + // // in "bar.proto" + // package corge.grault; + // message TestMessage2 { + // required string foo = 1; + // required string bar = 2; + // required string quux = 6; + // } + // + // We cheat and use TestForeign as the type for qux rather than create + // an actual nested type. + // + // Since all primitive types (including string) use the same building + // code, there's no need to test each one individually. + // + // TestMessage2 is primarily here to test FindFieldByName and friends. + // All messages created from the same DescriptorPool share the same lookup + // table, so we need to insure that they don't interfere. + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + AddMessage(&foo_file, "TestForeign"); + AddEmptyEnum(&foo_file, "TestEnum"); + + DescriptorProto* message = AddMessage(&foo_file, "TestMessage"); + AddField(message, "foo", 1, + FieldDescriptorProto::LABEL_REQUIRED, + FieldDescriptorProto::TYPE_STRING); + AddField(message, "bar", 6, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_ENUM) + ->set_type_name("TestEnum"); + AddField(message, "baz", 500000000, + FieldDescriptorProto::LABEL_REPEATED, + FieldDescriptorProto::TYPE_MESSAGE) + ->set_type_name("TestForeign"); + AddField(message, "qux", 15, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_GROUP) + ->set_type_name("TestForeign"); + + FileDescriptorProto bar_file; + bar_file.set_name("bar.proto"); + bar_file.set_package("corge.grault"); + + DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2"); + AddField(message2, "foo", 1, + FieldDescriptorProto::LABEL_REQUIRED, + FieldDescriptorProto::TYPE_STRING); + AddField(message2, "bar", 2, + FieldDescriptorProto::LABEL_REQUIRED, + FieldDescriptorProto::TYPE_STRING); + AddField(message2, "quux", 6, + FieldDescriptorProto::LABEL_REQUIRED, + FieldDescriptorProto::TYPE_STRING); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + bar_file_ = pool_.BuildFile(bar_file); + ASSERT_TRUE(bar_file_ != NULL); + + ASSERT_EQ(1, foo_file_->enum_type_count()); + enum_ = foo_file_->enum_type(0); + + ASSERT_EQ(2, foo_file_->message_type_count()); + foreign_ = foo_file_->message_type(0); + message_ = foo_file_->message_type(1); + + ASSERT_EQ(4, message_->field_count()); + foo_ = message_->field(0); + bar_ = message_->field(1); + baz_ = message_->field(2); + qux_ = message_->field(3); + + ASSERT_EQ(1, bar_file_->message_type_count()); + message2_ = bar_file_->message_type(0); + + ASSERT_EQ(3, message2_->field_count()); + foo2_ = message2_->field(0); + bar2_ = message2_->field(1); + quux2_ = message2_->field(2); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + const FileDescriptor* bar_file_; + + const Descriptor* message_; + const Descriptor* message2_; + const Descriptor* foreign_; + const EnumDescriptor* enum_; + + const FieldDescriptor* foo_; + const FieldDescriptor* bar_; + const FieldDescriptor* baz_; + const FieldDescriptor* qux_; + + const FieldDescriptor* foo2_; + const FieldDescriptor* bar2_; + const FieldDescriptor* quux2_; +}; + +TEST_F(DescriptorTest, Name) { + EXPECT_EQ("TestMessage", message_->name()); + EXPECT_EQ("TestMessage", message_->full_name()); + EXPECT_EQ(foo_file_, message_->file()); + + EXPECT_EQ("TestMessage2", message2_->name()); + EXPECT_EQ("corge.grault.TestMessage2", message2_->full_name()); + EXPECT_EQ(bar_file_, message2_->file()); +} + +TEST_F(DescriptorTest, ContainingType) { + EXPECT_TRUE(message_->containing_type() == NULL); + EXPECT_TRUE(message2_->containing_type() == NULL); +} + +TEST_F(DescriptorTest, FieldsByIndex) { + ASSERT_EQ(4, message_->field_count()); + EXPECT_EQ(foo_, message_->field(0)); + EXPECT_EQ(bar_, message_->field(1)); + EXPECT_EQ(baz_, message_->field(2)); + EXPECT_EQ(qux_, message_->field(3)); +} + +TEST_F(DescriptorTest, FindFieldByName) { + // All messages in the same DescriptorPool share a single lookup table for + // fields. So, in addition to testing that FindFieldByName finds the fields + // of the message, we need to test that it does *not* find the fields of + // *other* messages. + + EXPECT_EQ(foo_, message_->FindFieldByName("foo")); + EXPECT_EQ(bar_, message_->FindFieldByName("bar")); + EXPECT_EQ(baz_, message_->FindFieldByName("baz")); + EXPECT_EQ(qux_, message_->FindFieldByName("qux")); + EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL); + EXPECT_TRUE(message_->FindFieldByName("quux") == NULL); + + EXPECT_EQ(foo2_ , message2_->FindFieldByName("foo" )); + EXPECT_EQ(bar2_ , message2_->FindFieldByName("bar" )); + EXPECT_EQ(quux2_, message2_->FindFieldByName("quux")); + EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL); + EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL); +} + +TEST_F(DescriptorTest, FindFieldByNumber) { + EXPECT_EQ(foo_, message_->FindFieldByNumber(1)); + EXPECT_EQ(bar_, message_->FindFieldByNumber(6)); + EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000)); + EXPECT_EQ(qux_, message_->FindFieldByNumber(15)); + EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL); + EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL); + + EXPECT_EQ(foo2_ , message2_->FindFieldByNumber(1)); + EXPECT_EQ(bar2_ , message2_->FindFieldByNumber(2)); + EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6)); + EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL); + EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL); +} + +TEST_F(DescriptorTest, FieldName) { + EXPECT_EQ("foo", foo_->name()); + EXPECT_EQ("bar", bar_->name()); + EXPECT_EQ("baz", baz_->name()); + EXPECT_EQ("qux", qux_->name()); +} + +TEST_F(DescriptorTest, FieldFullName) { + EXPECT_EQ("TestMessage.foo", foo_->full_name()); + EXPECT_EQ("TestMessage.bar", bar_->full_name()); + EXPECT_EQ("TestMessage.baz", baz_->full_name()); + EXPECT_EQ("TestMessage.qux", qux_->full_name()); + + EXPECT_EQ("corge.grault.TestMessage2.foo", foo2_->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.bar", bar2_->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name()); +} + +TEST_F(DescriptorTest, FieldFile) { + EXPECT_EQ(foo_file_, foo_->file()); + EXPECT_EQ(foo_file_, bar_->file()); + EXPECT_EQ(foo_file_, baz_->file()); + EXPECT_EQ(foo_file_, qux_->file()); + + EXPECT_EQ(bar_file_, foo2_->file()); + EXPECT_EQ(bar_file_, bar2_->file()); + EXPECT_EQ(bar_file_, quux2_->file()); +} + +TEST_F(DescriptorTest, FieldIndex) { + EXPECT_EQ(0, foo_->index()); + EXPECT_EQ(1, bar_->index()); + EXPECT_EQ(2, baz_->index()); + EXPECT_EQ(3, qux_->index()); +} + +TEST_F(DescriptorTest, FieldNumber) { + EXPECT_EQ( 1, foo_->number()); + EXPECT_EQ( 6, bar_->number()); + EXPECT_EQ(500000000, baz_->number()); + EXPECT_EQ( 15, qux_->number()); +} + +TEST_F(DescriptorTest, FieldType) { + EXPECT_EQ(FieldDescriptor::TYPE_STRING , foo_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_ENUM , bar_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_->type()); + EXPECT_EQ(FieldDescriptor::TYPE_GROUP , qux_->type()); +} + +TEST_F(DescriptorTest, FieldLabel) { + EXPECT_EQ(FieldDescriptor::LABEL_REQUIRED, foo_->label()); + EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->label()); + EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, baz_->label()); + EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, qux_->label()); + + EXPECT_TRUE (foo_->is_required()); + EXPECT_FALSE(foo_->is_optional()); + EXPECT_FALSE(foo_->is_repeated()); + + EXPECT_FALSE(bar_->is_required()); + EXPECT_TRUE (bar_->is_optional()); + EXPECT_FALSE(bar_->is_repeated()); + + EXPECT_FALSE(baz_->is_required()); + EXPECT_FALSE(baz_->is_optional()); + EXPECT_TRUE (baz_->is_repeated()); +} + +TEST_F(DescriptorTest, FieldHasDefault) { + EXPECT_FALSE(foo_->has_default_value()); + EXPECT_FALSE(bar_->has_default_value()); + EXPECT_FALSE(baz_->has_default_value()); + EXPECT_FALSE(qux_->has_default_value()); +} + +TEST_F(DescriptorTest, FieldContainingType) { + EXPECT_EQ(message_, foo_->containing_type()); + EXPECT_EQ(message_, bar_->containing_type()); + EXPECT_EQ(message_, baz_->containing_type()); + EXPECT_EQ(message_, qux_->containing_type()); + + EXPECT_EQ(message2_, foo2_ ->containing_type()); + EXPECT_EQ(message2_, bar2_ ->containing_type()); + EXPECT_EQ(message2_, quux2_->containing_type()); +} + +TEST_F(DescriptorTest, FieldMessageType) { + EXPECT_TRUE(foo_->message_type() == NULL); + EXPECT_TRUE(bar_->message_type() == NULL); + + EXPECT_EQ(foreign_, baz_->message_type()); + EXPECT_EQ(foreign_, qux_->message_type()); +} + +TEST_F(DescriptorTest, FieldEnumType) { + EXPECT_TRUE(foo_->enum_type() == NULL); + EXPECT_TRUE(baz_->enum_type() == NULL); + EXPECT_TRUE(qux_->enum_type() == NULL); + + EXPECT_EQ(enum_, bar_->enum_type()); +} + +// =================================================================== + +class StylizedFieldNamesTest : public testing::Test { + protected: + void SetUp() { + FileDescriptorProto file; + file.set_name("foo.proto"); + + AddExtensionRange(AddMessage(&file, "ExtendableMessage"), 1, 1000); + + DescriptorProto* message = AddMessage(&file, "TestMessage"); + AddField(message, "foo_foo", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(message, "FooBar", 2, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(message, "fooBaz", 3, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(message, "fooFoo", 4, // Camel-case conflict with foo_foo. + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(message, "foobar", 5, // Lower-case conflict with FooBar. + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + AddNestedExtension(message, "ExtendableMessage", "bar_foo", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddNestedExtension(message, "ExtendableMessage", "BarBar", 2, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddNestedExtension(message, "ExtendableMessage", "BarBaz", 3, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddNestedExtension(message, "ExtendableMessage", "barFoo", 4, // Conflict + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddNestedExtension(message, "ExtendableMessage", "barbar", 5, // Conflict + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + AddExtension(&file, "ExtendableMessage", "baz_foo", 11, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddExtension(&file, "ExtendableMessage", "BazBar", 12, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddExtension(&file, "ExtendableMessage", "BazBaz", 13, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddExtension(&file, "ExtendableMessage", "bazFoo", 14, // Conflict + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddExtension(&file, "ExtendableMessage", "bazbar", 15, // Conflict + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + file_ = pool_.BuildFile(file); + ASSERT_TRUE(file_ != NULL); + ASSERT_EQ(2, file_->message_type_count()); + message_ = file_->message_type(1); + ASSERT_EQ("TestMessage", message_->name()); + ASSERT_EQ(5, message_->field_count()); + ASSERT_EQ(5, message_->extension_count()); + ASSERT_EQ(5, file_->extension_count()); + } + + DescriptorPool pool_; + const FileDescriptor* file_; + const Descriptor* message_; +}; + +TEST_F(StylizedFieldNamesTest, LowercaseName) { + EXPECT_EQ("foo_foo", message_->field(0)->lowercase_name()); + EXPECT_EQ("foobar" , message_->field(1)->lowercase_name()); + EXPECT_EQ("foobaz" , message_->field(2)->lowercase_name()); + EXPECT_EQ("foofoo" , message_->field(3)->lowercase_name()); + EXPECT_EQ("foobar" , message_->field(4)->lowercase_name()); + + EXPECT_EQ("bar_foo", message_->extension(0)->lowercase_name()); + EXPECT_EQ("barbar" , message_->extension(1)->lowercase_name()); + EXPECT_EQ("barbaz" , message_->extension(2)->lowercase_name()); + EXPECT_EQ("barfoo" , message_->extension(3)->lowercase_name()); + EXPECT_EQ("barbar" , message_->extension(4)->lowercase_name()); + + EXPECT_EQ("baz_foo", file_->extension(0)->lowercase_name()); + EXPECT_EQ("bazbar" , file_->extension(1)->lowercase_name()); + EXPECT_EQ("bazbaz" , file_->extension(2)->lowercase_name()); + EXPECT_EQ("bazfoo" , file_->extension(3)->lowercase_name()); + EXPECT_EQ("bazbar" , file_->extension(4)->lowercase_name()); +} + +TEST_F(StylizedFieldNamesTest, CamelcaseName) { + EXPECT_EQ("fooFoo", message_->field(0)->camelcase_name()); + EXPECT_EQ("fooBar", message_->field(1)->camelcase_name()); + EXPECT_EQ("fooBaz", message_->field(2)->camelcase_name()); + EXPECT_EQ("fooFoo", message_->field(3)->camelcase_name()); + EXPECT_EQ("foobar", message_->field(4)->camelcase_name()); + + EXPECT_EQ("barFoo", message_->extension(0)->camelcase_name()); + EXPECT_EQ("barBar", message_->extension(1)->camelcase_name()); + EXPECT_EQ("barBaz", message_->extension(2)->camelcase_name()); + EXPECT_EQ("barFoo", message_->extension(3)->camelcase_name()); + EXPECT_EQ("barbar", message_->extension(4)->camelcase_name()); + + EXPECT_EQ("bazFoo", file_->extension(0)->camelcase_name()); + EXPECT_EQ("bazBar", file_->extension(1)->camelcase_name()); + EXPECT_EQ("bazBaz", file_->extension(2)->camelcase_name()); + EXPECT_EQ("bazFoo", file_->extension(3)->camelcase_name()); + EXPECT_EQ("bazbar", file_->extension(4)->camelcase_name()); +} + +TEST_F(StylizedFieldNamesTest, FindByLowercaseName) { + EXPECT_EQ(message_->field(0), + message_->FindFieldByLowercaseName("foo_foo")); + EXPECT_EQ(message_->field(1), + message_->FindFieldByLowercaseName("foobar")); + EXPECT_EQ(message_->field(2), + message_->FindFieldByLowercaseName("foobaz")); + EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL); + EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL); + EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL); + EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL); + + EXPECT_EQ(message_->extension(0), + message_->FindExtensionByLowercaseName("bar_foo")); + EXPECT_EQ(message_->extension(1), + message_->FindExtensionByLowercaseName("barbar")); + EXPECT_EQ(message_->extension(2), + message_->FindExtensionByLowercaseName("barbaz")); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL); + EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL); + + EXPECT_EQ(file_->extension(0), + file_->FindExtensionByLowercaseName("baz_foo")); + EXPECT_EQ(file_->extension(1), + file_->FindExtensionByLowercaseName("bazbar")); + EXPECT_EQ(file_->extension(2), + file_->FindExtensionByLowercaseName("bazbaz")); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL); + EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL); +} + +TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) { + EXPECT_EQ(message_->field(0), + message_->FindFieldByCamelcaseName("fooFoo")); + EXPECT_EQ(message_->field(1), + message_->FindFieldByCamelcaseName("fooBar")); + EXPECT_EQ(message_->field(2), + message_->FindFieldByCamelcaseName("fooBaz")); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL); + EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL); + + EXPECT_EQ(message_->extension(0), + message_->FindExtensionByCamelcaseName("barFoo")); + EXPECT_EQ(message_->extension(1), + message_->FindExtensionByCamelcaseName("barBar")); + EXPECT_EQ(message_->extension(2), + message_->FindExtensionByCamelcaseName("barBaz")); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL); + EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL); + + EXPECT_EQ(file_->extension(0), + file_->FindExtensionByCamelcaseName("bazFoo")); + EXPECT_EQ(file_->extension(1), + file_->FindExtensionByCamelcaseName("bazBar")); + EXPECT_EQ(file_->extension(2), + file_->FindExtensionByCamelcaseName("bazBaz")); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL); + EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL); +} + +// =================================================================== + +// Test enum descriptors. +class EnumDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // // in "foo.proto" + // enum TestEnum { + // FOO = 1; + // BAR = 2; + // } + // + // // in "bar.proto" + // package corge.grault; + // enum TestEnum2 { + // FOO = 1; + // BAZ = 3; + // } + // + // TestEnum2 is primarily here to test FindValueByName and friends. + // All enums created from the same DescriptorPool share the same lookup + // table, so we need to insure that they don't interfere. + + // TestEnum + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + EnumDescriptorProto* enum_proto = AddEnum(&foo_file, "TestEnum"); + AddEnumValue(enum_proto, "FOO", 1); + AddEnumValue(enum_proto, "BAR", 2); + + // TestEnum2 + FileDescriptorProto bar_file; + bar_file.set_name("bar.proto"); + bar_file.set_package("corge.grault"); + + EnumDescriptorProto* enum2_proto = AddEnum(&bar_file, "TestEnum2"); + AddEnumValue(enum2_proto, "FOO", 1); + AddEnumValue(enum2_proto, "BAZ", 3); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + bar_file_ = pool_.BuildFile(bar_file); + ASSERT_TRUE(bar_file_ != NULL); + + ASSERT_EQ(1, foo_file_->enum_type_count()); + enum_ = foo_file_->enum_type(0); + + ASSERT_EQ(2, enum_->value_count()); + foo_ = enum_->value(0); + bar_ = enum_->value(1); + + ASSERT_EQ(1, bar_file_->enum_type_count()); + enum2_ = bar_file_->enum_type(0); + + ASSERT_EQ(2, enum2_->value_count()); + foo2_ = enum2_->value(0); + baz2_ = enum2_->value(1); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + const FileDescriptor* bar_file_; + + const EnumDescriptor* enum_; + const EnumDescriptor* enum2_; + + const EnumValueDescriptor* foo_; + const EnumValueDescriptor* bar_; + + const EnumValueDescriptor* foo2_; + const EnumValueDescriptor* baz2_; +}; + +TEST_F(EnumDescriptorTest, Name) { + EXPECT_EQ("TestEnum", enum_->name()); + EXPECT_EQ("TestEnum", enum_->full_name()); + EXPECT_EQ(foo_file_, enum_->file()); + + EXPECT_EQ("TestEnum2", enum2_->name()); + EXPECT_EQ("corge.grault.TestEnum2", enum2_->full_name()); + EXPECT_EQ(bar_file_, enum2_->file()); +} + +TEST_F(EnumDescriptorTest, ContainingType) { + EXPECT_TRUE(enum_->containing_type() == NULL); + EXPECT_TRUE(enum2_->containing_type() == NULL); +} + +TEST_F(EnumDescriptorTest, ValuesByIndex) { + ASSERT_EQ(2, enum_->value_count()); + EXPECT_EQ(foo_, enum_->value(0)); + EXPECT_EQ(bar_, enum_->value(1)); +} + +TEST_F(EnumDescriptorTest, FindValueByName) { + EXPECT_EQ(foo_ , enum_ ->FindValueByName("FOO")); + EXPECT_EQ(bar_ , enum_ ->FindValueByName("BAR")); + EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO")); + EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ")); + + EXPECT_TRUE(enum_ ->FindValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(enum_ ->FindValueByName("BAZ" ) == NULL); + EXPECT_TRUE(enum2_->FindValueByName("BAR" ) == NULL); +} + +TEST_F(EnumDescriptorTest, FindValueByNumber) { + EXPECT_EQ(foo_ , enum_ ->FindValueByNumber(1)); + EXPECT_EQ(bar_ , enum_ ->FindValueByNumber(2)); + EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1)); + EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3)); + + EXPECT_TRUE(enum_ ->FindValueByNumber(416) == NULL); + EXPECT_TRUE(enum_ ->FindValueByNumber(3) == NULL); + EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL); +} + +TEST_F(EnumDescriptorTest, ValueName) { + EXPECT_EQ("FOO", foo_->name()); + EXPECT_EQ("BAR", bar_->name()); +} + +TEST_F(EnumDescriptorTest, ValueFullName) { + EXPECT_EQ("FOO", foo_->full_name()); + EXPECT_EQ("BAR", bar_->full_name()); + EXPECT_EQ("corge.grault.FOO", foo2_->full_name()); + EXPECT_EQ("corge.grault.BAZ", baz2_->full_name()); +} + +TEST_F(EnumDescriptorTest, ValueIndex) { + EXPECT_EQ(0, foo_->index()); + EXPECT_EQ(1, bar_->index()); +} + +TEST_F(EnumDescriptorTest, ValueNumber) { + EXPECT_EQ(1, foo_->number()); + EXPECT_EQ(2, bar_->number()); +} + +TEST_F(EnumDescriptorTest, ValueType) { + EXPECT_EQ(enum_ , foo_ ->type()); + EXPECT_EQ(enum_ , bar_ ->type()); + EXPECT_EQ(enum2_, foo2_->type()); + EXPECT_EQ(enum2_, baz2_->type()); +} + +// =================================================================== + +// Test service descriptors. +class ServiceDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following messages and service: + // // in "foo.proto" + // message FooRequest {} + // message FooResponse {} + // message BarRequest {} + // message BarResponse {} + // message BazRequest {} + // message BazResponse {} + // + // service TestService { + // rpc Foo(FooRequest) returns (FooResponse); + // rpc Bar(BarRequest) returns (BarResponse); + // } + // + // // in "bar.proto" + // package corge.grault + // service TestService2 { + // rpc Foo(FooRequest) returns (FooResponse); + // rpc Baz(BazRequest) returns (BazResponse); + // } + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + AddMessage(&foo_file, "FooRequest"); + AddMessage(&foo_file, "FooResponse"); + AddMessage(&foo_file, "BarRequest"); + AddMessage(&foo_file, "BarResponse"); + AddMessage(&foo_file, "BazRequest"); + AddMessage(&foo_file, "BazResponse"); + + ServiceDescriptorProto* service = AddService(&foo_file, "TestService"); + AddMethod(service, "Foo", "FooRequest", "FooResponse"); + AddMethod(service, "Bar", "BarRequest", "BarResponse"); + + FileDescriptorProto bar_file; + bar_file.set_name("bar.proto"); + bar_file.set_package("corge.grault"); + bar_file.add_dependency("foo.proto"); + + ServiceDescriptorProto* service2 = AddService(&bar_file, "TestService2"); + AddMethod(service2, "Foo", "FooRequest", "FooResponse"); + AddMethod(service2, "Baz", "BazRequest", "BazResponse"); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + bar_file_ = pool_.BuildFile(bar_file); + ASSERT_TRUE(bar_file_ != NULL); + + ASSERT_EQ(6, foo_file_->message_type_count()); + foo_request_ = foo_file_->message_type(0); + foo_response_ = foo_file_->message_type(1); + bar_request_ = foo_file_->message_type(2); + bar_response_ = foo_file_->message_type(3); + baz_request_ = foo_file_->message_type(4); + baz_response_ = foo_file_->message_type(5); + + ASSERT_EQ(1, foo_file_->service_count()); + service_ = foo_file_->service(0); + + ASSERT_EQ(2, service_->method_count()); + foo_ = service_->method(0); + bar_ = service_->method(1); + + ASSERT_EQ(1, bar_file_->service_count()); + service2_ = bar_file_->service(0); + + ASSERT_EQ(2, service2_->method_count()); + foo2_ = service2_->method(0); + baz2_ = service2_->method(1); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + const FileDescriptor* bar_file_; + + const Descriptor* foo_request_; + const Descriptor* foo_response_; + const Descriptor* bar_request_; + const Descriptor* bar_response_; + const Descriptor* baz_request_; + const Descriptor* baz_response_; + + const ServiceDescriptor* service_; + const ServiceDescriptor* service2_; + + const MethodDescriptor* foo_; + const MethodDescriptor* bar_; + + const MethodDescriptor* foo2_; + const MethodDescriptor* baz2_; +}; + +TEST_F(ServiceDescriptorTest, Name) { + EXPECT_EQ("TestService", service_->name()); + EXPECT_EQ("TestService", service_->full_name()); + EXPECT_EQ(foo_file_, service_->file()); + + EXPECT_EQ("TestService2", service2_->name()); + EXPECT_EQ("corge.grault.TestService2", service2_->full_name()); + EXPECT_EQ(bar_file_, service2_->file()); +} + +TEST_F(ServiceDescriptorTest, MethodsByIndex) { + ASSERT_EQ(2, service_->method_count()); + EXPECT_EQ(foo_, service_->method(0)); + EXPECT_EQ(bar_, service_->method(1)); +} + +TEST_F(ServiceDescriptorTest, FindMethodByName) { + EXPECT_EQ(foo_ , service_ ->FindMethodByName("Foo")); + EXPECT_EQ(bar_ , service_ ->FindMethodByName("Bar")); + EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo")); + EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz")); + + EXPECT_TRUE(service_ ->FindMethodByName("NoSuchMethod") == NULL); + EXPECT_TRUE(service_ ->FindMethodByName("Baz" ) == NULL); + EXPECT_TRUE(service2_->FindMethodByName("Bar" ) == NULL); +} + +TEST_F(ServiceDescriptorTest, MethodName) { + EXPECT_EQ("Foo", foo_->name()); + EXPECT_EQ("Bar", bar_->name()); +} + +TEST_F(ServiceDescriptorTest, MethodFullName) { + EXPECT_EQ("TestService.Foo", foo_->full_name()); + EXPECT_EQ("TestService.Bar", bar_->full_name()); + EXPECT_EQ("corge.grault.TestService2.Foo", foo2_->full_name()); + EXPECT_EQ("corge.grault.TestService2.Baz", baz2_->full_name()); +} + +TEST_F(ServiceDescriptorTest, MethodIndex) { + EXPECT_EQ(0, foo_->index()); + EXPECT_EQ(1, bar_->index()); +} + +TEST_F(ServiceDescriptorTest, MethodParent) { + EXPECT_EQ(service_, foo_->service()); + EXPECT_EQ(service_, bar_->service()); +} + +TEST_F(ServiceDescriptorTest, MethodInputType) { + EXPECT_EQ(foo_request_, foo_->input_type()); + EXPECT_EQ(bar_request_, bar_->input_type()); +} + +TEST_F(ServiceDescriptorTest, MethodOutputType) { + EXPECT_EQ(foo_response_, foo_->output_type()); + EXPECT_EQ(bar_response_, bar_->output_type()); +} + +// =================================================================== + +// Test nested types. +class NestedDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // // in "foo.proto" + // message TestMessage { + // message Foo {} + // message Bar {} + // enum Baz { A = 1; } + // enum Qux { B = 1; } + // } + // + // // in "bar.proto" + // package corge.grault; + // message TestMessage2 { + // message Foo {} + // message Baz {} + // enum Qux { A = 1; } + // enum Quux { C = 1; } + // } + // + // TestMessage2 is primarily here to test FindNestedTypeByName and friends. + // All messages created from the same DescriptorPool share the same lookup + // table, so we need to insure that they don't interfere. + // + // We add enum values to the enums in order to test searching for enum + // values across a message's scope. + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + DescriptorProto* message = AddMessage(&foo_file, "TestMessage"); + AddNestedMessage(message, "Foo"); + AddNestedMessage(message, "Bar"); + EnumDescriptorProto* baz = AddNestedEnum(message, "Baz"); + AddEnumValue(baz, "A", 1); + EnumDescriptorProto* qux = AddNestedEnum(message, "Qux"); + AddEnumValue(qux, "B", 1); + + FileDescriptorProto bar_file; + bar_file.set_name("bar.proto"); + bar_file.set_package("corge.grault"); + + DescriptorProto* message2 = AddMessage(&bar_file, "TestMessage2"); + AddNestedMessage(message2, "Foo"); + AddNestedMessage(message2, "Baz"); + EnumDescriptorProto* qux2 = AddNestedEnum(message2, "Qux"); + AddEnumValue(qux2, "A", 1); + EnumDescriptorProto* quux2 = AddNestedEnum(message2, "Quux"); + AddEnumValue(quux2, "C", 1); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + bar_file_ = pool_.BuildFile(bar_file); + ASSERT_TRUE(bar_file_ != NULL); + + ASSERT_EQ(1, foo_file_->message_type_count()); + message_ = foo_file_->message_type(0); + + ASSERT_EQ(2, message_->nested_type_count()); + foo_ = message_->nested_type(0); + bar_ = message_->nested_type(1); + + ASSERT_EQ(2, message_->enum_type_count()); + baz_ = message_->enum_type(0); + qux_ = message_->enum_type(1); + + ASSERT_EQ(1, baz_->value_count()); + a_ = baz_->value(0); + ASSERT_EQ(1, qux_->value_count()); + b_ = qux_->value(0); + + ASSERT_EQ(1, bar_file_->message_type_count()); + message2_ = bar_file_->message_type(0); + + ASSERT_EQ(2, message2_->nested_type_count()); + foo2_ = message2_->nested_type(0); + baz2_ = message2_->nested_type(1); + + ASSERT_EQ(2, message2_->enum_type_count()); + qux2_ = message2_->enum_type(0); + quux2_ = message2_->enum_type(1); + + ASSERT_EQ(1, qux2_->value_count()); + a2_ = qux2_->value(0); + ASSERT_EQ(1, quux2_->value_count()); + c2_ = quux2_->value(0); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + const FileDescriptor* bar_file_; + + const Descriptor* message_; + const Descriptor* message2_; + + const Descriptor* foo_; + const Descriptor* bar_; + const EnumDescriptor* baz_; + const EnumDescriptor* qux_; + const EnumValueDescriptor* a_; + const EnumValueDescriptor* b_; + + const Descriptor* foo2_; + const Descriptor* baz2_; + const EnumDescriptor* qux2_; + const EnumDescriptor* quux2_; + const EnumValueDescriptor* a2_; + const EnumValueDescriptor* c2_; +}; + +TEST_F(NestedDescriptorTest, MessageName) { + EXPECT_EQ("Foo", foo_ ->name()); + EXPECT_EQ("Bar", bar_ ->name()); + EXPECT_EQ("Foo", foo2_->name()); + EXPECT_EQ("Baz", baz2_->name()); + + EXPECT_EQ("TestMessage.Foo", foo_->full_name()); + EXPECT_EQ("TestMessage.Bar", bar_->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.Foo", foo2_->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.Baz", baz2_->full_name()); +} + +TEST_F(NestedDescriptorTest, MessageContainingType) { + EXPECT_EQ(message_ , foo_ ->containing_type()); + EXPECT_EQ(message_ , bar_ ->containing_type()); + EXPECT_EQ(message2_, foo2_->containing_type()); + EXPECT_EQ(message2_, baz2_->containing_type()); +} + +TEST_F(NestedDescriptorTest, NestedMessagesByIndex) { + ASSERT_EQ(2, message_->nested_type_count()); + EXPECT_EQ(foo_, message_->nested_type(0)); + EXPECT_EQ(bar_, message_->nested_type(1)); +} + +TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) { + EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL); + EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL); + EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL); + EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL); +} + +TEST_F(NestedDescriptorTest, FindNestedTypeByName) { + EXPECT_EQ(foo_ , message_ ->FindNestedTypeByName("Foo")); + EXPECT_EQ(bar_ , message_ ->FindNestedTypeByName("Bar")); + EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo")); + EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz")); + + EXPECT_TRUE(message_ ->FindNestedTypeByName("NoSuchType") == NULL); + EXPECT_TRUE(message_ ->FindNestedTypeByName("Baz" ) == NULL); + EXPECT_TRUE(message2_->FindNestedTypeByName("Bar" ) == NULL); + + EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL); +} + +TEST_F(NestedDescriptorTest, EnumName) { + EXPECT_EQ("Baz" , baz_ ->name()); + EXPECT_EQ("Qux" , qux_ ->name()); + EXPECT_EQ("Qux" , qux2_->name()); + EXPECT_EQ("Quux", quux2_->name()); + + EXPECT_EQ("TestMessage.Baz", baz_->full_name()); + EXPECT_EQ("TestMessage.Qux", qux_->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.Qux" , qux2_ ->full_name()); + EXPECT_EQ("corge.grault.TestMessage2.Quux", quux2_->full_name()); +} + +TEST_F(NestedDescriptorTest, EnumContainingType) { + EXPECT_EQ(message_ , baz_ ->containing_type()); + EXPECT_EQ(message_ , qux_ ->containing_type()); + EXPECT_EQ(message2_, qux2_ ->containing_type()); + EXPECT_EQ(message2_, quux2_->containing_type()); +} + +TEST_F(NestedDescriptorTest, NestedEnumsByIndex) { + ASSERT_EQ(2, message_->nested_type_count()); + EXPECT_EQ(foo_, message_->nested_type(0)); + EXPECT_EQ(bar_, message_->nested_type(1)); +} + +TEST_F(NestedDescriptorTest, FindEnumTypeByName) { + EXPECT_EQ(baz_ , message_ ->FindEnumTypeByName("Baz" )); + EXPECT_EQ(qux_ , message_ ->FindEnumTypeByName("Qux" )); + EXPECT_EQ(qux2_ , message2_->FindEnumTypeByName("Qux" )); + EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux")); + + EXPECT_TRUE(message_ ->FindEnumTypeByName("NoSuchType") == NULL); + EXPECT_TRUE(message_ ->FindEnumTypeByName("Quux" ) == NULL); + EXPECT_TRUE(message2_->FindEnumTypeByName("Baz" ) == NULL); + + EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL); +} + +TEST_F(NestedDescriptorTest, FindEnumValueByName) { + EXPECT_EQ(a_ , message_ ->FindEnumValueByName("A")); + EXPECT_EQ(b_ , message_ ->FindEnumValueByName("B")); + EXPECT_EQ(a2_, message2_->FindEnumValueByName("A")); + EXPECT_EQ(c2_, message2_->FindEnumValueByName("C")); + + EXPECT_TRUE(message_ ->FindEnumValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(message_ ->FindEnumValueByName("C" ) == NULL); + EXPECT_TRUE(message2_->FindEnumValueByName("B" ) == NULL); + + EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL); +} + +// =================================================================== + +// Test extensions. +class ExtensionDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // enum Baz {} + // message Qux {} + // + // message Foo { + // extensions 10 to 19; + // extensions 30 to 39; + // } + // extends Foo with optional int32 foo_int32 = 10; + // extends Foo with repeated TestEnum foo_enum = 19; + // message Bar { + // extends Foo with optional Qux foo_message = 30; + // // (using Qux as the group type) + // extends Foo with repeated group foo_group = 39; + // } + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + AddEmptyEnum(&foo_file, "Baz"); + AddMessage(&foo_file, "Qux"); + + DescriptorProto* foo = AddMessage(&foo_file, "Foo"); + AddExtensionRange(foo, 10, 20); + AddExtensionRange(foo, 30, 40); + + AddExtension(&foo_file, "Foo", "foo_int32", 10, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddExtension(&foo_file, "Foo", "foo_enum", 19, + FieldDescriptorProto::LABEL_REPEATED, + FieldDescriptorProto::TYPE_ENUM) + ->set_type_name("Baz"); + + DescriptorProto* bar = AddMessage(&foo_file, "Bar"); + AddNestedExtension(bar, "Foo", "foo_message", 30, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_MESSAGE) + ->set_type_name("Qux"); + AddNestedExtension(bar, "Foo", "foo_group", 39, + FieldDescriptorProto::LABEL_REPEATED, + FieldDescriptorProto::TYPE_GROUP) + ->set_type_name("Qux"); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + ASSERT_EQ(1, foo_file_->enum_type_count()); + baz_ = foo_file_->enum_type(0); + + ASSERT_EQ(3, foo_file_->message_type_count()); + qux_ = foo_file_->message_type(0); + foo_ = foo_file_->message_type(1); + bar_ = foo_file_->message_type(2); + } + + DescriptorPool pool_; + + const FileDescriptor* foo_file_; + + const Descriptor* foo_; + const Descriptor* bar_; + const EnumDescriptor* baz_; + const Descriptor* qux_; +}; + +TEST_F(ExtensionDescriptorTest, ExtensionRanges) { + EXPECT_EQ(0, bar_->extension_range_count()); + ASSERT_EQ(2, foo_->extension_range_count()); + + EXPECT_EQ(10, foo_->extension_range(0)->start); + EXPECT_EQ(30, foo_->extension_range(1)->start); + + EXPECT_EQ(20, foo_->extension_range(0)->end); + EXPECT_EQ(40, foo_->extension_range(1)->end); +}; + +TEST_F(ExtensionDescriptorTest, Extensions) { + EXPECT_EQ(0, foo_->extension_count()); + ASSERT_EQ(2, foo_file_->extension_count()); + ASSERT_EQ(2, bar_->extension_count()); + + EXPECT_TRUE(foo_file_->extension(0)->is_extension()); + EXPECT_TRUE(foo_file_->extension(1)->is_extension()); + EXPECT_TRUE(bar_->extension(0)->is_extension()); + EXPECT_TRUE(bar_->extension(1)->is_extension()); + + EXPECT_EQ("foo_int32" , foo_file_->extension(0)->name()); + EXPECT_EQ("foo_enum" , foo_file_->extension(1)->name()); + EXPECT_EQ("foo_message", bar_->extension(0)->name()); + EXPECT_EQ("foo_group" , bar_->extension(1)->name()); + + EXPECT_EQ(10, foo_file_->extension(0)->number()); + EXPECT_EQ(19, foo_file_->extension(1)->number()); + EXPECT_EQ(30, bar_->extension(0)->number()); + EXPECT_EQ(39, bar_->extension(1)->number()); + + EXPECT_EQ(FieldDescriptor::TYPE_INT32 , foo_file_->extension(0)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_ENUM , foo_file_->extension(1)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_->extension(0)->type()); + EXPECT_EQ(FieldDescriptor::TYPE_GROUP , bar_->extension(1)->type()); + + EXPECT_EQ(baz_, foo_file_->extension(1)->enum_type()); + EXPECT_EQ(qux_, bar_->extension(0)->message_type()); + EXPECT_EQ(qux_, bar_->extension(1)->message_type()); + + EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, foo_file_->extension(0)->label()); + EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, foo_file_->extension(1)->label()); + EXPECT_EQ(FieldDescriptor::LABEL_OPTIONAL, bar_->extension(0)->label()); + EXPECT_EQ(FieldDescriptor::LABEL_REPEATED, bar_->extension(1)->label()); + + EXPECT_EQ(foo_, foo_file_->extension(0)->containing_type()); + EXPECT_EQ(foo_, foo_file_->extension(1)->containing_type()); + EXPECT_EQ(foo_, bar_->extension(0)->containing_type()); + EXPECT_EQ(foo_, bar_->extension(1)->containing_type()); + + EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL); + EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL); + EXPECT_EQ(bar_, bar_->extension(0)->extension_scope()); + EXPECT_EQ(bar_, bar_->extension(1)->extension_scope()); +}; + +TEST_F(ExtensionDescriptorTest, IsExtensionNumber) { + EXPECT_FALSE(foo_->IsExtensionNumber( 9)); + EXPECT_TRUE (foo_->IsExtensionNumber(10)); + EXPECT_TRUE (foo_->IsExtensionNumber(19)); + EXPECT_FALSE(foo_->IsExtensionNumber(20)); + EXPECT_FALSE(foo_->IsExtensionNumber(29)); + EXPECT_TRUE (foo_->IsExtensionNumber(30)); + EXPECT_TRUE (foo_->IsExtensionNumber(39)); + EXPECT_FALSE(foo_->IsExtensionNumber(40)); +} + +TEST_F(ExtensionDescriptorTest, FindExtensionByName) { + // Note that FileDescriptor::FindExtensionByName() is tested by + // FileDescriptorTest. + ASSERT_EQ(2, bar_->extension_count()); + + EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message")); + EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group" )); + + EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL); + EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL); + EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL); +} + +TEST_F(ExtensionDescriptorTest, FindAllExtensions) { + vector extensions; + pool_.FindAllExtensions(foo_, &extensions); + ASSERT_EQ(4, extensions.size()); + EXPECT_EQ(10, extensions[0]->number()); + EXPECT_EQ(19, extensions[1]->number()); + EXPECT_EQ(30, extensions[2]->number()); + EXPECT_EQ(39, extensions[3]->number()); +} + +// =================================================================== + +class MiscTest : public testing::Test { + protected: + // Function which makes a field descriptor of the given type. + const FieldDescriptor* GetFieldDescriptorOfType(FieldDescriptor::Type type) { + FileDescriptorProto file_proto; + file_proto.set_name("foo.proto"); + AddEmptyEnum(&file_proto, "DummyEnum"); + + DescriptorProto* message = AddMessage(&file_proto, "TestMessage"); + FieldDescriptorProto* field = + AddField(message, "foo", 1, FieldDescriptorProto::LABEL_OPTIONAL, + static_cast(static_cast(type))); + + if (type == FieldDescriptor::TYPE_MESSAGE || + type == FieldDescriptor::TYPE_GROUP) { + field->set_type_name("TestMessage"); + } else if (type == FieldDescriptor::TYPE_ENUM) { + field->set_type_name("DummyEnum"); + } + + // Build the descriptors and get the pointers. + pool_.reset(new DescriptorPool()); + const FileDescriptor* file = pool_->BuildFile(file_proto); + + if (file != NULL && + file->message_type_count() == 1 && + file->message_type(0)->field_count() == 1) { + return file->message_type(0)->field(0); + } else { + return NULL; + } + } + + const char* GetTypeNameForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->type_name() : ""; + } + + FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->cpp_type() : + static_cast(0); + } + + const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->cpp_type_name() : ""; + } + + scoped_ptr pool_; +}; + +TEST_F(MiscTest, TypeNames) { + // Test that correct type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , GetTypeNameForFieldType(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , GetTypeNameForFieldType(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , GetTypeNameForFieldType(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , GetTypeNameForFieldType(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , GetTypeNameForFieldType(FD::TYPE_INT32 )); + EXPECT_STREQ("fixed64" , GetTypeNameForFieldType(FD::TYPE_FIXED64 )); + EXPECT_STREQ("fixed32" , GetTypeNameForFieldType(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , GetTypeNameForFieldType(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , GetTypeNameForFieldType(FD::TYPE_STRING )); + EXPECT_STREQ("group" , GetTypeNameForFieldType(FD::TYPE_GROUP )); + EXPECT_STREQ("message" , GetTypeNameForFieldType(FD::TYPE_MESSAGE )); + EXPECT_STREQ("bytes" , GetTypeNameForFieldType(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , GetTypeNameForFieldType(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , GetTypeNameForFieldType(FD::TYPE_ENUM )); + EXPECT_STREQ("sfixed32", GetTypeNameForFieldType(FD::TYPE_SFIXED32)); + EXPECT_STREQ("sfixed64", GetTypeNameForFieldType(FD::TYPE_SFIXED64)); + EXPECT_STREQ("sint32" , GetTypeNameForFieldType(FD::TYPE_SINT32 )); + EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, CppTypes) { + // Test that CPP types are assigned correctly. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_EQ(FD::CPPTYPE_DOUBLE , GetCppTypeForFieldType(FD::TYPE_DOUBLE )); + EXPECT_EQ(FD::CPPTYPE_FLOAT , GetCppTypeForFieldType(FD::TYPE_FLOAT )); + EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_INT64 )); + EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_UINT64 )); + EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_INT32 )); + EXPECT_EQ(FD::CPPTYPE_UINT64 , GetCppTypeForFieldType(FD::TYPE_FIXED64 )); + EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_FIXED32 )); + EXPECT_EQ(FD::CPPTYPE_BOOL , GetCppTypeForFieldType(FD::TYPE_BOOL )); + EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_STRING )); + EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_GROUP )); + EXPECT_EQ(FD::CPPTYPE_MESSAGE, GetCppTypeForFieldType(FD::TYPE_MESSAGE )); + EXPECT_EQ(FD::CPPTYPE_STRING , GetCppTypeForFieldType(FD::TYPE_BYTES )); + EXPECT_EQ(FD::CPPTYPE_UINT32 , GetCppTypeForFieldType(FD::TYPE_UINT32 )); + EXPECT_EQ(FD::CPPTYPE_ENUM , GetCppTypeForFieldType(FD::TYPE_ENUM )); + EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SFIXED32)); + EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SFIXED64)); + EXPECT_EQ(FD::CPPTYPE_INT32 , GetCppTypeForFieldType(FD::TYPE_SINT32 )); + EXPECT_EQ(FD::CPPTYPE_INT64 , GetCppTypeForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, CppTypeNames) { + // Test that correct CPP type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , GetCppTypeNameForFieldType(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , GetCppTypeNameForFieldType(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_INT32 )); + EXPECT_STREQ("uint64" , GetCppTypeNameForFieldType(FD::TYPE_FIXED64 )); + EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , GetCppTypeNameForFieldType(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_STRING )); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_GROUP )); + EXPECT_STREQ("message", GetCppTypeNameForFieldType(FD::TYPE_MESSAGE )); + EXPECT_STREQ("string" , GetCppTypeNameForFieldType(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , GetCppTypeNameForFieldType(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , GetCppTypeNameForFieldType(FD::TYPE_ENUM )); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED32)); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SFIXED64)); + EXPECT_STREQ("int32" , GetCppTypeNameForFieldType(FD::TYPE_SINT32 )); + EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, DefaultValues) { + // Test that setting default values works. + FileDescriptorProto file_proto; + file_proto.set_name("foo.proto"); + + EnumDescriptorProto* enum_type_proto = AddEnum(&file_proto, "DummyEnum"); + AddEnumValue(enum_type_proto, "A", 1); + AddEnumValue(enum_type_proto, "B", 2); + + DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); + + typedef FieldDescriptorProto FD; // avoid ugly line wrapping + const FD::Label label = FD::LABEL_OPTIONAL; + + // Create fields of every CPP type with default values. + AddField(message_proto, "int32" , 1, label, FD::TYPE_INT32 ) + ->set_default_value("-1"); + AddField(message_proto, "int64" , 2, label, FD::TYPE_INT64 ) + ->set_default_value("-1000000000000"); + AddField(message_proto, "uint32", 3, label, FD::TYPE_UINT32) + ->set_default_value("42"); + AddField(message_proto, "uint64", 4, label, FD::TYPE_UINT64) + ->set_default_value("2000000000000"); + AddField(message_proto, "float" , 5, label, FD::TYPE_FLOAT ) + ->set_default_value("4.5"); + AddField(message_proto, "double", 6, label, FD::TYPE_DOUBLE) + ->set_default_value("10e100"); + AddField(message_proto, "bool" , 7, label, FD::TYPE_BOOL ) + ->set_default_value("true"); + AddField(message_proto, "string", 8, label, FD::TYPE_STRING) + ->set_default_value("hello"); + AddField(message_proto, "data" , 9, label, FD::TYPE_BYTES ) + ->set_default_value("\\001\\002\\003"); + + FieldDescriptorProto* enum_field = + AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM); + enum_field->set_type_name("DummyEnum"); + enum_field->set_default_value("B"); + + // Strings are allowed to have empty defaults. (At one point, due to + // a bug, empty defaults for strings were rejected. Oops.) + AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING) + ->set_default_value(""); + + // Add a second set of fields with implicit defalut values. + AddField(message_proto, "implicit_int32" , 21, label, FD::TYPE_INT32 ); + AddField(message_proto, "implicit_int64" , 22, label, FD::TYPE_INT64 ); + AddField(message_proto, "implicit_uint32", 23, label, FD::TYPE_UINT32); + AddField(message_proto, "implicit_uint64", 24, label, FD::TYPE_UINT64); + AddField(message_proto, "implicit_float" , 25, label, FD::TYPE_FLOAT ); + AddField(message_proto, "implicit_double", 26, label, FD::TYPE_DOUBLE); + AddField(message_proto, "implicit_bool" , 27, label, FD::TYPE_BOOL ); + AddField(message_proto, "implicit_string", 28, label, FD::TYPE_STRING); + AddField(message_proto, "implicit_data" , 29, label, FD::TYPE_BYTES ); + AddField(message_proto, "implicit_enum" , 30, label, FD::TYPE_ENUM) + ->set_type_name("DummyEnum"); + + // Build it. + DescriptorPool pool; + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + + ASSERT_EQ(1, file->enum_type_count()); + const EnumDescriptor* enum_type = file->enum_type(0); + ASSERT_EQ(2, enum_type->value_count()); + const EnumValueDescriptor* enum_value_a = enum_type->value(0); + const EnumValueDescriptor* enum_value_b = enum_type->value(1); + + ASSERT_EQ(1, file->message_type_count()); + const Descriptor* message = file->message_type(0); + + ASSERT_EQ(21, message->field_count()); + + // Check the default values. + ASSERT_TRUE(message->field(0)->has_default_value()); + ASSERT_TRUE(message->field(1)->has_default_value()); + ASSERT_TRUE(message->field(2)->has_default_value()); + ASSERT_TRUE(message->field(3)->has_default_value()); + ASSERT_TRUE(message->field(4)->has_default_value()); + ASSERT_TRUE(message->field(5)->has_default_value()); + ASSERT_TRUE(message->field(6)->has_default_value()); + ASSERT_TRUE(message->field(7)->has_default_value()); + ASSERT_TRUE(message->field(8)->has_default_value()); + ASSERT_TRUE(message->field(9)->has_default_value()); + ASSERT_TRUE(message->field(10)->has_default_value()); + + EXPECT_EQ(-1 , message->field(0)->default_value_int32 ()); + EXPECT_EQ(-GOOGLE_ULONGLONG(1000000000000), + message->field(1)->default_value_int64 ()); + EXPECT_EQ(42 , message->field(2)->default_value_uint32()); + EXPECT_EQ(GOOGLE_ULONGLONG(2000000000000), + message->field(3)->default_value_uint64()); + EXPECT_EQ(4.5 , message->field(4)->default_value_float ()); + EXPECT_EQ(10e100 , message->field(5)->default_value_double()); + EXPECT_TRUE( message->field(6)->default_value_bool ()); + EXPECT_EQ("hello" , message->field(7)->default_value_string()); + EXPECT_EQ("\001\002\003" , message->field(8)->default_value_string()); + EXPECT_EQ(enum_value_b , message->field(9)->default_value_enum ()); + EXPECT_EQ("" , message->field(10)->default_value_string()); + + ASSERT_FALSE(message->field(11)->has_default_value()); + ASSERT_FALSE(message->field(12)->has_default_value()); + ASSERT_FALSE(message->field(13)->has_default_value()); + ASSERT_FALSE(message->field(14)->has_default_value()); + ASSERT_FALSE(message->field(15)->has_default_value()); + ASSERT_FALSE(message->field(16)->has_default_value()); + ASSERT_FALSE(message->field(17)->has_default_value()); + ASSERT_FALSE(message->field(18)->has_default_value()); + ASSERT_FALSE(message->field(19)->has_default_value()); + ASSERT_FALSE(message->field(20)->has_default_value()); + + EXPECT_EQ(0 , message->field(11)->default_value_int32 ()); + EXPECT_EQ(0 , message->field(12)->default_value_int64 ()); + EXPECT_EQ(0 , message->field(13)->default_value_uint32()); + EXPECT_EQ(0 , message->field(14)->default_value_uint64()); + EXPECT_EQ(0.0f , message->field(15)->default_value_float ()); + EXPECT_EQ(0.0 , message->field(16)->default_value_double()); + EXPECT_FALSE( message->field(17)->default_value_bool ()); + EXPECT_EQ("" , message->field(18)->default_value_string()); + EXPECT_EQ("" , message->field(19)->default_value_string()); + EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum()); +} + +TEST_F(MiscTest, FieldOptions) { + // Try setting field options. + + FileDescriptorProto file_proto; + file_proto.set_name("foo.proto"); + + DescriptorProto* message_proto = AddMessage(&file_proto, "TestMessage"); + AddField(message_proto, "foo", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + FieldDescriptorProto* bar_proto = + AddField(message_proto, "bar", 2, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + + FieldOptions* options = bar_proto->mutable_options(); + options->set_ctype(FieldOptions::CORD); + + // Build the descriptors and get the pointers. + DescriptorPool pool; + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + + ASSERT_EQ(1, file->message_type_count()); + const Descriptor* message = file->message_type(0); + + ASSERT_EQ(2, message->field_count()); + const FieldDescriptor* foo = message->field(0); + const FieldDescriptor* bar = message->field(1); + + // "foo" had no options set, so it should return the default options. + EXPECT_EQ(&FieldOptions::default_instance(), &foo->options()); + + // "bar" had options set. + EXPECT_NE(&FieldOptions::default_instance(), options); + EXPECT_TRUE(bar->options().has_ctype()); + EXPECT_EQ(FieldOptions::CORD, bar->options().ctype()); +} + +// =================================================================== +enum DescriptorPoolMode { + NO_DATABASE, + FALLBACK_DATABASE +}; + +class AllowUnknownDependenciesTest + : public testing::TestWithParam { + protected: + DescriptorPoolMode mode() { + return GetParam(); + } + + virtual void SetUp() { + FileDescriptorProto foo_proto, bar_proto; + + switch (mode()) { + case NO_DATABASE: + pool_.reset(new DescriptorPool); + break; + case FALLBACK_DATABASE: + pool_.reset(new DescriptorPool(&db_)); + break; + } + + pool_->AllowUnknownDependencies(); + + ASSERT_TRUE(TextFormat::ParseFromString( + "name: 'foo.proto'" + "dependency: 'bar.proto'" + "dependency: 'baz.proto'" + "message_type {" + " name: 'Foo'" + " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'Bar' }" + " field { name:'baz' number:2 label:LABEL_OPTIONAL type_name:'Baz' }" + " field { name:'qux' number:3 label:LABEL_OPTIONAL" + " type_name: '.corge.Qux'" + " type: TYPE_ENUM" + " options {" + " uninterpreted_option {" + " name {" + " name_part: 'grault'" + " is_extension: true" + " }" + " positive_int_value: 1234" + " }" + " }" + " }" + "}", + &foo_proto)); + ASSERT_TRUE(TextFormat::ParseFromString( + "name: 'bar.proto'" + "message_type { name: 'Bar' }", + &bar_proto)); + + // Collect pointers to stuff. + bar_file_ = BuildFile(bar_proto); + ASSERT_TRUE(bar_file_ != NULL); + + ASSERT_EQ(1, bar_file_->message_type_count()); + bar_type_ = bar_file_->message_type(0); + + foo_file_ = BuildFile(foo_proto); + ASSERT_TRUE(foo_file_ != NULL); + + ASSERT_EQ(1, foo_file_->message_type_count()); + foo_type_ = foo_file_->message_type(0); + + ASSERT_EQ(3, foo_type_->field_count()); + bar_field_ = foo_type_->field(0); + baz_field_ = foo_type_->field(1); + qux_field_ = foo_type_->field(2); + } + + const FileDescriptor* BuildFile(const FileDescriptorProto& proto) { + switch (mode()) { + case NO_DATABASE: + return pool_->BuildFile(proto); + break; + case FALLBACK_DATABASE: { + EXPECT_TRUE(db_.Add(proto)); + return pool_->FindFileByName(proto.name()); + } + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; + } + + const FileDescriptor* bar_file_; + const Descriptor* bar_type_; + const FileDescriptor* foo_file_; + const Descriptor* foo_type_; + const FieldDescriptor* bar_field_; + const FieldDescriptor* baz_field_; + const FieldDescriptor* qux_field_; + + SimpleDescriptorDatabase db_; // used if in FALLBACK_DATABASE mode. + scoped_ptr pool_; +}; + +TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { + ASSERT_EQ(2, foo_file_->dependency_count()); + EXPECT_EQ(bar_file_, foo_file_->dependency(0)); + + const FileDescriptor* baz_file = foo_file_->dependency(1); + EXPECT_EQ("baz.proto", baz_file->name()); + EXPECT_EQ(0, baz_file->message_type_count()); + + // Placeholder files should not be findable. + EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); + EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL); +} + +TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { + ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type()); + EXPECT_EQ(bar_type_, bar_field_->message_type()); + + ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type()); + const Descriptor* baz_type = baz_field_->message_type(); + EXPECT_EQ("Baz", baz_type->name()); + EXPECT_EQ("Baz", baz_type->full_name()); + EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name()); + EXPECT_EQ(0, baz_type->extension_range_count()); + + ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type()); + const EnumDescriptor* qux_type = qux_field_->enum_type(); + EXPECT_EQ("Qux", qux_type->name()); + EXPECT_EQ("corge.Qux", qux_type->full_name()); + EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name()); + + // Placeholder types should not be findable. + EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); + EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL); + EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL); +} + +TEST_P(AllowUnknownDependenciesTest, CopyTo) { + // FieldDescriptor::CopyTo() should write non-fully-qualified type names + // for placeholder types which were not originally fully-qualified. + FieldDescriptorProto proto; + + // Bar is not a placeholder, so it is fully-qualified. + bar_field_->CopyTo(&proto); + EXPECT_EQ(".Bar", proto.type_name()); + EXPECT_EQ(FieldDescriptorProto::TYPE_MESSAGE, proto.type()); + + // Baz is an unqualified placeholder. + proto.Clear(); + baz_field_->CopyTo(&proto); + EXPECT_EQ("Baz", proto.type_name()); + EXPECT_FALSE(proto.has_type()); + + // Qux is a fully-qualified placeholder. + proto.Clear(); + qux_field_->CopyTo(&proto); + EXPECT_EQ(".corge.Qux", proto.type_name()); + EXPECT_EQ(FieldDescriptorProto::TYPE_ENUM, proto.type()); +} + +TEST_P(AllowUnknownDependenciesTest, CustomOptions) { + // Qux should still have the uninterpreted option attached. + ASSERT_EQ(1, qux_field_->options().uninterpreted_option_size()); + const UninterpretedOption& option = + qux_field_->options().uninterpreted_option(0); + ASSERT_EQ(1, option.name_size()); + EXPECT_EQ("grault", option.name(0).name_part()); +} + +TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) { + // Test that we can extend an unknown type. This is slightly tricky because + // it means that the placeholder type must have an extension range. + + FileDescriptorProto extension_proto; + + ASSERT_TRUE(TextFormat::ParseFromString( + "name: 'extension.proto'" + "extension { extendee: 'UnknownType' name:'some_extension' number:123" + " label:LABEL_OPTIONAL type:TYPE_INT32 }", + &extension_proto)); + const FileDescriptor* file = BuildFile(extension_proto); + + ASSERT_TRUE(file != NULL); + + ASSERT_EQ(1, file->extension_count()); + const Descriptor* extendee = file->extension(0)->containing_type(); + EXPECT_EQ("UnknownType", extendee->name()); + ASSERT_EQ(1, extendee->extension_range_count()); + EXPECT_EQ(1, extendee->extension_range(0)->start); + EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end); +} + +TEST_P(AllowUnknownDependenciesTest, CustomOption) { + // Test that we can use a custom option without having parsed + // descriptor.proto. + + FileDescriptorProto option_proto; + + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"unknown_custom_options.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { " + " extendee: \"google.protobuf.FileOptions\" " + " name: \"some_option\" " + " number: 123456 " + " label: LABEL_OPTIONAL " + " type: TYPE_INT32 " + "} " + "options { " + " uninterpreted_option { " + " name { " + " name_part: \"some_option\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"unknown_option\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"optimize_for\" " + " is_extension: false " + " } " + " identifier_value: \"SPEED\" " + " } " + "}", + &option_proto)); + + const FileDescriptor* file = BuildFile(option_proto); + ASSERT_TRUE(file != NULL); + + // Verify that no extension options were set, but they were left as + // uninterpreted_options. + vector fields; + file->options().GetReflection()->ListFields(file->options(), &fields); + ASSERT_EQ(2, fields.size()); + EXPECT_TRUE(file->options().has_optimize_for()); + EXPECT_EQ(2, file->options().uninterpreted_option_size()); +} + +TEST_P(AllowUnknownDependenciesTest, + UndeclaredDependencyTriggersBuildOfDependency) { + // Crazy case: suppose foo.proto refers to a symbol without declaring the + // dependency that finds it. In the event that the pool is backed by a + // DescriptorDatabase, the pool will attempt to find the symbol in the + // database. If successful, it will build the undeclared dependency to verify + // that the file does indeed contain the symbol. If that file fails to build, + // then its descriptors must be rolled back. However, we still want foo.proto + // to build successfully, since we are allowing unknown dependencies. + + FileDescriptorProto undeclared_dep_proto; + // We make this file fail to build by giving it two fields with tag 1. + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"invalid_file_as_undeclared_dep.proto\" " + "package: \"undeclared\" " + "message_type: { " + " name: \"Quux\" " + " field { " + " name:'qux' number:1 label:LABEL_OPTIONAL type: TYPE_INT32 " + " }" + " field { " + " name:'quux' number:1 label:LABEL_OPTIONAL type: TYPE_INT64 " + " }" + "}", + &undeclared_dep_proto)); + // We can't use the BuildFile() helper because we don't actually want to build + // it into the descriptor pool in the fallback database case: it just needs to + // be sitting in the database so that it gets built during the building of + // test.proto below. + switch (mode()) { + case NO_DATABASE: { + ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL); + break; + } + case FALLBACK_DATABASE: { + ASSERT_TRUE(db_.Add(undeclared_dep_proto)); + } + } + + FileDescriptorProto test_proto; + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"test.proto\" " + "message_type: { " + " name: \"Corge\" " + " field { " + " name:'quux' number:1 label: LABEL_OPTIONAL " + " type_name:'undeclared.Quux' type: TYPE_MESSAGE " + " }" + "}", + &test_proto)); + + const FileDescriptor* file = BuildFile(test_proto); + ASSERT_TRUE(file != NULL); + GOOGLE_LOG(INFO) << file->DebugString(); + + EXPECT_EQ(0, file->dependency_count()); + ASSERT_EQ(1, file->message_type_count()); + const Descriptor* corge_desc = file->message_type(0); + ASSERT_EQ("Corge", corge_desc->name()); + ASSERT_EQ(1, corge_desc->field_count()); + + const FieldDescriptor* quux_field = corge_desc->field(0); + ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type()); + ASSERT_EQ("Quux", quux_field->message_type()->name()); + ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); + EXPECT_EQ("undeclared.Quux.placeholder.proto", + quux_field->message_type()->file()->name()); + // The place holder type should not be findable. + ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); +} + +INSTANTIATE_TEST_CASE_P(DatabaseSource, + AllowUnknownDependenciesTest, + testing::Values(NO_DATABASE, FALLBACK_DATABASE)); + +// =================================================================== + +TEST(CustomOptions, OptionLocations) { + const Descriptor* message = + protobuf_unittest::TestMessageWithCustomOptions::descriptor(); + const FileDescriptor* file = message->file(); + const FieldDescriptor* field = message->FindFieldByName("field1"); + const EnumDescriptor* enm = message->FindEnumTypeByName("AnEnum"); + // TODO(benjy): Support EnumValue options, once the compiler does. + const ServiceDescriptor* service = + file->FindServiceByName("TestServiceWithCustomOptions"); + const MethodDescriptor* method = service->FindMethodByName("Foo"); + + EXPECT_EQ(GOOGLE_LONGLONG(9876543210), + file->options().GetExtension(protobuf_unittest::file_opt1)); + EXPECT_EQ(-56, + message->options().GetExtension(protobuf_unittest::message_opt1)); + EXPECT_EQ(GOOGLE_LONGLONG(8765432109), + field->options().GetExtension(protobuf_unittest::field_opt1)); + EXPECT_EQ(42, // Check that we get the default for an option we don't set. + field->options().GetExtension(protobuf_unittest::field_opt2)); + EXPECT_EQ(-789, + enm->options().GetExtension(protobuf_unittest::enum_opt1)); + EXPECT_EQ(123, + enm->value(1)->options().GetExtension( + protobuf_unittest::enum_value_opt1)); + EXPECT_EQ(GOOGLE_LONGLONG(-9876543210), + service->options().GetExtension(protobuf_unittest::service_opt1)); + EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2, + method->options().GetExtension(protobuf_unittest::method_opt1)); + + // See that the regular options went through unscathed. + EXPECT_TRUE(message->options().has_message_set_wire_format()); + EXPECT_EQ(FieldOptions::CORD, field->options().ctype()); +} + +TEST(CustomOptions, OptionTypes) { + const MessageOptions* options = NULL; + + options = + &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options(); + EXPECT_FALSE( options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt)); + EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt)); + EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt)); + EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint64_opt)); + EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sint32_opt)); + EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sint64_opt)); + EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed32_opt)); + EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::fixed64_opt)); + EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::sfixed32_opt)); + EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::sfixed64_opt)); + + options = + &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options(); + EXPECT_TRUE( options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt)); + EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt)); + EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt)); + EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::uint64_opt)); + EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sint32_opt)); + EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sint64_opt)); + EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::fixed32_opt)); + EXPECT_EQ(kuint64max, options->GetExtension(protobuf_unittest::fixed64_opt)); + EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::sfixed32_opt)); + EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::sfixed64_opt)); + + options = + &protobuf_unittest::CustomOptionOtherValues::descriptor()->options(); + EXPECT_EQ(-100, options->GetExtension(protobuf_unittest::int32_opt)); + EXPECT_FLOAT_EQ(12.3456789, + options->GetExtension(protobuf_unittest::float_opt)); + EXPECT_DOUBLE_EQ(1.234567890123456789, + options->GetExtension(protobuf_unittest::double_opt)); + EXPECT_EQ("Hello, \"World\"", + options->GetExtension(protobuf_unittest::string_opt)); + + EXPECT_EQ(string("Hello\0World", 11), + options->GetExtension(protobuf_unittest::bytes_opt)); + + EXPECT_EQ(protobuf_unittest::DummyMessageContainingEnum::TEST_OPTION_ENUM_TYPE2, + options->GetExtension(protobuf_unittest::enum_opt)); + + options = + &protobuf_unittest::SettingRealsFromPositiveInts::descriptor()->options(); + EXPECT_FLOAT_EQ(12, options->GetExtension(protobuf_unittest::float_opt)); + EXPECT_DOUBLE_EQ(154, options->GetExtension(protobuf_unittest::double_opt)); + + options = + &protobuf_unittest::SettingRealsFromNegativeInts::descriptor()->options(); + EXPECT_FLOAT_EQ(-12, options->GetExtension(protobuf_unittest::float_opt)); + EXPECT_DOUBLE_EQ(-154, options->GetExtension(protobuf_unittest::double_opt)); +} + +TEST(CustomOptions, ComplexExtensionOptions) { + const MessageOptions* options = + &protobuf_unittest::VariousComplexOptions::descriptor()->options(); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1).foo(), 42); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1). + GetExtension(protobuf_unittest::quux), 324); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt1). + GetExtension(protobuf_unittest::corge).qux(), 876); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).baz(), 987); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). + GetExtension(protobuf_unittest::grault), 654); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar().foo(), + 743); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar(). + GetExtension(protobuf_unittest::quux), 1999); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2).bar(). + GetExtension(protobuf_unittest::corge).qux(), 2008); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). + GetExtension(protobuf_unittest::garply).foo(), 741); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). + GetExtension(protobuf_unittest::garply). + GetExtension(protobuf_unittest::quux), 1998); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). + GetExtension(protobuf_unittest::garply). + GetExtension(protobuf_unittest::corge).qux(), 2121); + EXPECT_EQ(options->GetExtension( + protobuf_unittest::ComplexOptionType2::ComplexOptionType4::complex_opt4). + waldo(), 1971); + EXPECT_EQ(options->GetExtension(protobuf_unittest::complex_opt2). + fred().waldo(), 321); + EXPECT_EQ(9, options->GetExtension(protobuf_unittest::complex_opt3).qux()); + EXPECT_EQ(22, options->GetExtension(protobuf_unittest::complex_opt3). + complexoptiontype5().plugh()); + EXPECT_EQ(24, options->GetExtension(protobuf_unittest::complexopt6).xyzzy()); +} + +TEST(CustomOptions, OptionsFromOtherFile) { + // Test that to use a custom option, we only need to import the file + // defining the option; we do not also have to import descriptor.proto. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "options { " + " uninterpreted_option { " + " name { " + " name_part: \"file_opt1\" " + " is_extension: true " + " } " + " positive_int_value: 1234 " + " } " + // Test a non-extension option too. (At one point this failed due to a + // bug.) + " uninterpreted_option { " + " name { " + " name_part: \"java_package\" " + " is_extension: false " + " } " + " string_value: \"foo\" " + " } " + // Test that enum-typed options still work too. (At one point this also + // failed due to a bug.) + " uninterpreted_option { " + " name { " + " name_part: \"optimize_for\" " + " is_extension: false " + " } " + " identifier_value: \"SPEED\" " + " } " + "}" + , + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1)); + EXPECT_TRUE(file->options().has_java_package()); + EXPECT_EQ("foo", file->options().java_package()); + EXPECT_TRUE(file->options().has_optimize_for()); + EXPECT_EQ(FileOptions::SPEED, file->options().optimize_for()); +} + +TEST(CustomOptions, MessageOptionThreeFieldsSet) { + // This tests a bug which previously existed in custom options parsing. The + // bug occurred when you defined a custom option with message type and then + // set three fields of that option on a single definition (see the example + // below). The bug is a bit hard to explain, so check the change history if + // you want to know more. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt1).foo = 1234; + // option (complex_opt1).foo2 = 1234; + // option (complex_opt1).foo3 = 1234; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo2\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo3\" " + " is_extension: false " + " } " + " positive_int_value: 1234 " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); +} + +// Check that aggregate options were parsed and saved correctly in +// the appropriate descriptors. +TEST(CustomOptions, AggregateOptions) { + const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor(); + const FileDescriptor* file = msg->file(); + const FieldDescriptor* field = msg->FindFieldByName("fieldname"); + const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); + const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); + const ServiceDescriptor* service = file->FindServiceByName( + "AggregateService"); + const MethodDescriptor* method = service->FindMethodByName("Method"); + + // Tests for the different types of data embedded in fileopt + const protobuf_unittest::Aggregate& file_options = + file->options().GetExtension(protobuf_unittest::fileopt); + EXPECT_EQ(100, file_options.i()); + EXPECT_EQ("FileAnnotation", file_options.s()); + EXPECT_EQ("NestedFileAnnotation", file_options.sub().s()); + EXPECT_EQ("FileExtensionAnnotation", + file_options.file().GetExtension(protobuf_unittest::fileopt).s()); + EXPECT_EQ("EmbeddedMessageSetElement", + file_options.mset().GetExtension( + protobuf_unittest::AggregateMessageSetElement + ::message_set_extension).s()); + + // Simple tests for all the other types of annotations + EXPECT_EQ("MessageAnnotation", + msg->options().GetExtension(protobuf_unittest::msgopt).s()); + EXPECT_EQ("FieldAnnotation", + field->options().GetExtension(protobuf_unittest::fieldopt).s()); + EXPECT_EQ("EnumAnnotation", + enumd->options().GetExtension(protobuf_unittest::enumopt).s()); + EXPECT_EQ("EnumValueAnnotation", + enumv->options().GetExtension(protobuf_unittest::enumvalopt).s()); + EXPECT_EQ("ServiceAnnotation", + service->options().GetExtension(protobuf_unittest::serviceopt).s()); + EXPECT_EQ("MethodAnnotation", + method->options().GetExtension(protobuf_unittest::methodopt).s()); +} + +// =================================================================== + +// The tests below trigger every unique call to AddError() in descriptor.cc, +// in the order in which they appear in that file. I'm using TextFormat here +// to specify the input descriptors because building them using code would +// be too bulky. + +class MockErrorCollector : public DescriptorPool::ErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(const string& filename, + const string& element_name, const Message* descriptor, + ErrorLocation location, const string& message) { + const char* location_name = NULL; + switch (location) { + case NAME : location_name = "NAME" ; break; + case NUMBER : location_name = "NUMBER" ; break; + case TYPE : location_name = "TYPE" ; break; + case EXTENDEE : location_name = "EXTENDEE" ; break; + case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; + case OPTION_NAME : location_name = "OPTION_NAME" ; break; + case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; + case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; + case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; + case OTHER : location_name = "OTHER" ; break; + } + + strings::SubstituteAndAppend( + &text_, "$0: $1: $2: $3\n", + filename, element_name, location_name, message); + } +}; + +class ValidationErrorTest : public testing::Test { + protected: + // Parse file_text as a FileDescriptorProto in text format and add it + // to the DescriptorPool. Expect no errors. + void BuildFile(const string& file_text) { + FileDescriptorProto file_proto; + ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); + } + + // Parse file_text as a FileDescriptorProto in text format and add it + // to the DescriptorPool. Expect errors to be produced which match the + // given error text. + void BuildFileWithErrors(const string& file_text, + const string& expected_errors) { + FileDescriptorProto file_proto; + ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + + MockErrorCollector error_collector; + EXPECT_TRUE( + pool_.BuildFileCollectingErrors(file_proto, &error_collector) == NULL); + EXPECT_EQ(expected_errors, error_collector.text_); + } + + // Builds some already-parsed file in our test pool. + void BuildFileInTestPool(const FileDescriptor* file) { + FileDescriptorProto file_proto; + file->CopyTo(&file_proto); + ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); + } + + // Build descriptor.proto in our test pool. This allows us to extend it in + // the test pool, so we can test custom options. + void BuildDescriptorMessagesInTestPool() { + BuildFileInTestPool(DescriptorProto::descriptor()->file()); + } + + DescriptorPool pool_; +}; + +TEST_F(ValidationErrorTest, AlreadyDefined) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }" + "message_type { name: \"Foo\" }", + + "foo.proto: Foo: NAME: \"Foo\" is already defined.\n"); +} + +TEST_F(ValidationErrorTest, AlreadyDefinedInPackage) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "package: \"foo.bar\" " + "message_type { name: \"Foo\" }" + "message_type { name: \"Foo\" }", + + "foo.proto: foo.bar.Foo: NAME: \"Foo\" is already defined in " + "\"foo.bar\".\n"); +} + +TEST_F(ValidationErrorTest, AlreadyDefinedInOtherFile) { + BuildFile( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }"); + + BuildFileWithErrors( + "name: \"bar.proto\" " + "message_type { name: \"Foo\" }", + + "bar.proto: Foo: NAME: \"Foo\" is already defined in file " + "\"foo.proto\".\n"); +} + +TEST_F(ValidationErrorTest, PackageAlreadyDefined) { + BuildFile( + "name: \"foo.proto\" " + "message_type { name: \"foo\" }"); + BuildFileWithErrors( + "name: \"bar.proto\" " + "package: \"foo.bar\"", + + "bar.proto: foo: NAME: \"foo\" is already defined (as something other " + "than a package) in file \"foo.proto\".\n"); +} + +TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParent) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " + "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", + + "foo.proto: FOO: NAME: \"FOO\" is already defined.\n" + "foo.proto: FOO: NAME: Note that enum values use C++ scoping rules, " + "meaning that enum values are siblings of their type, not children of " + "it. Therefore, \"FOO\" must be unique within the global scope, not " + "just within \"Bar\".\n"); +} + +TEST_F(ValidationErrorTest, EnumValueAlreadyDefinedInParentNonGlobal) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "package: \"pkg\" " + "enum_type { name: \"Foo\" value { name: \"FOO\" number: 1 } } " + "enum_type { name: \"Bar\" value { name: \"FOO\" number: 1 } } ", + + "foo.proto: pkg.FOO: NAME: \"FOO\" is already defined in \"pkg\".\n" + "foo.proto: pkg.FOO: NAME: Note that enum values use C++ scoping rules, " + "meaning that enum values are siblings of their type, not children of " + "it. Therefore, \"FOO\" must be unique within \"pkg\", not just within " + "\"Bar\".\n"); +} + +TEST_F(ValidationErrorTest, MissingName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { }", + + "foo.proto: : NAME: Missing name.\n"); +} + +TEST_F(ValidationErrorTest, InvalidName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"$\" }", + + "foo.proto: $: NAME: \"$\" is not a valid identifier.\n"); +} + +TEST_F(ValidationErrorTest, InvalidPackageName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "package: \"foo.$\"", + + "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n"); +} + +TEST_F(ValidationErrorTest, MissingFileName) { + BuildFileWithErrors( + "", + + ": : OTHER: Missing field: FileDescriptorProto.name.\n"); +} + +TEST_F(ValidationErrorTest, DupeDependency) { + BuildFile("name: \"foo.proto\""); + BuildFileWithErrors( + "name: \"bar.proto\" " + "dependency: \"foo.proto\" " + "dependency: \"foo.proto\" ", + + "bar.proto: bar.proto: OTHER: Import \"foo.proto\" was listed twice.\n"); +} + +TEST_F(ValidationErrorTest, UnknownDependency) { + BuildFileWithErrors( + "name: \"bar.proto\" " + "dependency: \"foo.proto\" ", + + "bar.proto: bar.proto: OTHER: Import \"foo.proto\" has not been loaded.\n"); +} + +TEST_F(ValidationErrorTest, InvalidPublicDependencyIndex) { + BuildFile("name: \"foo.proto\""); + BuildFileWithErrors( + "name: \"bar.proto\" " + "dependency: \"foo.proto\" " + "public_dependency: 1", + "bar.proto: bar.proto: OTHER: Invalid public dependency index.\n"); +} + +TEST_F(ValidationErrorTest, ForeignUnimportedPackageNoCrash) { + // Used to crash: If we depend on a non-existent file and then refer to a + // package defined in a file that we didn't import, and that package is + // nested within a parent package which this file is also in, and we don't + // include that parent package in the name (i.e. we do a relative lookup)... + // Yes, really. + BuildFile( + "name: 'foo.proto' " + "package: 'outer.foo' "); + BuildFileWithErrors( + "name: 'bar.proto' " + "dependency: 'baz.proto' " + "package: 'outer.bar' " + "message_type { " + " name: 'Bar' " + " field { name:'bar' number:1 label:LABEL_OPTIONAL type_name:'foo.Foo' }" + "}", + + "bar.proto: bar.proto: OTHER: Import \"baz.proto\" has not been loaded.\n" + "bar.proto: outer.bar.Bar.bar: TYPE: \"outer.foo\" seems to be defined in " + "\"foo.proto\", which is not imported by \"bar.proto\". To use it here, " + "please add the necessary import.\n"); +} + +TEST_F(ValidationErrorTest, DupeFile) { + BuildFile( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" }"); + // Note: We should *not* get redundant errors about "Foo" already being + // defined. + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + // Add another type so that the files aren't identical (in which case there + // would be no error). + "enum_type { name: \"Bar\" }", + + "foo.proto: foo.proto: OTHER: A file with this name is already in the " + "pool.\n"); +} + +TEST_F(ValidationErrorTest, FieldInExtensionRange) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"bar\" number: 10 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"baz\" number: 19 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"qux\" number: 20 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " extension_range { start: 10 end: 20 }" + "}", + + "foo.proto: Foo.bar: NUMBER: Extension range 10 to 19 includes field " + "\"bar\" (10).\n" + "foo.proto: Foo.baz: NUMBER: Extension range 10 to 19 includes field " + "\"baz\" (19).\n"); +} + +TEST_F(ValidationErrorTest, OverlappingExtensionRanges) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " extension_range { start: 20 end: 30 }" + " extension_range { start: 19 end: 21 }" + "}", + + "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " + "already-defined range 10 to 19.\n" + "foo.proto: Foo: NUMBER: Extension range 19 to 20 overlaps with " + "already-defined range 20 to 29.\n"); +} + +TEST_F(ValidationErrorTest, InvalidDefaults) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + + // Invalid number. + " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32" + " default_value: \"abc\" }" + + // Empty default value. + " field { name: \"bar\" number: 2 label: LABEL_OPTIONAL type: TYPE_INT32" + " default_value: \"\" }" + + // Invalid boolean. + " field { name: \"baz\" number: 3 label: LABEL_OPTIONAL type: TYPE_BOOL" + " default_value: \"abc\" }" + + // Messages can't have defaults. + " field { name: \"qux\" number: 4 label: LABEL_OPTIONAL type: TYPE_MESSAGE" + " default_value: \"abc\" type_name: \"Foo\" }" + + // Same thing, but we don't know that this field has message type until + // we look up the type name. + " field { name: \"quux\" number: 5 label: LABEL_OPTIONAL" + " default_value: \"abc\" type_name: \"Foo\" }" + + // Repeateds can't have defaults. + " field { name: \"corge\" number: 6 label: LABEL_REPEATED type: TYPE_INT32" + " default_value: \"1\" }" + "}", + + "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n" + "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n" + "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " + "false.\n" + "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" + "foo.proto: Foo.corge: DEFAULT_VALUE: Repeated fields can't have default " + "values.\n" + // This ends up being reported later because the error is detected at + // cross-linking time. + "foo.proto: Foo.quux: DEFAULT_VALUE: Messages can't have default " + "values.\n"); +} + +TEST_F(ValidationErrorTest, NegativeFieldNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: -1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.foo: NUMBER: Field numbers must be positive integers.\n"); +} + +TEST_F(ValidationErrorTest, HugeFieldNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 0x70000000 " + " label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.foo: NUMBER: Field numbers cannot be greater than " + "536870911.\n"); +} + +TEST_F(ValidationErrorTest, ReservedFieldNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field {name:\"foo\" number: 18999 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field {name:\"bar\" number: 19000 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field {name:\"baz\" number: 19999 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field {name:\"qux\" number: 20000 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.bar: NUMBER: Field numbers 19000 through 19999 are " + "reserved for the protocol buffer library implementation.\n" + "foo.proto: Foo.baz: NUMBER: Field numbers 19000 through 19999 are " + "reserved for the protocol buffer library implementation.\n"); +} + +TEST_F(ValidationErrorTest, ExtensionMissingExtendee) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension { name: \"foo\" number: 1 label: LABEL_OPTIONAL" + " type_name: \"Foo\" }" + "}", + + "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee not set for " + "extension field.\n"); +} + +TEST_F(ValidationErrorTest, NonExtensionWithExtendee) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " extension_range { start: 1 end: 2 }" + "}" + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 1 label: LABEL_OPTIONAL" + " type_name: \"Foo\" extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: EXTENDEE: FieldDescriptorProto.extendee set for " + "non-extension field.\n"); +} + +TEST_F(ValidationErrorTest, FieldNumberConflict) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"bar\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.bar: NUMBER: Field number 1 has already been used in " + "\"Foo\" by field \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, BadMessageSetExtensionType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"MessageSet\"" + " options { message_set_wire_format: true }" + " extension_range { start: 4 end: 5 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:4 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"MessageSet\" }" + "}", + + "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " + "messages.\n"); +} + +TEST_F(ValidationErrorTest, BadMessageSetExtensionLabel) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"MessageSet\"" + " options { message_set_wire_format: true }" + " extension_range { start: 4 end: 5 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:4 label:LABEL_REPEATED type:TYPE_MESSAGE" + " type_name: \"Foo\" extendee: \"MessageSet\" }" + "}", + + "foo.proto: Foo.foo: TYPE: Extensions of MessageSets must be optional " + "messages.\n"); +} + +TEST_F(ValidationErrorTest, FieldInMessageSet) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " options { message_set_wire_format: true }" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.foo: NAME: MessageSets cannot have fields, only " + "extensions.\n"); +} + +TEST_F(ValidationErrorTest, NegativeExtensionRangeNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: -10 end: -1 }" + "}", + + "foo.proto: Foo: NUMBER: Extension numbers must be positive integers.\n"); +} + +TEST_F(ValidationErrorTest, HugeExtensionRangeNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 1 end: 0x70000000 }" + "}", + + "foo.proto: Foo: NUMBER: Extension numbers cannot be greater than " + "536870911.\n"); +} + +TEST_F(ValidationErrorTest, ExtensionRangeEndBeforeStart) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 10 }" + " extension_range { start: 10 end: 5 }" + "}", + + "foo.proto: Foo: NUMBER: Extension range end number must be greater than " + "start number.\n" + "foo.proto: Foo: NUMBER: Extension range end number must be greater than " + "start number.\n"); +} + +TEST_F(ValidationErrorTest, EmptyEnum) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Foo\" }" + // Also use the empty enum in a message to make sure there are no crashes + // during validation (possible if the code attempts to derive a default + // value for the field). + "message_type {" + " name: \"Bar\"" + " field { name: \"foo\" number: 1 label:LABEL_OPTIONAL type_name:\"Foo\" }" + " field { name: \"bar\" number: 2 label:LABEL_OPTIONAL type_name:\"Foo\" " + " default_value: \"NO_SUCH_VALUE\" }" + "}", + + "foo.proto: Foo: NAME: Enums must contain at least one value.\n" + "foo.proto: Bar.bar: DEFAULT_VALUE: Enum type \"Foo\" has no value named " + "\"NO_SUCH_VALUE\".\n"); +} + +TEST_F(ValidationErrorTest, UndefinedExtendee) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not defined.\n"); +} + +TEST_F(ValidationErrorTest, NonMessageExtendee) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } }" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: EXTENDEE: \"Bar\" is not a message type.\n"); +} + +TEST_F(ValidationErrorTest, NotAnExtensionNumber) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + "}" + "message_type {" + " name: \"Foo\"" + " extension { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " extendee: \"Bar\" }" + "}", + + "foo.proto: Foo.foo: NUMBER: \"Bar\" does not declare 1 as an extension " + "number.\n"); +} + +TEST_F(ValidationErrorTest, UndefinedFieldType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" } "); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "which is not imported by \"foo.proto\". To use it here, please add the " + "necessary import.\n"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInIndirectDependency) { + // Test for hidden dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import "bar.proto" + // + // // foo.proto + // import "forward.proto" + // message Foo { + // optional Bar foo = 1; // Error, needs to import bar.proto explicitly. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "which is not imported by \"foo.proto\". To use it here, please add the " + "necessary import.\n"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInPublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import public "bar.proto" + // + // // foo.proto + // import "forward.proto" + // message Foo { + // optional Bar foo = 1; // Correct. "bar.proto" is public imported into + // // forward.proto, so when "foo.proto" imports + // // "forward.proto", it imports "bar.proto" too. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"forward.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, FieldTypeDefinedInTransitivePublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import public "bar.proto" + // + // // forward2.proto + // import public "forward.proto" + // + // // foo.proto + // import "forward2.proto" + // message Foo { + // optional Bar foo = 1; // Correct, public imports are transitive. + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, + FieldTypeDefinedInPrivateDependencyOfPublicDependency) { + // Test for public dependencies. + // + // // bar.proto + // message Bar{} + // + // // forward.proto + // import "bar.proto" + // + // // forward2.proto + // import public "forward.proto" + // + // // foo.proto + // import "forward2.proto" + // message Foo { + // optional Bar foo = 1; // Error, the "bar.proto" is not public imported + // // into "forward.proto", so will not be imported + // // into either "forward2.proto" or "foo.proto". + // } + // + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + BuildFile( + "name: \"forward.proto\"" + "dependency: \"bar.proto\""); + + BuildFile( + "name: \"forward2.proto\"" + "dependency: \"forward.proto\" " + "public_dependency: 0"); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"forward2.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar\" seems to be defined in \"bar.proto\", " + "which is not imported by \"foo.proto\". To use it here, please add the " + "necessary import.\n"); +} + + +TEST_F(ValidationErrorTest, SearchMostLocalFirst) { + // The following should produce an error that Bar.Baz is not defined: + // message Bar { message Baz {} } + // message Foo { + // message Bar { + // // Placing "message Baz{}" here, or removing Foo.Bar altogether, + // // would fix the error. + // } + // optional Bar.Baz baz = 1; + // } + // An one point the lookup code incorrectly did not produce an error in this + // case, because when looking for Bar.Baz, it would try "Foo.Bar.Baz" first, + // fail, and ten try "Bar.Baz" and succeed, even though "Bar" should actually + // refer to the inner Bar, not the outer one. + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " nested_type { name: \"Baz\" }" + "}" + "message_type {" + " name: \"Foo\"" + " nested_type { name: \"Bar\" }" + " field { name:\"baz\" number:1 label:LABEL_OPTIONAL" + " type_name:\"Bar.Baz\" }" + "}", + + "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n"); +} + +TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { + // This test would find the most local "Bar" first, and does, but + // proceeds to find the outer one because the inner one's not an + // aggregate. + BuildFile( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " nested_type { name: \"Baz\" }" + "}" + "message_type {" + " name: \"Foo\"" + " field { name: \"Bar\" number:1 type:TYPE_BYTES } " + " field { name:\"baz\" number:2 label:LABEL_OPTIONAL" + " type_name:\"Bar.Baz\" }" + "}"); +} + +TEST_F(ValidationErrorTest, PackageOriginallyDeclaredInTransitiveDependent) { + // Imagine we have the following: + // + // foo.proto: + // package foo.bar; + // bar.proto: + // package foo.bar; + // import "foo.proto"; + // message Bar {} + // baz.proto: + // package foo; + // import "bar.proto" + // message Baz { optional bar.Bar qux = 1; } + // + // When validating baz.proto, we will look up "bar.Bar". As part of this + // lookup, we first lookup "bar" then try to find "Bar" within it. "bar" + // should resolve to "foo.bar". Note, though, that "foo.bar" was originally + // defined in foo.proto, which is not a direct dependency of baz.proto. The + // implementation of FindSymbol() normally only returns symbols in direct + // dependencies, not indirect ones. This test insures that this does not + // prevent it from finding "foo.bar". + + BuildFile( + "name: \"foo.proto\" " + "package: \"foo.bar\" "); + BuildFile( + "name: \"bar.proto\" " + "package: \"foo.bar\" " + "dependency: \"foo.proto\" " + "message_type { name: \"Bar\" }"); + BuildFile( + "name: \"baz.proto\" " + "package: \"foo\" " + "dependency: \"bar.proto\" " + "message_type { " + " name: \"Baz\" " + " field { name:\"qux\" number:1 label:LABEL_OPTIONAL " + " type_name:\"bar.Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, FieldTypeNotAType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " + " type_name:\".Foo.bar\" }" + " field { name:\"bar\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" + "}", + + "foo.proto: Foo.foo: TYPE: \".Foo.bar\" is not a type.\n"); +} + +TEST_F(ValidationErrorTest, RelativeFieldTypeNotAType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " nested_type {" + " name: \"Bar\"" + " field { name:\"Baz\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " }" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL " + " type_name:\"Bar.Baz\" }" + "}", + "foo.proto: Foo.foo: TYPE: \"Bar.Baz\" is not a type.\n"); +} + +TEST_F(ValidationErrorTest, FieldTypeMayBeItsName) { + BuildFile( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + "}" + "message_type {" + " name: \"Foo\"" + " field { name:\"Bar\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\" }" + "}"); +} + +TEST_F(ValidationErrorTest, EnumFieldTypeIsMessage) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Bar\" } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_ENUM" + " type_name:\"Bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"Bar\" is not an enum type.\n"); +} + +TEST_F(ValidationErrorTest, MessageFieldTypeIsEnum) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE" + " type_name:\"Bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"Bar\" is not a message type.\n"); +} + +TEST_F(ValidationErrorTest, BadEnumDefaultValue) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" + " default_value:\"NO_SUCH_VALUE\" }" + "}", + + "foo.proto: Foo.foo: DEFAULT_VALUE: Enum type \"Bar\" has no value named " + "\"NO_SUCH_VALUE\".\n"); +} + +TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32" + " type_name:\"Foo\" }" + "}", + + "foo.proto: Foo.foo: TYPE: Field with primitive type has type_name.\n"); +} + +TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_MESSAGE }" + "}", + + "foo.proto: Foo.foo: TYPE: Field with message or enum type missing " + "type_name.\n"); +} + +TEST_F(ValidationErrorTest, InputTypeNotDefined) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" + "}", + + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n" + ); +} + +TEST_F(ValidationErrorTest, InputTypeNotAMessage) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }" + "}", + + "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n" + ); +} + +TEST_F(ValidationErrorTest, OutputTypeNotDefined) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" + "}", + + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n" + ); +} + +TEST_F(ValidationErrorTest, OutputTypeNotAMessage) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "service {" + " name: \"TestService\"" + " method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }" + "}", + + "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n" + ); +} + + +TEST_F(ValidationErrorTest, IllegalPackedField) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {\n" + " name: \"Foo\"" + " field { name:\"packed_string\" number:1 label:LABEL_REPEATED " + " type:TYPE_STRING " + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + " field { name:\"packed_message\" number:3 label:LABEL_REPEATED " + " type_name: \"Foo\"" + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + " field { name:\"optional_int32\" number: 4 label: LABEL_OPTIONAL " + " type:TYPE_INT32 " + " options { uninterpreted_option {" + " name { name_part: \"packed\" is_extension: false }" + " identifier_value: \"true\" }}}\n" + "}", + + "foo.proto: Foo.packed_string: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n" + "foo.proto: Foo.packed_message: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n" + "foo.proto: Foo.optional_int32: TYPE: [packed = true] can only be " + "specified for repeated primitive fields.\n" + ); +} + +TEST_F(ValidationErrorTest, OptionWrongType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " positive_int_value: 1 }" + " }" + " }" + "}\n", + + "foo.proto: TestMessage.foo: OPTION_VALUE: Value must be identifier for " + "enum-valued option \"google.protobuf.FieldOptions.ctype\".\n"); +} + +TEST_F(ValidationErrorTest, OptionExtendsAtomicType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " name { name_part: \"foo\" " + " is_extension: true }" + " positive_int_value: 1 }" + " }" + " }" + "}\n", + + "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" is an " + "atomic type, not a message.\n"); +} + +TEST_F(ValidationErrorTest, DupOption) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_UINT32 " + " options { uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " identifier_value: \"CORD\" }" + " uninterpreted_option { name { name_part: \"ctype\" " + " is_extension: false }" + " identifier_value: \"CORD\" }" + " }" + " }" + "}\n", + + "foo.proto: TestMessage.foo: OPTION_NAME: Option \"ctype\" was " + "already set.\n"); +} + +TEST_F(ValidationErrorTest, InvalidOptionName) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type { " + " name: \"TestMessage\" " + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_BOOL " + " options { uninterpreted_option { " + " name { name_part: \"uninterpreted_option\" " + " is_extension: false }" + " positive_int_value: 1 " + " }" + " }" + " }" + "}\n", + + "foo.proto: TestMessage.foo: OPTION_NAME: Option must not use " + "reserved name \"uninterpreted_option\".\n"); +} + +TEST_F(ValidationErrorTest, RepeatedOption) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED " + " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " double_value: 1.2 } }", + + "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. " + "Repeated options are not supported.\n"); +} + +TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo1\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }" + "extension { name: \"foo2\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FieldOptions\" }", + + "foo.proto: foo2: NUMBER: Extension number 7672757 has already been used " + "in \"google.protobuf.FieldOptions\" by extension \"foo1\".\n"); +} + +TEST_F(ValidationErrorTest, Int32OptionValueOutOfPositiveRange) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x80000000 } " + "}", + + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int32 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, Int32OptionValueOutOfNegativeRange) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " negative_int_value: -0x80000001 } " + "}", + + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int32 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, Int32OptionValueIsNotPositiveInt) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"5\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " + "for int32 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, Int64OptionValueOutOfRange) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x8000000000000000 } " + "}", + + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for int64 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, Int64OptionValueIsNotPositiveInt) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_INT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"5\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be integer " + "for int64 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, UInt32OptionValueOutOfRange) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " positive_int_value: 0x100000000 } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value out of range " + "for uint32 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, UInt32OptionValueIsNotPositiveInt) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT32 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " double_value: -5.6 } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " + "for uint32 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, UInt64OptionValueIsNotPositiveInt) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_UINT64 extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " negative_int_value: -5 } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer " + "for uint64 option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, FloatOptionValueIsNotNumber) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"bar\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be number " + "for float option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, DoubleOptionValueIsNotNumber) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_DOUBLE extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"bar\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be number " + "for double option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, BoolOptionValueIsNotTrueOrFalse) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_BOOL extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"bar\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be \"true\" or \"false\" " + "for boolean option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, EnumOptionValueIsNotIdentifier) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " string_value: \"QUUX\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be identifier for " + "enum-valued option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, EnumOptionValueIsNotEnumValueName) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum\" has no value " + "named \"QUUX\" for option \"foo\".\n"); +} + +TEST_F(ValidationErrorTest, EnumOptionValueIsSiblingEnumValueName) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "enum_type { name: \"FooEnum1\" value { name: \"BAR\" number: 1 } " + " value { name: \"BAZ\" number: 2 } }" + "enum_type { name: \"FooEnum2\" value { name: \"QUX\" number: 1 } " + " value { name: \"QUUX\" number: 2 } }" + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_ENUM type_name: \"FooEnum1\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Enum type \"FooEnum1\" has no value " + "named \"QUUX\" for option \"foo\". This appears to be a value from a " + "sibling type.\n"); +} + +TEST_F(ValidationErrorTest, StringOptionValueIsNotString) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_STRING extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " identifier_value: \"QUUX\" } }", + + "foo.proto: foo.proto: OPTION_VALUE: Value must be quoted string for " + "string option \"foo\".\n"); +} + +// Helper function for tests that check for aggregate value parsing +// errors. The "value" argument is embedded inside the +// "uninterpreted_option" portion of the result. +static string EmbedAggregateValue(const char* value) { + return strings::Substitute( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type { name: \"Foo\" } " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Foo\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " $0 } }", + value); +} + +TEST_F(ValidationErrorTest, AggregateValueNotFound) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("string_value: \"\""), + "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. " + "To set the entire message, use syntax like " + "\"foo = { }\". To set fields within it, use " + "syntax like \"foo.foo = value\".\n"); +} + +TEST_F(ValidationErrorTest, AggregateValueParseError) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"1+2\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Expected identifier.\n"); +} + +TEST_F(ValidationErrorTest, AggregateValueUnknownFields) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"x:100\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n"); +} + +TEST_F(ValidationErrorTest, NotLiteImportsLite) { + BuildFile( + "name: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } "); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"bar.proto\" ", + + "foo.proto: foo.proto: OTHER: Files that do not use optimize_for = " + "LITE_RUNTIME cannot import files which do use this option. This file " + "is not lite, but it imports \"bar.proto\" which is.\n"); +} + +TEST_F(ValidationErrorTest, LiteExtendsNotLite) { + BuildFile( + "name: \"bar.proto\" " + "message_type: {" + " name: \"Bar\"" + " extension_range { start: 1 end: 1000 }" + "}"); + + BuildFileWithErrors( + "name: \"foo.proto\" " + "dependency: \"bar.proto\" " + "options { optimize_for: LITE_RUNTIME } " + "extension { name: \"ext\" number: 123 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"Bar\" }", + + "foo.proto: ext: EXTENDEE: Extensions to non-lite types can only be " + "declared in non-lite files. Note that you cannot extend a non-lite " + "type to contain a lite type, but the reverse is allowed.\n"); +} + +TEST_F(ValidationErrorTest, NoLiteServices) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: true" + " java_generic_services: true" + "} " + "service { name: \"Foo\" }", + + "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " + "define services unless you set both options cc_generic_services and " + "java_generic_sevices to false.\n"); + + BuildFile( + "name: \"bar.proto\" " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: false" + " java_generic_services: false" + "} " + "service { name: \"Bar\" }"); +} + +TEST_F(ValidationErrorTest, RollbackAfterError) { + // Build a file which contains every kind of construct but references an + // undefined type. All these constructs will be added to the symbol table + // before the undefined type error is noticed. The DescriptorPool will then + // have to roll everything back. + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" + "} " + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"BAR\" number:1 }" + "} " + "service {" + " name: \"TestService\"" + " method {" + " name: \"Baz\"" + " input_type: \"NoSuchType\"" // error + " output_type: \"TestMessage\"" + " }" + "}", + + "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n" + ); + + // Make sure that if we build the same file again with the error fixed, + // it works. If the above rollback was incomplete, then some symbols will + // be left defined, and this second attempt will fail since it tries to + // re-define the same symbols. + BuildFile( + "name: \"foo.proto\" " + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" + "} " + "enum_type {" + " name: \"TestEnum\"" + " value { name:\"BAR\" number:1 }" + "} " + "service {" + " name: \"TestService\"" + " method { name:\"Baz\"" + " input_type:\"TestMessage\"" + " output_type:\"TestMessage\" }" + "}"); +} + +TEST_F(ValidationErrorTest, ErrorsReportedToLogError) { + // Test that errors are reported to GOOGLE_LOG(ERROR) if no error collector is + // provided. + + FileDescriptorProto file_proto; + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"foo.proto\" " + "message_type { name: \"Foo\" } " + "message_type { name: \"Foo\" } ", + &file_proto)); + + vector errors; + + { + ScopedMemoryLog log; + EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL); + errors = log.GetMessages(ERROR); + } + + ASSERT_EQ(2, errors.size()); + + EXPECT_EQ("Invalid proto descriptor for file \"foo.proto\":", errors[0]); + EXPECT_EQ(" Foo: \"Foo\" is already defined.", errors[1]); +} + +TEST_F(ValidationErrorTest, DisallowEnumAlias) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + " options { allow_alias: false }" + "}", + "foo.proto: Bar: NUMBER: " + "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " + "If this is intended, set 'option allow_alias = true;' to the enum " + "definition.\n"); +} + +// =================================================================== +// DescriptorDatabase + +static void AddToDatabase(SimpleDescriptorDatabase* database, + const char* file_text) { + FileDescriptorProto file_proto; + EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + database->Add(file_proto); +} + +class DatabaseBackedPoolTest : public testing::Test { + protected: + DatabaseBackedPoolTest() {} + + SimpleDescriptorDatabase database_; + + virtual void SetUp() { + AddToDatabase(&database_, + "name: 'foo.proto' " + "message_type { name:'Foo' extension_range { start: 1 end: 100 } } " + "enum_type { name:'TestEnum' value { name:'DUMMY' number:0 } } " + "service { name:'TestService' } "); + AddToDatabase(&database_, + "name: 'bar.proto' " + "dependency: 'foo.proto' " + "message_type { name:'Bar' } " + "extension { name:'foo_ext' extendee: '.Foo' number:5 " + " label:LABEL_OPTIONAL type:TYPE_INT32 } "); + // Baz has an undeclared dependency on Foo. + AddToDatabase(&database_, + "name: 'baz.proto' " + "message_type { " + " name:'Baz' " + " field { name:'foo' number:1 label:LABEL_OPTIONAL type_name:'Foo' } " + "}"); + } + + // We can't inject a file containing errors into a DescriptorPool, so we + // need an actual mock DescriptorDatabase to test errors. + class ErrorDescriptorDatabase : public DescriptorDatabase { + public: + ErrorDescriptorDatabase() {} + ~ErrorDescriptorDatabase() {} + + // implements DescriptorDatabase --------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output) { + // error.proto and error2.proto cyclically import each other. + if (filename == "error.proto") { + output->Clear(); + output->set_name("error.proto"); + output->add_dependency("error2.proto"); + return true; + } else if (filename == "error2.proto") { + output->Clear(); + output->set_name("error2.proto"); + output->add_dependency("error.proto"); + return true; + } else { + return false; + } + } + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) { + return false; + } + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return false; + } + }; + + // A DescriptorDatabase that counts how many times each method has been + // called and forwards to some other DescriptorDatabase. + class CallCountingDatabase : public DescriptorDatabase { + public: + CallCountingDatabase(DescriptorDatabase* wrapped_db) + : wrapped_db_(wrapped_db) { + Clear(); + } + ~CallCountingDatabase() {} + + DescriptorDatabase* wrapped_db_; + + int call_count_; + + void Clear() { + call_count_ = 0; + } + + // implements DescriptorDatabase --------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output) { + ++call_count_; + return wrapped_db_->FindFileByName(filename, output); + } + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) { + ++call_count_; + return wrapped_db_->FindFileContainingSymbol(symbol_name, output); + } + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) { + ++call_count_; + return wrapped_db_->FindFileContainingExtension( + containing_type, field_number, output); + } + }; + + // A DescriptorDatabase which falsely always returns foo.proto when searching + // for any symbol or extension number. This shouldn't cause the + // DescriptorPool to reload foo.proto if it is already loaded. + class FalsePositiveDatabase : public DescriptorDatabase { + public: + FalsePositiveDatabase(DescriptorDatabase* wrapped_db) + : wrapped_db_(wrapped_db) {} + ~FalsePositiveDatabase() {} + + DescriptorDatabase* wrapped_db_; + + // implements DescriptorDatabase --------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output) { + return wrapped_db_->FindFileByName(filename, output); + } + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) { + return FindFileByName("foo.proto", output); + } + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return FindFileByName("foo.proto", output); + } + }; +}; + +TEST_F(DatabaseBackedPoolTest, FindFileByName) { + DescriptorPool pool(&database_); + + const FileDescriptor* foo = pool.FindFileByName("foo.proto"); + ASSERT_TRUE(foo != NULL); + EXPECT_EQ("foo.proto", foo->name()); + ASSERT_EQ(1, foo->message_type_count()); + EXPECT_EQ("Foo", foo->message_type(0)->name()); + + EXPECT_EQ(foo, pool.FindFileByName("foo.proto")); + + EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL); +} + +TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) { + DescriptorPool pool(&database_); + + const FileDescriptor* foo = pool.FindFileByName("foo.proto"); + ASSERT_TRUE(foo != NULL); + EXPECT_EQ("foo.proto", foo->name()); + ASSERT_EQ(1, foo->message_type_count()); + EXPECT_EQ("Foo", foo->message_type(0)->name()); + + const FileDescriptor* bar = pool.FindFileByName("bar.proto"); + ASSERT_TRUE(bar != NULL); + EXPECT_EQ("bar.proto", bar->name()); + ASSERT_EQ(1, bar->message_type_count()); + EXPECT_EQ("Bar", bar->message_type(0)->name()); + + ASSERT_EQ(1, bar->dependency_count()); + EXPECT_EQ(foo, bar->dependency(0)); +} + +TEST_F(DatabaseBackedPoolTest, FindDependentBeforeDependency) { + DescriptorPool pool(&database_); + + const FileDescriptor* bar = pool.FindFileByName("bar.proto"); + ASSERT_TRUE(bar != NULL); + EXPECT_EQ("bar.proto", bar->name()); + ASSERT_EQ(1, bar->message_type_count()); + ASSERT_EQ("Bar", bar->message_type(0)->name()); + + const FileDescriptor* foo = pool.FindFileByName("foo.proto"); + ASSERT_TRUE(foo != NULL); + EXPECT_EQ("foo.proto", foo->name()); + ASSERT_EQ(1, foo->message_type_count()); + ASSERT_EQ("Foo", foo->message_type(0)->name()); + + ASSERT_EQ(1, bar->dependency_count()); + EXPECT_EQ(foo, bar->dependency(0)); +} + +TEST_F(DatabaseBackedPoolTest, FindFileContainingSymbol) { + DescriptorPool pool(&database_); + + const FileDescriptor* file = pool.FindFileContainingSymbol("Foo"); + ASSERT_TRUE(file != NULL); + EXPECT_EQ("foo.proto", file->name()); + EXPECT_EQ(file, pool.FindFileByName("foo.proto")); + + EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL); +} + +TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) { + DescriptorPool pool(&database_); + + const Descriptor* type = pool.FindMessageTypeByName("Foo"); + ASSERT_TRUE(type != NULL); + EXPECT_EQ("Foo", type->name()); + EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto")); + + EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL); +} + +TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) { + DescriptorPool pool(&database_); + + const Descriptor* foo = pool.FindMessageTypeByName("Foo"); + ASSERT_TRUE(foo != NULL); + + const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5); + ASSERT_TRUE(extension != NULL); + EXPECT_EQ("foo_ext", extension->name()); + EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto")); + + EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL); +} + +TEST_F(DatabaseBackedPoolTest, FindAllExtensions) { + DescriptorPool pool(&database_); + + const Descriptor* foo = pool.FindMessageTypeByName("Foo"); + + for (int i = 0; i < 2; ++i) { + // Repeat the lookup twice, to check that we get consistent + // results despite the fallback database lookup mutating the pool. + vector extensions; + pool.FindAllExtensions(foo, &extensions); + ASSERT_EQ(1, extensions.size()); + EXPECT_EQ(5, extensions[0]->number()); + } +} + +TEST_F(DatabaseBackedPoolTest, ErrorWithoutErrorCollector) { + ErrorDescriptorDatabase error_database; + DescriptorPool pool(&error_database); + + vector errors; + + { + ScopedMemoryLog log; + EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + errors = log.GetMessages(ERROR); + } + + EXPECT_FALSE(errors.empty()); +} + +TEST_F(DatabaseBackedPoolTest, ErrorWithErrorCollector) { + ErrorDescriptorDatabase error_database; + MockErrorCollector error_collector; + DescriptorPool pool(&error_database, &error_collector); + + EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + EXPECT_EQ( + "error.proto: error.proto: OTHER: File recursively imports itself: " + "error.proto -> error2.proto -> error.proto\n" + "error2.proto: error2.proto: OTHER: Import \"error.proto\" was not " + "found or had errors.\n" + "error.proto: error.proto: OTHER: Import \"error2.proto\" was not " + "found or had errors.\n", + error_collector.text_); +} + +TEST_F(DatabaseBackedPoolTest, UndeclaredDependencyOnUnbuiltType) { + // Check that we find and report undeclared dependencies on types that exist + // in the descriptor database but that have not not been built yet. + MockErrorCollector error_collector; + DescriptorPool pool(&database_, &error_collector); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + EXPECT_EQ( + "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", " + "which is not imported by \"baz.proto\". To use it here, please add " + "the necessary import.\n", + error_collector.text_); +} + +TEST_F(DatabaseBackedPoolTest, RollbackAfterError) { + // Make sure that all traces of bad types are removed from the pool. This used + // to be b/4529436, due to the fact that a symbol resolution failure could + // potentially cause another file to be recursively built, which would trigger + // a checkpoint _past_ possibly invalid symbols. + // Baz is defined in the database, but the file is invalid because it is + // missing a necessary import. + DescriptorPool pool(&database_); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); + // Make sure that searching again for the file or the type fails. + EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL); +} + +TEST_F(DatabaseBackedPoolTest, UnittestProto) { + // Try to load all of unittest.proto from a DescriptorDatabase. This should + // thoroughly test all paths through DescriptorBuilder to insure that there + // are no deadlocking problems when pool_->mutex_ is non-NULL. + const FileDescriptor* original_file = + protobuf_unittest::TestAllTypes::descriptor()->file(); + + DescriptorPoolDatabase database(*DescriptorPool::generated_pool()); + DescriptorPool pool(&database); + const FileDescriptor* file_from_database = + pool.FindFileByName(original_file->name()); + + ASSERT_TRUE(file_from_database != NULL); + + FileDescriptorProto original_file_proto; + original_file->CopyTo(&original_file_proto); + + FileDescriptorProto file_from_database_proto; + file_from_database->CopyTo(&file_from_database_proto); + + EXPECT_EQ(original_file_proto.DebugString(), + file_from_database_proto.DebugString()); +} + +TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { + // Searching for a child of an existing descriptor should never fall back + // to the DescriptorDatabase even if it isn't found, because we know all + // children are already loaded. + CallCountingDatabase call_counter(&database_); + DescriptorPool pool(&call_counter); + + const FileDescriptor* file = pool.FindFileByName("foo.proto"); + ASSERT_TRUE(file != NULL); + const Descriptor* foo = pool.FindMessageTypeByName("Foo"); + ASSERT_TRUE(foo != NULL); + const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum"); + ASSERT_TRUE(test_enum != NULL); + const ServiceDescriptor* test_service = pool.FindServiceByName("TestService"); + ASSERT_TRUE(test_service != NULL); + + EXPECT_NE(0, call_counter.call_count_); + call_counter.Clear(); + + EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL); + EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL); + EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL); + EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL); + EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL); + + EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL); + EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL); + EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL); + + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL); + EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL); + EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL); + EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL); + EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL); + EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL); + EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL); + + EXPECT_EQ(0, call_counter.call_count_); +} + +TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) { + // If FindFileContainingSymbol() or FindFileContainingExtension() return a + // file that is already in the DescriptorPool, it should not attempt to + // reload the file. + FalsePositiveDatabase false_positive_database(&database_); + MockErrorCollector error_collector; + DescriptorPool pool(&false_positive_database, &error_collector); + + // First make sure foo.proto is loaded. + const Descriptor* foo = pool.FindMessageTypeByName("Foo"); + ASSERT_TRUE(foo != NULL); + + // Try inducing false positives. + EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL); + EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL); + + // No errors should have been reported. (If foo.proto was incorrectly + // loaded multiple times, errors would have been reported.) + EXPECT_EQ("", error_collector.text_); +} + +TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { + ErrorDescriptorDatabase error_database; + MockErrorCollector error_collector; + DescriptorPool pool(&error_database, &error_collector); + + EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + error_collector.text_.clear(); + EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); + EXPECT_EQ("", error_collector.text_); +} + +TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { + // If a lookup finds a symbol of the wrong type (e.g. we pass a type name + // to FindFieldByName()), we should fail fast, without checking the fallback + // database. + CallCountingDatabase call_counter(&database_); + DescriptorPool pool(&call_counter); + + const FileDescriptor* file = pool.FindFileByName("foo.proto"); + ASSERT_TRUE(file != NULL); + const Descriptor* foo = pool.FindMessageTypeByName("Foo"); + ASSERT_TRUE(foo != NULL); + const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum"); + ASSERT_TRUE(test_enum != NULL); + + EXPECT_NE(0, call_counter.call_count_); + call_counter.Clear(); + + EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL); + EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL); + EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL); + EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL); + EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL); + EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL); + EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL); + + EXPECT_EQ(0, call_counter.call_count_); +} + +// =================================================================== + +class AbortingErrorCollector : public DescriptorPool::ErrorCollector { + public: + AbortingErrorCollector() {} + + virtual void AddError( + const string &filename, + const string &element_name, + const Message *message, + ErrorLocation location, + const string &error_message) { + GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": " + << error_message; + } + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector); +}; + +// A source tree containing only one file. +class SingletonSourceTree : public compiler::SourceTree { + public: + SingletonSourceTree(const string& filename, const string& contents) + : filename_(filename), contents_(contents) {} + + virtual io::ZeroCopyInputStream* Open(const string& filename) { + return filename == filename_ ? + new io::ArrayInputStream(contents_.data(), contents_.size()) : NULL; + } + + private: + const string filename_; + const string contents_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree); +}; + +const char *const kSourceLocationTestInput = + "syntax = \"proto2\";\n" + "message A {\n" + " optional int32 a = 1;\n" + " message B {\n" + " required double b = 1;\n" + " }\n" + "}\n" + "enum Indecision {\n" + " YES = 1;\n" + " NO = 2;\n" + " MAYBE = 3;\n" + "}\n" + "service S {\n" + " rpc Method(A) returns (A.B);\n" + // Put an empty line here to make the source location range match. + "\n" + "}\n"; + +class SourceLocationTest : public testing::Test { + public: + SourceLocationTest() + : source_tree_("/test/test.proto", kSourceLocationTestInput), + db_(&source_tree_), + pool_(&db_, &collector_) {} + + static string PrintSourceLocation(const SourceLocation &loc) { + return strings::Substitute("$0:$1-$2:$3", + 1 + loc.start_line, + 1 + loc.start_column, + 1 + loc.end_line, + 1 + loc.end_column); + } + + private: + AbortingErrorCollector collector_; + SingletonSourceTree source_tree_; + compiler::SourceTreeDescriptorDatabase db_; + + protected: + DescriptorPool pool_; +}; + +// TODO(adonovan): implement support for option fields and for +// subparts of declarations. + +TEST_F(SourceLocationTest, GetSourceLocation) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + const Descriptor *a_desc = file_desc->FindMessageTypeByName("A"); + EXPECT_TRUE(a_desc->GetSourceLocation(&loc)); + EXPECT_EQ("2:1-7:2", PrintSourceLocation(loc)); + + const Descriptor *a_b_desc = a_desc->FindNestedTypeByName("B"); + EXPECT_TRUE(a_b_desc->GetSourceLocation(&loc)); + EXPECT_EQ("4:3-6:4", PrintSourceLocation(loc)); + + const EnumDescriptor *e_desc = file_desc->FindEnumTypeByName("Indecision"); + EXPECT_TRUE(e_desc->GetSourceLocation(&loc)); + EXPECT_EQ("8:1-12:2", PrintSourceLocation(loc)); + + const EnumValueDescriptor *yes_desc = e_desc->FindValueByName("YES"); + EXPECT_TRUE(yes_desc->GetSourceLocation(&loc)); + EXPECT_EQ("9:3-9:13", PrintSourceLocation(loc)); + + const ServiceDescriptor *s_desc = file_desc->FindServiceByName("S"); + EXPECT_TRUE(s_desc->GetSourceLocation(&loc)); + EXPECT_EQ("13:1-16:2", PrintSourceLocation(loc)); + + const MethodDescriptor *m_desc = s_desc->FindMethodByName("Method"); + EXPECT_TRUE(m_desc->GetSourceLocation(&loc)); + EXPECT_EQ("14:3-14:31", PrintSourceLocation(loc)); + +} + +// Missing SourceCodeInfo doesn't cause crash: +TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + FileDescriptorProto proto; + file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. + EXPECT_FALSE(proto.has_source_code_info()); + + DescriptorPool bad1_pool(&pool_); + const FileDescriptor* bad1_file_desc = + GOOGLE_CHECK_NOTNULL(bad1_pool.BuildFile(proto)); + const Descriptor *bad1_a_desc = bad1_file_desc->FindMessageTypeByName("A"); + EXPECT_FALSE(bad1_a_desc->GetSourceLocation(&loc)); +} + +// Corrupt SourceCodeInfo doesn't cause crash: +TEST_F(SourceLocationTest, GetSourceLocation_BogusSourceCodeInfo) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + FileDescriptorProto proto; + file_desc->CopyTo(&proto); // Note, this discards the SourceCodeInfo. + EXPECT_FALSE(proto.has_source_code_info()); + SourceCodeInfo_Location *loc_msg = + proto.mutable_source_code_info()->add_location(); + loc_msg->add_path(1); + loc_msg->add_path(2); + loc_msg->add_path(3); + loc_msg->add_span(4); + loc_msg->add_span(5); + loc_msg->add_span(6); + + DescriptorPool bad2_pool(&pool_); + const FileDescriptor* bad2_file_desc = + GOOGLE_CHECK_NOTNULL(bad2_pool.BuildFile(proto)); + const Descriptor *bad2_a_desc = bad2_file_desc->FindMessageTypeByName("A"); + EXPECT_FALSE(bad2_a_desc->GetSourceLocation(&loc)); +} + +// =================================================================== + +const char* const kCopySourceCodeInfoToTestInput = + "syntax = \"proto2\";\n" + "message Foo {}\n"; + +// Required since source code information is not preserved by +// FileDescriptorTest. +class CopySourceCodeInfoToTest : public testing::Test { + public: + CopySourceCodeInfoToTest() + : source_tree_("/test/test.proto", kCopySourceCodeInfoToTestInput), + db_(&source_tree_), + pool_(&db_, &collector_) {} + + private: + AbortingErrorCollector collector_; + SingletonSourceTree source_tree_; + compiler::SourceTreeDescriptorDatabase db_; + + protected: + DescriptorPool pool_; +}; + +TEST_F(CopySourceCodeInfoToTest, CopyTo_DoesNotCopySourceCodeInfo) { + const FileDescriptor* file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + FileDescriptorProto file_desc_proto; + ASSERT_FALSE(file_desc_proto.has_source_code_info()); + + file_desc->CopyTo(&file_desc_proto); + EXPECT_FALSE(file_desc_proto.has_source_code_info()); +} + +TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { + const FileDescriptor* file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + FileDescriptorProto file_desc_proto; + ASSERT_FALSE(file_desc_proto.has_source_code_info()); + + file_desc->CopySourceCodeInfoTo(&file_desc_proto); + const SourceCodeInfo& info = file_desc_proto.source_code_info(); + ASSERT_EQ(3, info.location_size()); + // Get the Foo message location + const SourceCodeInfo_Location& foo_location = info.location(1); + ASSERT_EQ(2, foo_location.path_size()); + EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); + EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined + ASSERT_EQ(3, foo_location.span_size()); // Foo spans one line + EXPECT_EQ(1, foo_location.span(0)); // Foo is declared on line 1 + EXPECT_EQ(0, foo_location.span(1)); // Foo starts at column 0 + EXPECT_EQ(14, foo_location.span(2)); // Foo ends on column 14 +} + +// =================================================================== + + +} // namespace descriptor_unittest +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.cc new file mode 100644 index 000000000..09bec5436 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.cc @@ -0,0 +1,571 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// DynamicMessage is implemented by constructing a data structure which +// has roughly the same memory layout as a generated message would have. +// Then, we use GeneratedMessageReflection to implement our reflection +// interface. All the other operations we need to implement (e.g. +// parsing, copying, etc.) are already implemented in terms of +// Reflection, so the rest is easy. +// +// The up side of this strategy is that it's very efficient. We don't +// need to use hash_maps or generic representations of fields. The +// down side is that this is a low-level memory management hack which +// can be tricky to get right. +// +// As mentioned in the header, we only expose a DynamicMessageFactory +// publicly, not the DynamicMessage class itself. This is because +// GenericMessageReflection wants to have a pointer to a "default" +// copy of the class, with all fields initialized to their default +// values. We only want to construct one of these per message type, +// so DynamicMessageFactory stores a cache of default messages for +// each type it sees (each unique Descriptor pointer). The code +// refers to the "default" copy of the class as the "prototype". +// +// Note on memory allocation: This module often calls "operator new()" +// to allocate untyped memory, rather than calling something like +// "new uint8[]". This is because "operator new()" means "Give me some +// space which I can use as I please." while "new uint8[]" means "Give +// me an array of 8-bit integers.". In practice, the later may return +// a pointer that is not aligned correctly for general use. I believe +// Item 8 of "More Effective C++" discusses this in more detail, though +// I don't have the book on me right now so I'm not sure. + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using internal::WireFormat; +using internal::ExtensionSet; +using internal::GeneratedMessageReflection; + + +// =================================================================== +// Some helper tables and functions... + +namespace { + +// Compute the byte size of the in-memory representation of the field. +int FieldSpaceUsed(const FieldDescriptor* field) { + typedef FieldDescriptor FD; // avoid line wrapping + if (field->label() == FD::LABEL_REPEATED) { + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32 : return sizeof(RepeatedField); + case FD::CPPTYPE_INT64 : return sizeof(RepeatedField); + case FD::CPPTYPE_UINT32 : return sizeof(RepeatedField); + case FD::CPPTYPE_UINT64 : return sizeof(RepeatedField); + case FD::CPPTYPE_DOUBLE : return sizeof(RepeatedField); + case FD::CPPTYPE_FLOAT : return sizeof(RepeatedField); + case FD::CPPTYPE_BOOL : return sizeof(RepeatedField); + case FD::CPPTYPE_ENUM : return sizeof(RepeatedField); + case FD::CPPTYPE_MESSAGE: return sizeof(RepeatedPtrField); + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return sizeof(RepeatedPtrField); + } + break; + } + } else { + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32 : return sizeof(int32 ); + case FD::CPPTYPE_INT64 : return sizeof(int64 ); + case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); + case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); + case FD::CPPTYPE_DOUBLE : return sizeof(double ); + case FD::CPPTYPE_FLOAT : return sizeof(float ); + case FD::CPPTYPE_BOOL : return sizeof(bool ); + case FD::CPPTYPE_ENUM : return sizeof(int ); + + case FD::CPPTYPE_MESSAGE: + return sizeof(Message*); + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return sizeof(string*); + } + break; + } + } + + GOOGLE_LOG(DFATAL) << "Can't get here."; + return 0; +} + +inline int DivideRoundingUp(int i, int j) { + return (i + (j - 1)) / j; +} + +static const int kSafeAlignment = sizeof(uint64); + +inline int AlignTo(int offset, int alignment) { + return DivideRoundingUp(offset, alignment) * alignment; +} + +// Rounds the given byte offset up to the next offset aligned such that any +// type may be stored at it. +inline int AlignOffset(int offset) { + return AlignTo(offset, kSafeAlignment); +} + +#define bitsizeof(T) (sizeof(T) * 8) + +} // namespace + +// =================================================================== + +class DynamicMessage : public Message { + public: + struct TypeInfo { + int size; + int has_bits_offset; + int unknown_fields_offset; + int extensions_offset; + + // Not owned by the TypeInfo. + DynamicMessageFactory* factory; // The factory that created this object. + const DescriptorPool* pool; // The factory's DescriptorPool. + const Descriptor* type; // Type of this DynamicMessage. + + // Warning: The order in which the following pointers are defined is + // important (the prototype must be deleted *before* the offsets). + scoped_array offsets; + scoped_ptr reflection; + // Don't use a scoped_ptr to hold the prototype: the destructor for + // DynamicMessage needs to know whether it is the prototype, and does so by + // looking back at this field. This would assume details about the + // implementation of scoped_ptr. + const DynamicMessage* prototype; + + TypeInfo() : prototype(NULL) {} + + ~TypeInfo() { + delete prototype; + } + }; + + DynamicMessage(const TypeInfo* type_info); + ~DynamicMessage(); + + // Called on the prototype after construction to initialize message fields. + void CrossLinkPrototypes(); + + // implements Message ---------------------------------------------- + + Message* New() const; + + int GetCachedSize() const; + void SetCachedSize(int size) const; + + Metadata GetMetadata() const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); + + inline bool is_prototype() const { + return type_info_->prototype == this || + // If type_info_->prototype is NULL, then we must be constructing + // the prototype now, which means we must be the prototype. + type_info_->prototype == NULL; + } + + inline void* OffsetToPointer(int offset) { + return reinterpret_cast(this) + offset; + } + inline const void* OffsetToPointer(int offset) const { + return reinterpret_cast(this) + offset; + } + + const TypeInfo* type_info_; + + // TODO(kenton): Make this an atomic when C++ supports it. + mutable int cached_byte_size_; +}; + +DynamicMessage::DynamicMessage(const TypeInfo* type_info) + : type_info_(type_info), + cached_byte_size_(0) { + // We need to call constructors for various fields manually and set + // default values where appropriate. We use placement new to call + // constructors. If you haven't heard of placement new, I suggest Googling + // it now. We use placement new even for primitive types that don't have + // constructors for consistency. (In theory, placement new should be used + // any time you are trying to convert untyped memory to typed memory, though + // in practice that's not strictly necessary for types that don't have a + // constructor.) + + const Descriptor* descriptor = type_info_->type; + + new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet; + + if (type_info_->extensions_offset != -1) { + new(OffsetToPointer(type_info_->extensions_offset)) ExtensionSet; + } + + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + if (!field->is_repeated()) { \ + new(field_ptr) TYPE(field->default_value_##TYPE()); \ + } else { \ + new(field_ptr) RepeatedField(); \ + } \ + break; + + HANDLE_TYPE(INT32 , int32 ); + HANDLE_TYPE(INT64 , int64 ); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT , float ); + HANDLE_TYPE(BOOL , bool ); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + if (!field->is_repeated()) { + new(field_ptr) int(field->default_value_enum()->number()); + } else { + new(field_ptr) RepeatedField(); + } + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + if (!field->is_repeated()) { + if (is_prototype()) { + new(field_ptr) const string*(&field->default_value_string()); + } else { + string* default_value = + *reinterpret_cast( + type_info_->prototype->OffsetToPointer( + type_info_->offsets[i])); + new(field_ptr) string*(default_value); + } + } else { + new(field_ptr) RepeatedPtrField(); + } + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: { + if (!field->is_repeated()) { + new(field_ptr) Message*(NULL); + } else { + new(field_ptr) RepeatedPtrField(); + } + break; + } + } + } +} + +DynamicMessage::~DynamicMessage() { + const Descriptor* descriptor = type_info_->type; + + reinterpret_cast( + OffsetToPointer(type_info_->unknown_fields_offset))->~UnknownFieldSet(); + + if (type_info_->extensions_offset != -1) { + reinterpret_cast( + OffsetToPointer(type_info_->extensions_offset))->~ExtensionSet(); + } + + // We need to manually run the destructors for repeated fields and strings, + // just as we ran their constructors in the the DynamicMessage constructor. + // Additionally, if any singular embedded messages have been allocated, we + // need to delete them, UNLESS we are the prototype message of this type, + // in which case any embedded messages are other prototypes and shouldn't + // be touched. + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + reinterpret_cast*>(field_ptr) \ + ->~RepeatedField(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + reinterpret_cast*>(field_ptr) + ->~RepeatedPtrField(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + reinterpret_cast*>(field_ptr) + ->~RepeatedPtrField(); + break; + } + + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + string* ptr = *reinterpret_cast(field_ptr); + if (ptr != &field->default_value_string()) { + delete ptr; + } + break; + } + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (!is_prototype()) { + Message* message = *reinterpret_cast(field_ptr); + if (message != NULL) { + delete message; + } + } + } + } +} + +void DynamicMessage::CrossLinkPrototypes() { + // This should only be called on the prototype message. + GOOGLE_CHECK(is_prototype()); + + DynamicMessageFactory* factory = type_info_->factory; + const Descriptor* descriptor = type_info_->type; + + // Cross-link default messages. + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { + // For fields with message types, we need to cross-link with the + // prototype for the field's type. + // For singular fields, the field is just a pointer which should + // point to the prototype. + *reinterpret_cast(field_ptr) = + factory->GetPrototypeNoLock(field->message_type()); + } + } +} + +Message* DynamicMessage::New() const { + void* new_base = operator new(type_info_->size); + memset(new_base, 0, type_info_->size); + return new(new_base) DynamicMessage(type_info_); +} + +int DynamicMessage::GetCachedSize() const { + return cached_byte_size_; +} + +void DynamicMessage::SetCachedSize(int size) const { + // This is theoretically not thread-compatible, but in practice it works + // because if multiple threads write this simultaneously, they will be + // writing the exact same value. + cached_byte_size_ = size; +} + +Metadata DynamicMessage::GetMetadata() const { + Metadata metadata; + metadata.descriptor = type_info_->type; + metadata.reflection = type_info_->reflection.get(); + return metadata; +} + +// =================================================================== + +struct DynamicMessageFactory::PrototypeMap { + typedef hash_map Map; + Map map_; +}; + +DynamicMessageFactory::DynamicMessageFactory() + : pool_(NULL), delegate_to_generated_factory_(false), + prototypes_(new PrototypeMap) { +} + +DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) + : pool_(pool), delegate_to_generated_factory_(false), + prototypes_(new PrototypeMap) { +} + +DynamicMessageFactory::~DynamicMessageFactory() { + for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin(); + iter != prototypes_->map_.end(); ++iter) { + delete iter->second; + } +} + +const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) { + MutexLock lock(&prototypes_mutex_); + return GetPrototypeNoLock(type); +} + +const Message* DynamicMessageFactory::GetPrototypeNoLock( + const Descriptor* type) { + if (delegate_to_generated_factory_ && + type->file()->pool() == DescriptorPool::generated_pool()) { + return MessageFactory::generated_factory()->GetPrototype(type); + } + + const DynamicMessage::TypeInfo** target = &prototypes_->map_[type]; + if (*target != NULL) { + // Already exists. + return (*target)->prototype; + } + + DynamicMessage::TypeInfo* type_info = new DynamicMessage::TypeInfo; + *target = type_info; + + type_info->type = type; + type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_; + type_info->factory = this; + + // We need to construct all the structures passed to + // GeneratedMessageReflection's constructor. This includes: + // - A block of memory that contains space for all the message's fields. + // - An array of integers indicating the byte offset of each field within + // this block. + // - A big bitfield containing a bit for each field indicating whether + // or not that field is set. + + // Compute size and offsets. + int* offsets = new int[type->field_count()]; + type_info->offsets.reset(offsets); + + // Decide all field offsets by packing in order. + // We place the DynamicMessage object itself at the beginning of the allocated + // space. + int size = sizeof(DynamicMessage); + size = AlignOffset(size); + + // Next the has_bits, which is an array of uint32s. + type_info->has_bits_offset = size; + int has_bits_array_size = + DivideRoundingUp(type->field_count(), bitsizeof(uint32)); + size += has_bits_array_size * sizeof(uint32); + size = AlignOffset(size); + + // The ExtensionSet, if any. + if (type->extension_range_count() > 0) { + type_info->extensions_offset = size; + size += sizeof(ExtensionSet); + size = AlignOffset(size); + } else { + // No extensions. + type_info->extensions_offset = -1; + } + + // All the fields. + for (int i = 0; i < type->field_count(); i++) { + // Make sure field is aligned to avoid bus errors. + int field_size = FieldSpaceUsed(type->field(i)); + size = AlignTo(size, min(kSafeAlignment, field_size)); + offsets[i] = size; + size += field_size; + } + + // Add the UnknownFieldSet to the end. + size = AlignOffset(size); + type_info->unknown_fields_offset = size; + size += sizeof(UnknownFieldSet); + + // Align the final size to make sure no clever allocators think that + // alignment is not necessary. + size = AlignOffset(size); + type_info->size = size; + + // Allocate the prototype. + void* base = operator new(size); + memset(base, 0, size); + DynamicMessage* prototype = new(base) DynamicMessage(type_info); + type_info->prototype = prototype; + + // Construct the reflection object. + type_info->reflection.reset( + new GeneratedMessageReflection( + type_info->type, + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_offset, + type_info->unknown_fields_offset, + type_info->extensions_offset, + type_info->pool, + this, + type_info->size)); + + // Cross link prototypes. + prototype->CrossLinkPrototypes(); + + return prototype; +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.h new file mode 100644 index 000000000..b3d1e5d28 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message.h @@ -0,0 +1,136 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Defines an implementation of Message which can emulate types which are not +// known at compile-time. + +#ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ +#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ + +#include +#include + +namespace google { +namespace protobuf { + +// Defined in other files. +class Descriptor; // descriptor.h +class DescriptorPool; // descriptor.h + +// Constructs implementations of Message which can emulate types which are not +// known at compile-time. +// +// Sometimes you want to be able to manipulate protocol types that you don't +// know about at compile time. It would be nice to be able to construct +// a Message object which implements the message type given by any arbitrary +// Descriptor. DynamicMessage provides this. +// +// As it turns out, a DynamicMessage needs to construct extra +// information about its type in order to operate. Most of this information +// can be shared between all DynamicMessages of the same type. But, caching +// this information in some sort of global map would be a bad idea, since +// the cached information for a particular descriptor could outlive the +// descriptor itself. To avoid this problem, DynamicMessageFactory +// encapsulates this "cache". All DynamicMessages of the same type created +// from the same factory will share the same support data. Any Descriptors +// used with a particular factory must outlive the factory. +class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { + public: + // Construct a DynamicMessageFactory that will search for extensions in + // the DescriptorPool in which the extendee is defined. + DynamicMessageFactory(); + + // Construct a DynamicMessageFactory that will search for extensions in + // the given DescriptorPool. + // + // DEPRECATED: Use CodedInputStream::SetExtensionRegistry() to tell the + // parser to look for extensions in an alternate pool. However, note that + // this is almost never what you want to do. Almost all users should use + // the zero-arg constructor. + DynamicMessageFactory(const DescriptorPool* pool); + + ~DynamicMessageFactory(); + + // Call this to tell the DynamicMessageFactory that if it is given a + // Descriptor d for which: + // d->file()->pool() == DescriptorPool::generated_pool(), + // then it should delegate to MessageFactory::generated_factory() instead + // of constructing a dynamic implementation of the message. In theory there + // is no down side to doing this, so it may become the default in the future. + void SetDelegateToGeneratedFactory(bool enable) { + delegate_to_generated_factory_ = enable; + } + + // implements MessageFactory --------------------------------------- + + // Given a Descriptor, constructs the default (prototype) Message of that + // type. You can then call that message's New() method to construct a + // mutable message of that type. + // + // Calling this method twice with the same Descriptor returns the same + // object. The returned object remains property of the factory and will + // be destroyed when the factory is destroyed. Also, any objects created + // by calling the prototype's New() method share some data with the + // prototype, so these must be destroyed before the DynamicMessageFactory + // is destroyed. + // + // The given descriptor must outlive the returned message, and hence must + // outlive the DynamicMessageFactory. + // + // The method is thread-safe. + const Message* GetPrototype(const Descriptor* type); + + private: + const DescriptorPool* pool_; + bool delegate_to_generated_factory_; + + // This struct just contains a hash_map. We can't #include from + // this header due to hacks needed for hash_map portability in the open source + // release. Namely, stubs/hash.h, which defines hash_map portably, is not a + // public header (for good reason), but dynamic_message.h is, and public + // headers may only #include other public headers. + struct PrototypeMap; + scoped_ptr prototypes_; + mutable Mutex prototypes_mutex_; + + friend class DynamicMessage; + const Message* GetPrototypeNoLock(const Descriptor* type); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message_unittest.cc new file mode 100644 index 000000000..e46159702 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/dynamic_message_unittest.cc @@ -0,0 +1,166 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Since the reflection interface for DynamicMessage is implemented by +// GenericMessageReflection, the only thing we really have to test is +// that DynamicMessage correctly sets up the information that +// GenericMessageReflection needs to use. So, we focus on that in this +// test. Other tests, such as generic_message_reflection_unittest and +// reflection_ops_unittest, cover the rest of the functionality used by +// DynamicMessage. + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { + +class DynamicMessageTest : public testing::Test { + protected: + DescriptorPool pool_; + DynamicMessageFactory factory_; + const Descriptor* descriptor_; + const Message* prototype_; + const Descriptor* extensions_descriptor_; + const Message* extensions_prototype_; + const Descriptor* packed_descriptor_; + const Message* packed_prototype_; + + DynamicMessageTest(): factory_(&pool_) {} + + virtual void SetUp() { + // We want to make sure that DynamicMessage works (particularly with + // extensions) even if we use descriptors that are *not* from compiled-in + // types, so we make copies of the descriptors for unittest.proto and + // unittest_import.proto. + FileDescriptorProto unittest_file; + FileDescriptorProto unittest_import_file; + FileDescriptorProto unittest_import_public_file; + + unittest::TestAllTypes::descriptor()->file()->CopyTo(&unittest_file); + unittest_import::ImportMessage::descriptor()->file()->CopyTo( + &unittest_import_file); + unittest_import::PublicImportMessage::descriptor()->file()->CopyTo( + &unittest_import_public_file); + + ASSERT_TRUE(pool_.BuildFile(unittest_import_public_file) != NULL); + ASSERT_TRUE(pool_.BuildFile(unittest_import_file) != NULL); + ASSERT_TRUE(pool_.BuildFile(unittest_file) != NULL); + + descriptor_ = pool_.FindMessageTypeByName("protobuf_unittest.TestAllTypes"); + ASSERT_TRUE(descriptor_ != NULL); + prototype_ = factory_.GetPrototype(descriptor_); + + extensions_descriptor_ = + pool_.FindMessageTypeByName("protobuf_unittest.TestAllExtensions"); + ASSERT_TRUE(extensions_descriptor_ != NULL); + extensions_prototype_ = factory_.GetPrototype(extensions_descriptor_); + + packed_descriptor_ = + pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); + ASSERT_TRUE(packed_descriptor_ != NULL); + packed_prototype_ = factory_.GetPrototype(packed_descriptor_); + } +}; + +TEST_F(DynamicMessageTest, Descriptor) { + // Check that the descriptor on the DynamicMessage matches the descriptor + // passed to GetPrototype(). + EXPECT_EQ(prototype_->GetDescriptor(), descriptor_); +} + +TEST_F(DynamicMessageTest, OnePrototype) { + // Check that requesting the same prototype twice produces the same object. + EXPECT_EQ(prototype_, factory_.GetPrototype(descriptor_)); +} + +TEST_F(DynamicMessageTest, Defaults) { + // Check that all default values are set correctly in the initial message. + TestUtil::ReflectionTester reflection_tester(descriptor_); + reflection_tester.ExpectClearViaReflection(*prototype_); +} + +TEST_F(DynamicMessageTest, IndependentOffsets) { + // Check that all fields have independent offsets by setting each + // one to a unique value then checking that they all still have those + // unique values (i.e. they don't stomp each other). + scoped_ptr message(prototype_->New()); + TestUtil::ReflectionTester reflection_tester(descriptor_); + + reflection_tester.SetAllFieldsViaReflection(message.get()); + reflection_tester.ExpectAllFieldsSetViaReflection(*message); +} + +TEST_F(DynamicMessageTest, Extensions) { + // Check that extensions work. + scoped_ptr message(extensions_prototype_->New()); + TestUtil::ReflectionTester reflection_tester(extensions_descriptor_); + + reflection_tester.SetAllFieldsViaReflection(message.get()); + reflection_tester.ExpectAllFieldsSetViaReflection(*message); +} + +TEST_F(DynamicMessageTest, PackedFields) { + // Check that packed fields work properly. + scoped_ptr message(packed_prototype_->New()); + TestUtil::ReflectionTester reflection_tester(packed_descriptor_); + + reflection_tester.SetPackedFieldsViaReflection(message.get()); + reflection_tester.ExpectPackedFieldsSetViaReflection(*message); +} + +TEST_F(DynamicMessageTest, SpaceUsed) { + // Test that SpaceUsed() works properly + + // Since we share the implementation with generated messages, we don't need + // to test very much here. Just make sure it appears to be working. + + scoped_ptr message(prototype_->New()); + TestUtil::ReflectionTester reflection_tester(descriptor_); + + int initial_space_used = message->SpaceUsed(); + + reflection_tester.SetAllFieldsViaReflection(message.get()); + EXPECT_LT(initial_space_used, message->SpaceUsed()); +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.cc new file mode 100644 index 000000000..2cbba8f54 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.cc @@ -0,0 +1,1461 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +inline WireFormatLite::FieldType real_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast(type); +} + +inline WireFormatLite::CppType cpp_type(FieldType type) { + return WireFormatLite::FieldTypeToCppType(real_type(type)); +} + +// Registry stuff. +typedef hash_map, + ExtensionInfo> ExtensionRegistry; +ExtensionRegistry* registry_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(registry_init_); + +void DeleteRegistry() { + delete registry_; + registry_ = NULL; +} + +void InitRegistry() { + registry_ = new ExtensionRegistry; + OnShutdown(&DeleteRegistry); +} + +// This function is only called at startup, so there is no need for thread- +// safety. +void Register(const MessageLite* containing_type, + int number, ExtensionInfo info) { + ::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); + + if (!InsertIfNotPresent(registry_, make_pair(containing_type, number), + info)) { + GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" + << containing_type->GetTypeName() + << "\", field number " << number << "."; + } +} + +const ExtensionInfo* FindRegisteredExtension( + const MessageLite* containing_type, int number) { + return (registry_ == NULL) ? NULL : + FindOrNull(*registry_, make_pair(containing_type, number)); +} + +} // namespace + +ExtensionFinder::~ExtensionFinder() {} + +bool GeneratedExtensionFinder::Find(int number, ExtensionInfo* output) { + const ExtensionInfo* extension = + FindRegisteredExtension(containing_type_, number); + if (extension == NULL) { + return false; + } else { + *output = *extension; + return true; + } +} + +void ExtensionSet::RegisterExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed) { + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_ENUM); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_MESSAGE); + GOOGLE_CHECK_NE(type, WireFormatLite::TYPE_GROUP); + ExtensionInfo info(type, is_repeated, is_packed); + Register(containing_type, number, info); +} + +static bool CallNoArgValidityFunc(const void* arg, int number) { + // Note: Must use C-style cast here rather than reinterpret_cast because + // the C++ standard at one point did not allow casts between function and + // data pointers and some compilers enforce this for C++-style casts. No + // compiler enforces it for C-style casts since lots of C-style code has + // relied on these kinds of casts for a long time, despite being + // technically undefined. See: + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195 + // Also note: Some compilers do not allow function pointers to be "const". + // Which makes sense, I suppose, because it's meaningless. + return ((EnumValidityFunc*)arg)(number); +} + +void ExtensionSet::RegisterEnumExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed, + EnumValidityFunc* is_valid) { + GOOGLE_CHECK_EQ(type, WireFormatLite::TYPE_ENUM); + ExtensionInfo info(type, is_repeated, is_packed); + info.enum_validity_check.func = CallNoArgValidityFunc; + // See comment in CallNoArgValidityFunc() about why we use a c-style cast. + info.enum_validity_check.arg = (void*)is_valid; + Register(containing_type, number, info); +} + +void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed, + const MessageLite* prototype) { + GOOGLE_CHECK(type == WireFormatLite::TYPE_MESSAGE || + type == WireFormatLite::TYPE_GROUP); + ExtensionInfo info(type, is_repeated, is_packed); + info.message_prototype = prototype; + Register(containing_type, number, info); +} + + +// =================================================================== +// Constructors and basic methods. + +ExtensionSet::ExtensionSet() {} + +ExtensionSet::~ExtensionSet() { + for (map::iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + iter->second.Free(); + } +} + +// Defined in extension_set_heavy.cc. +// void ExtensionSet::AppendToList(const Descriptor* containing_type, +// const DescriptorPool* pool, +// vector* output) const + +bool ExtensionSet::Has(int number) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) return false; + GOOGLE_DCHECK(!iter->second.is_repeated); + return !iter->second.is_cleared; +} + +int ExtensionSet::NumExtensions() const { + int result = 0; + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + if (!iter->second.is_cleared) { + ++result; + } + } + return result; +} + +int ExtensionSet::ExtensionSize(int number) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) return false; + return iter->second.GetSize(); +} + +FieldType ExtensionSet::ExtensionType(int number) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; + return 0; + } + if (iter->second.is_cleared) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; + } + return iter->second.type; +} + +void ExtensionSet::ClearExtension(int number) { + map::iterator iter = extensions_.find(number); + if (iter == extensions_.end()) return; + iter->second.Clear(); +} + +// =================================================================== +// Field accessors + +namespace { + +enum Cardinality { + REPEATED, + OPTIONAL +}; + +} // namespace + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? REPEATED : OPTIONAL, LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), WireFormatLite::CPPTYPE_##CPPTYPE) + +// ------------------------------------------------------------------- +// Primitives + +#define PRIMITIVE_ACCESSORS(UPPERCASE, LOWERCASE, CAMELCASE) \ + \ +LOWERCASE ExtensionSet::Get##CAMELCASE(int number, \ + LOWERCASE default_value) const { \ + map::const_iterator iter = extensions_.find(number); \ + if (iter == extensions_.end() || iter->second.is_cleared) { \ + return default_value; \ + } else { \ + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, UPPERCASE); \ + return iter->second.LOWERCASE##_value; \ + } \ +} \ + \ +void ExtensionSet::Set##CAMELCASE(int number, FieldType type, \ + LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = false; \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, UPPERCASE); \ + } \ + extension->is_cleared = false; \ + extension->LOWERCASE##_value = value; \ +} \ + \ +LOWERCASE ExtensionSet::GetRepeated##CAMELCASE(int number, int index) const { \ + map::const_iterator iter = extensions_.find(number); \ + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \ + return iter->second.repeated_##LOWERCASE##_value->Get(index); \ +} \ + \ +void ExtensionSet::SetRepeated##CAMELCASE( \ + int number, int index, LOWERCASE value) { \ + map::iterator iter = extensions_.find(number); \ + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; \ + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, UPPERCASE); \ + iter->second.repeated_##LOWERCASE##_value->Set(index, value); \ +} \ + \ +void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \ + bool packed, LOWERCASE value, \ + const FieldDescriptor* descriptor) { \ + Extension* extension; \ + if (MaybeNewExtension(number, descriptor, &extension)) { \ + extension->type = type; \ + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \ + extension->is_repeated = true; \ + extension->is_packed = packed; \ + extension->repeated_##LOWERCASE##_value = new RepeatedField(); \ + } else { \ + GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \ + GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ + } \ + extension->repeated_##LOWERCASE##_value->Add(value); \ +} + +PRIMITIVE_ACCESSORS( INT32, int32, Int32) +PRIMITIVE_ACCESSORS( INT64, int64, Int64) +PRIMITIVE_ACCESSORS(UINT32, uint32, UInt32) +PRIMITIVE_ACCESSORS(UINT64, uint64, UInt64) +PRIMITIVE_ACCESSORS( FLOAT, float, Float) +PRIMITIVE_ACCESSORS(DOUBLE, double, Double) +PRIMITIVE_ACCESSORS( BOOL, bool, Bool) + +#undef PRIMITIVE_ACCESSORS + +void* ExtensionSet::MutableRawRepeatedField(int number) { + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + map::const_iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number; + return iter->second.repeated_int32_value; +} + +// ------------------------------------------------------------------- +// Enums + +int ExtensionSet::GetEnum(int number, int default_value) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end() || iter->second.is_cleared) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, ENUM); + return iter->second.enum_value; + } +} + +void ExtensionSet::SetEnum(int number, FieldType type, int value, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); + extension->is_repeated = false; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, ENUM); + } + extension->is_cleared = false; + extension->enum_value = value; +} + +int ExtensionSet::GetRepeatedEnum(int number, int index) const { + map::const_iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM); + return iter->second.repeated_enum_value->Get(index); +} + +void ExtensionSet::SetRepeatedEnum(int number, int index, int value) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, ENUM); + iter->second.repeated_enum_value->Set(index, value); +} + +void ExtensionSet::AddEnum(int number, FieldType type, + bool packed, int value, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM); + extension->is_repeated = true; + extension->is_packed = packed; + extension->repeated_enum_value = new RepeatedField(); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM); + GOOGLE_DCHECK_EQ(extension->is_packed, packed); + } + extension->repeated_enum_value->Add(value); +} + +// ------------------------------------------------------------------- +// Strings + +const string& ExtensionSet::GetString(int number, + const string& default_value) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end() || iter->second.is_cleared) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, STRING); + return *iter->second.string_value; + } +} + +string* ExtensionSet::MutableString(int number, FieldType type, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); + extension->is_repeated = false; + extension->string_value = new string; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING); + } + extension->is_cleared = false; + return extension->string_value; +} + +const string& ExtensionSet::GetRepeatedString(int number, int index) const { + map::const_iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING); + return iter->second.repeated_string_value->Get(index); +} + +string* ExtensionSet::MutableRepeatedString(int number, int index) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, STRING); + return iter->second.repeated_string_value->Mutable(index); +} + +string* ExtensionSet::AddString(int number, FieldType type, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING); + extension->is_repeated = true; + extension->is_packed = false; + extension->repeated_string_value = new RepeatedPtrField(); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING); + } + return extension->repeated_string_value->Add(); +} + +// ------------------------------------------------------------------- +// Messages + +const MessageLite& ExtensionSet::GetMessage( + int number, const MessageLite& default_value) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + // Not present. Return the default value. + return default_value; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + if (iter->second.is_lazy) { + return iter->second.lazymessage_value->GetMessage(default_value); + } else { + return *iter->second.message_value; + } + } +} + +// Defined in extension_set_heavy.cc. +// const MessageLite& ExtensionSet::GetMessage(int number, +// const Descriptor* message_type, +// MessageFactory* factory) const + +MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, + const MessageLite& prototype, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = prototype.New(); + extension->is_cleared = false; + return extension->message_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage(prototype); + } else { + return extension->message_value; + } + } +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::MutableMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) + +void ExtensionSet::SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message) { + if (message == NULL) { + ClearExtension(number); + return; + } + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = message; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + extension->lazymessage_value->SetAllocatedMessage(message); + } else { + delete extension->message_value; + extension->message_value = message; + } + } + extension->is_cleared = false; +} + +MessageLite* ExtensionSet::ReleaseMessage(int number, + const MessageLite& prototype) { + map::iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + // Not present. Return NULL. + return NULL; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + MessageLite* ret = NULL; + if (iter->second.is_lazy) { + ret = iter->second.lazymessage_value->ReleaseMessage(prototype); + delete iter->second.lazymessage_value; + } else { + ret = iter->second.message_value; + } + extensions_.erase(number); + return ret; + } +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, +// MessageFactory* factory); + +const MessageLite& ExtensionSet::GetRepeatedMessage( + int number, int index) const { + map::const_iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); + return iter->second.repeated_message_value->Get(index); +} + +MessageLite* ExtensionSet::MutableRepeatedMessage(int number, int index) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + GOOGLE_DCHECK_TYPE(iter->second, REPEATED, MESSAGE); + return iter->second.repeated_message_value->Mutable(index); +} + +MessageLite* ExtensionSet::AddMessage(int number, FieldType type, + const MessageLite& prototype, + const FieldDescriptor* descriptor) { + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = true; + extension->repeated_message_value = + new RepeatedPtrField(); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + } + + // RepeatedPtrField does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = extension->repeated_message_value + ->AddFromCleared >(); + if (result == NULL) { + result = prototype.New(); + extension->repeated_message_value->AddAllocated(result); + } + return result; +} + +// Defined in extension_set_heavy.cc. +// MessageLite* ExtensionSet::AddMessage(int number, FieldType type, +// const Descriptor* message_type, +// MessageFactory* factory) + +#undef GOOGLE_DCHECK_TYPE + +void ExtensionSet::RemoveLast(int number) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + + Extension* extension = &iter->second; + GOOGLE_DCHECK(extension->is_repeated); + + switch(cpp_type(extension->type)) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->RemoveLast(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->RemoveLast(); + break; + } +} + +MessageLite* ExtensionSet::ReleaseLast(int number) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + + Extension* extension = &iter->second; + GOOGLE_DCHECK(extension->is_repeated); + GOOGLE_DCHECK(cpp_type(extension->type) == WireFormatLite::CPPTYPE_MESSAGE); + return extension->repeated_message_value->ReleaseLast(); +} + +void ExtensionSet::SwapElements(int number, int index1, int index2) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter != extensions_.end()) << "Index out-of-bounds (field is empty)."; + + Extension* extension = &iter->second; + GOOGLE_DCHECK(extension->is_repeated); + + switch(cpp_type(extension->type)) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value->SwapElements(index1, index2); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value->SwapElements(index1, index2); + break; + } +} + +// =================================================================== + +void ExtensionSet::Clear() { + for (map::iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + iter->second.Clear(); + } +} + +void ExtensionSet::MergeFrom(const ExtensionSet& other) { + for (map::const_iterator iter = other.extensions_.begin(); + iter != other.extensions_.end(); ++iter) { + const Extension& other_extension = iter->second; + + if (other_extension.is_repeated) { + Extension* extension; + bool is_new = MaybeNewExtension(iter->first, other_extension.descriptor, + &extension); + if (is_new) { + // Extension did not already exist in set. + extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; + extension->is_repeated = true; + } else { + GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed); + GOOGLE_DCHECK(extension->is_repeated); + } + + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + if (is_new) { \ + extension->repeated_##LOWERCASE##_value = \ + new REPEATED_TYPE; \ + } \ + extension->repeated_##LOWERCASE##_value->MergeFrom( \ + *other_extension.repeated_##LOWERCASE##_value); \ + break; + + HANDLE_TYPE( INT32, int32, RepeatedField < int32>); + HANDLE_TYPE( INT64, int64, RepeatedField < int64>); + HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>); + HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>); + HANDLE_TYPE( FLOAT, float, RepeatedField < float>); + HANDLE_TYPE( DOUBLE, double, RepeatedField < double>); + HANDLE_TYPE( BOOL, bool, RepeatedField < bool>); + HANDLE_TYPE( ENUM, enum, RepeatedField < int>); + HANDLE_TYPE( STRING, string, RepeatedPtrField< string>); +#undef HANDLE_TYPE + + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_new) { + extension->repeated_message_value = + new RepeatedPtrField(); + } + // We can't call RepeatedPtrField::MergeFrom() because + // it would attempt to allocate new objects. + RepeatedPtrField* other_repeated_message = + other_extension.repeated_message_value; + for (int i = 0; i < other_repeated_message->size(); i++) { + const MessageLite& other_message = other_repeated_message->Get(i); + MessageLite* target = extension->repeated_message_value + ->AddFromCleared >(); + if (target == NULL) { + target = other_message.New(); + extension->repeated_message_value->AddAllocated(target); + } + target->CheckTypeAndMergeFrom(other_message); + } + break; + } + } else { + if (!other_extension.is_cleared) { + switch (cpp_type(other_extension.type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + Set##CAMELCASE(iter->first, other_extension.type, \ + other_extension.LOWERCASE##_value, \ + other_extension.descriptor); \ + break; + + HANDLE_TYPE( INT32, int32, Int32); + HANDLE_TYPE( INT64, int64, Int64); + HANDLE_TYPE(UINT32, uint32, UInt32); + HANDLE_TYPE(UINT64, uint64, UInt64); + HANDLE_TYPE( FLOAT, float, Float); + HANDLE_TYPE(DOUBLE, double, Double); + HANDLE_TYPE( BOOL, bool, Bool); + HANDLE_TYPE( ENUM, enum, Enum); +#undef HANDLE_TYPE + case WireFormatLite::CPPTYPE_STRING: + SetString(iter->first, other_extension.type, + *other_extension.string_value, + other_extension.descriptor); + break; + case WireFormatLite::CPPTYPE_MESSAGE: { + Extension* extension; + bool is_new = MaybeNewExtension(iter->first, + other_extension.descriptor, + &extension); + if (is_new) { + extension->type = other_extension.type; + extension->is_packed = other_extension.is_packed; + extension->is_repeated = false; + if (other_extension.is_lazy) { + extension->is_lazy = true; + extension->lazymessage_value = + other_extension.lazymessage_value->New(); + extension->lazymessage_value->MergeFrom( + *other_extension.lazymessage_value); + } else { + extension->is_lazy = false; + extension->message_value = + other_extension.message_value->New(); + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } else { + GOOGLE_DCHECK_EQ(extension->type, other_extension.type); + GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed); + GOOGLE_DCHECK(!extension->is_repeated); + if (other_extension.is_lazy) { + if (extension->is_lazy) { + extension->lazymessage_value->MergeFrom( + *other_extension.lazymessage_value); + } else { + extension->message_value->CheckTypeAndMergeFrom( + other_extension.lazymessage_value->GetMessage( + *extension->message_value)); + } + } else { + if (extension->is_lazy) { + extension->lazymessage_value->MutableMessage( + *other_extension.message_value)->CheckTypeAndMergeFrom( + *other_extension.message_value); + } else { + extension->message_value->CheckTypeAndMergeFrom( + *other_extension.message_value); + } + } + } + extension->is_cleared = false; + break; + } + } + } + } + } +} + +void ExtensionSet::Swap(ExtensionSet* x) { + extensions_.swap(x->extensions_); +} + +bool ExtensionSet::IsInitialized() const { + // Extensions are never required. However, we need to check that all + // embedded messages are initialized. + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + const Extension& extension = iter->second; + if (cpp_type(extension.type) == WireFormatLite::CPPTYPE_MESSAGE) { + if (extension.is_repeated) { + for (int i = 0; i < extension.repeated_message_value->size(); i++) { + if (!extension.repeated_message_value->Get(i).IsInitialized()) { + return false; + } + } + } else { + if (!extension.is_cleared) { + if (extension.is_lazy) { + if (!extension.lazymessage_value->IsInitialized()) return false; + } else { + if (!extension.message_value->IsInitialized()) return false; + } + } + } + } + } + + return true; +} + +bool ExtensionSet::FindExtensionInfoFromTag( + uint32 tag, ExtensionFinder* extension_finder, + int* field_number, ExtensionInfo* extension) { + *field_number = WireFormatLite::GetTagFieldNumber(tag); + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + bool is_unknown; + if (!extension_finder->Find(*field_number, extension)) { + is_unknown = true; + } else if (extension->is_packed) { + is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + } else { + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type(extension->type)); + is_unknown = (wire_type != expected_wire_type); + } + return !is_unknown; +} + +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + int number; + ExtensionInfo extension; + if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) { + return field_skipper->SkipField(input, tag); + } else { + return ParseFieldWithExtensionInfo(number, extension, input, field_skipper); + } +} + +bool ExtensionSet::ParseFieldWithExtensionInfo( + int number, const ExtensionInfo& extension, + io::CodedInputStream* input, + FieldSkipper* field_skipper) { + if (extension.is_packed) { + uint32 size; + if (!input->ReadVarint32(&size)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(size); + + switch (extension.type) { +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + while (input->BytesUntilLimit() > 0) { \ + CPP_LOWERCASE value; \ + if (!WireFormatLite::ReadPrimitive< \ + CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ + input, &value)) return false; \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + true, value, extension.descriptor); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, Int32, int32); + HANDLE_TYPE( SINT64, Int64, int64); + HANDLE_TYPE( FIXED32, UInt32, uint32); + HANDLE_TYPE( FIXED64, UInt64, uint64); + HANDLE_TYPE(SFIXED32, Int32, int32); + HANDLE_TYPE(SFIXED64, Int64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_ENUM: + while (input->BytesUntilLimit() > 0) { + int value; + if (!WireFormatLite::ReadPrimitive( + input, &value)) return false; + if (extension.enum_validity_check.func( + extension.enum_validity_check.arg, value)) { + AddEnum(number, WireFormatLite::TYPE_ENUM, true, value, + extension.descriptor); + } + } + break; + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + + input->PopLimit(limit); + } else { + switch (extension.type) { +#define HANDLE_TYPE(UPPERCASE, CPP_CAMELCASE, CPP_LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: { \ + CPP_LOWERCASE value; \ + if (!WireFormatLite::ReadPrimitive< \ + CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ + input, &value)) return false; \ + if (extension.is_repeated) { \ + Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ + false, value, extension.descriptor); \ + } else { \ + Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ + extension.descriptor); \ + } \ + } break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, Int32, int32); + HANDLE_TYPE( SINT64, Int64, int64); + HANDLE_TYPE( FIXED32, UInt32, uint32); + HANDLE_TYPE( FIXED64, UInt64, uint64); + HANDLE_TYPE(SFIXED32, Int32, int32); + HANDLE_TYPE(SFIXED64, Int64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_ENUM: { + int value; + if (!WireFormatLite::ReadPrimitive( + input, &value)) return false; + + if (!extension.enum_validity_check.func( + extension.enum_validity_check.arg, value)) { + // Invalid value. Treat as unknown. + field_skipper->SkipUnknownEnum(number, value); + } else if (extension.is_repeated) { + AddEnum(number, WireFormatLite::TYPE_ENUM, false, value, + extension.descriptor); + } else { + SetEnum(number, WireFormatLite::TYPE_ENUM, value, + extension.descriptor); + } + break; + } + + case WireFormatLite::TYPE_STRING: { + string* value = extension.is_repeated ? + AddString(number, WireFormatLite::TYPE_STRING, extension.descriptor) : + MutableString(number, WireFormatLite::TYPE_STRING, + extension.descriptor); + if (!WireFormatLite::ReadString(input, value)) return false; + break; + } + + case WireFormatLite::TYPE_BYTES: { + string* value = extension.is_repeated ? + AddString(number, WireFormatLite::TYPE_BYTES, extension.descriptor) : + MutableString(number, WireFormatLite::TYPE_BYTES, + extension.descriptor); + if (!WireFormatLite::ReadBytes(input, value)) return false; + break; + } + + case WireFormatLite::TYPE_GROUP: { + MessageLite* value = extension.is_repeated ? + AddMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_prototype, extension.descriptor) : + MutableMessage(number, WireFormatLite::TYPE_GROUP, + *extension.message_prototype, extension.descriptor); + if (!WireFormatLite::ReadGroup(number, input, value)) return false; + break; + } + + case WireFormatLite::TYPE_MESSAGE: { + MessageLite* value = extension.is_repeated ? + AddMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_prototype, extension.descriptor) : + MutableMessage(number, WireFormatLite::TYPE_MESSAGE, + *extension.message_prototype, extension.descriptor); + if (!WireFormatLite::ReadMessage(input, value)) return false; + break; + } + } + } + + return true; +} + +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type) { + FieldSkipper skipper; + GeneratedExtensionFinder finder(containing_type); + return ParseField(tag, input, &finder, &skipper); +} + +// Defined in extension_set_heavy.cc. +// bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, +// const MessageLite* containing_type, +// UnknownFieldSet* unknown_fields) + +// Defined in extension_set_heavy.cc. +// bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, +// const MessageLite* containing_type, +// UnknownFieldSet* unknown_fields); + +void ExtensionSet::SerializeWithCachedSizes( + int start_field_number, int end_field_number, + io::CodedOutputStream* output) const { + map::const_iterator iter; + for (iter = extensions_.lower_bound(start_field_number); + iter != extensions_.end() && iter->first < end_field_number; + ++iter) { + iter->second.SerializeFieldWithCachedSizes(iter->first, output); + } +} + +int ExtensionSet::ByteSize() const { + int total_size = 0; + + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + total_size += iter->second.ByteSize(iter->first); + } + + return total_size; +} + +// Defined in extension_set_heavy.cc. +// int ExtensionSet::SpaceUsedExcludingSelf() const + +bool ExtensionSet::MaybeNewExtension(int number, + const FieldDescriptor* descriptor, + Extension** result) { + pair::iterator, bool> insert_result = + extensions_.insert(make_pair(number, Extension())); + *result = &insert_result.first->second; + (*result)->descriptor = descriptor; + return insert_result.second; +} + +// =================================================================== +// Methods of ExtensionSet::Extension + +void ExtensionSet::Extension::Clear() { + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + repeated_##LOWERCASE##_value->Clear(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE( UINT32, uint32); + HANDLE_TYPE( UINT64, uint64); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( DOUBLE, double); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, enum); + HANDLE_TYPE( STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + } else { + if (!is_cleared) { + switch (cpp_type(type)) { + case WireFormatLite::CPPTYPE_STRING: + string_value->clear(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_lazy) { + lazymessage_value->Clear(); + } else { + message_value->Clear(); + } + break; + default: + // No need to do anything. Get*() will return the default value + // as long as is_cleared is true and Set*() will overwrite the + // previous value. + break; + } + + is_cleared = true; + } + } +} + +void ExtensionSet::Extension::SerializeFieldWithCachedSizes( + int number, + io::CodedOutputStream* output) const { + if (is_repeated) { + if (is_packed) { + if (cached_size == 0) return; + + WireFormatLite::WriteTag(number, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(cached_size); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + WireFormatLite::Write##CAMELCASE##NoTag( \ + repeated_##LOWERCASE##_value->Get(i), output); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); + HANDLE_TYPE( ENUM, Enum, enum); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + WireFormatLite::Write##CAMELCASE(number, \ + repeated_##LOWERCASE##_value->Get(i), output); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); + HANDLE_TYPE( STRING, String, string); + HANDLE_TYPE( BYTES, Bytes, string); + HANDLE_TYPE( ENUM, Enum, enum); + HANDLE_TYPE( GROUP, Group, message); + HANDLE_TYPE( MESSAGE, Message, message); +#undef HANDLE_TYPE + } + } + } else if (!is_cleared) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + WireFormatLite::Write##CAMELCASE(number, VALUE, output); \ + break + + HANDLE_TYPE( INT32, Int32, int32_value); + HANDLE_TYPE( INT64, Int64, int64_value); + HANDLE_TYPE( UINT32, UInt32, uint32_value); + HANDLE_TYPE( UINT64, UInt64, uint64_value); + HANDLE_TYPE( SINT32, SInt32, int32_value); + HANDLE_TYPE( SINT64, SInt64, int64_value); + HANDLE_TYPE( FIXED32, Fixed32, uint32_value); + HANDLE_TYPE( FIXED64, Fixed64, uint64_value); + HANDLE_TYPE(SFIXED32, SFixed32, int32_value); + HANDLE_TYPE(SFIXED64, SFixed64, int64_value); + HANDLE_TYPE( FLOAT, Float, float_value); + HANDLE_TYPE( DOUBLE, Double, double_value); + HANDLE_TYPE( BOOL, Bool, bool_value); + HANDLE_TYPE( STRING, String, *string_value); + HANDLE_TYPE( BYTES, Bytes, *string_value); + HANDLE_TYPE( ENUM, Enum, enum_value); + HANDLE_TYPE( GROUP, Group, *message_value); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_MESSAGE: + if (is_lazy) { + lazymessage_value->WriteMessage(number, output); + } else { + WireFormatLite::WriteMessage(number, *message_value, output); + } + break; + } + } +} + +int ExtensionSet::Extension::ByteSize(int number) const { + int result = 0; + + if (is_repeated) { + if (is_packed) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( ENUM, Enum, enum); +#undef HANDLE_TYPE + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size * \ + repeated_##LOWERCASE##_value->size(); \ + break + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + + cached_size = result; + if (result > 0) { + result += io::CodedOutputStream::VarintSize32(result); + result += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(number, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + } + } else { + int tag_size = WireFormatLite::TagSize(number, real_type(type)); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += tag_size * repeated_##LOWERCASE##_value->size(); \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + result += WireFormatLite::CAMELCASE##Size( \ + repeated_##LOWERCASE##_value->Get(i)); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( STRING, String, string); + HANDLE_TYPE( BYTES, Bytes, string); + HANDLE_TYPE( ENUM, Enum, enum); + HANDLE_TYPE( GROUP, Group, message); + HANDLE_TYPE( MESSAGE, Message, message); +#undef HANDLE_TYPE + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += (tag_size + WireFormatLite::k##CAMELCASE##Size) * \ + repeated_##LOWERCASE##_value->size(); \ + break + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); +#undef HANDLE_TYPE + } + } + } else if (!is_cleared) { + result += WireFormatLite::TagSize(number, real_type(type)); + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::CAMELCASE##Size(LOWERCASE); \ + break + + HANDLE_TYPE( INT32, Int32, int32_value); + HANDLE_TYPE( INT64, Int64, int64_value); + HANDLE_TYPE( UINT32, UInt32, uint32_value); + HANDLE_TYPE( UINT64, UInt64, uint64_value); + HANDLE_TYPE( SINT32, SInt32, int32_value); + HANDLE_TYPE( SINT64, SInt64, int64_value); + HANDLE_TYPE( STRING, String, *string_value); + HANDLE_TYPE( BYTES, Bytes, *string_value); + HANDLE_TYPE( ENUM, Enum, enum_value); + HANDLE_TYPE( GROUP, Group, *message_value); +#undef HANDLE_TYPE + case WireFormatLite::TYPE_MESSAGE: { + if (is_lazy) { + int size = lazymessage_value->ByteSize(); + result += io::CodedOutputStream::VarintSize32(size) + size; + } else { + result += WireFormatLite::MessageSize(*message_value); + } + break; + } + + // Stuff with fixed size. +#define HANDLE_TYPE(UPPERCASE, CAMELCASE) \ + case WireFormatLite::TYPE_##UPPERCASE: \ + result += WireFormatLite::k##CAMELCASE##Size; \ + break + HANDLE_TYPE( FIXED32, Fixed32); + HANDLE_TYPE( FIXED64, Fixed64); + HANDLE_TYPE(SFIXED32, SFixed32); + HANDLE_TYPE(SFIXED64, SFixed64); + HANDLE_TYPE( FLOAT, Float); + HANDLE_TYPE( DOUBLE, Double); + HANDLE_TYPE( BOOL, Bool); +#undef HANDLE_TYPE + } + } + + return result; +} + +int ExtensionSet::Extension::GetSize() const { + GOOGLE_DCHECK(is_repeated); + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + return repeated_##LOWERCASE##_value->size() + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE( UINT32, uint32); + HANDLE_TYPE( UINT64, uint64); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( DOUBLE, double); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, enum); + HANDLE_TYPE( STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; +} + +void ExtensionSet::Extension::Free() { + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case WireFormatLite::CPPTYPE_##UPPERCASE: \ + delete repeated_##LOWERCASE##_value; \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE( UINT32, uint32); + HANDLE_TYPE( UINT64, uint64); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( DOUBLE, double); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, enum); + HANDLE_TYPE( STRING, string); + HANDLE_TYPE(MESSAGE, message); +#undef HANDLE_TYPE + } + } else { + switch (cpp_type(type)) { + case WireFormatLite::CPPTYPE_STRING: + delete string_value; + break; + case WireFormatLite::CPPTYPE_MESSAGE: + if (is_lazy) { + delete lazymessage_value; + } else { + delete message_value; + } + break; + default: + break; + } + } +} + +// Defined in extension_set_heavy.cc. +// int ExtensionSet::Extension::SpaceUsedExcludingSelf() const + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.h new file mode 100644 index 000000000..df8f1f368 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set.h @@ -0,0 +1,1007 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_EXTENSION_SET_H__ +#define GOOGLE_PROTOBUF_EXTENSION_SET_H__ + +#include +#include +#include +#include + + +#include + +namespace google { + +namespace protobuf { + class Descriptor; // descriptor.h + class FieldDescriptor; // descriptor.h + class DescriptorPool; // descriptor.h + class MessageLite; // message_lite.h + class Message; // message.h + class MessageFactory; // message.h + class UnknownFieldSet; // unknown_field_set.h + namespace io { + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h + } + namespace internal { + class FieldSkipper; // wire_format_lite.h + class RepeatedPtrFieldBase; // repeated_field.h + } + template class RepeatedField; // repeated_field.h + template class RepeatedPtrField; // repeated_field.h +} + +namespace protobuf { +namespace internal { + +// Used to store values of type WireFormatLite::FieldType without having to +// #include wire_format_lite.h. Also, ensures that we use only one byte to +// store these values, which is important to keep the layout of +// ExtensionSet::Extension small. +typedef uint8 FieldType; + +// A function which, given an integer value, returns true if the number +// matches one of the defined values for the corresponding enum type. This +// is used with RegisterEnumExtension, below. +typedef bool EnumValidityFunc(int number); + +// Version of the above which takes an argument. This is needed to deal with +// extensions that are not compiled in. +typedef bool EnumValidityFuncWithArg(const void* arg, int number); + +// Information about a registered extension. +struct ExtensionInfo { + inline ExtensionInfo() {} + inline ExtensionInfo(FieldType type_param, bool isrepeated, bool ispacked) + : type(type_param), is_repeated(isrepeated), is_packed(ispacked), + descriptor(NULL) {} + + FieldType type; + bool is_repeated; + bool is_packed; + + struct EnumValidityCheck { + EnumValidityFuncWithArg* func; + const void* arg; + }; + + union { + EnumValidityCheck enum_validity_check; + const MessageLite* message_prototype; + }; + + // The descriptor for this extension, if one exists and is known. May be + // NULL. Must not be NULL if the descriptor for the extension does not + // live in the same pool as the descriptor for the containing type. + const FieldDescriptor* descriptor; +}; + +// Abstract interface for an object which looks up extension definitions. Used +// when parsing. +class LIBPROTOBUF_EXPORT ExtensionFinder { + public: + virtual ~ExtensionFinder(); + + // Find the extension with the given containing type and number. + virtual bool Find(int number, ExtensionInfo* output) = 0; +}; + +// Implementation of ExtensionFinder which finds extensions defined in .proto +// files which have been compiled into the binary. +class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder { + public: + GeneratedExtensionFinder(const MessageLite* containing_type) + : containing_type_(containing_type) {} + virtual ~GeneratedExtensionFinder() {} + + // Returns true and fills in *output if found, otherwise returns false. + virtual bool Find(int number, ExtensionInfo* output); + + private: + const MessageLite* containing_type_; +}; + +// Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for +// finding extensions from a DescriptorPool. + +// This is an internal helper class intended for use within the protocol buffer +// library and generated classes. Clients should not use it directly. Instead, +// use the generated accessors such as GetExtension() of the class being +// extended. +// +// This class manages extensions for a protocol message object. The +// message's HasExtension(), GetExtension(), MutableExtension(), and +// ClearExtension() methods are just thin wrappers around the embedded +// ExtensionSet. When parsing, if a tag number is encountered which is +// inside one of the message type's extension ranges, the tag is passed +// off to the ExtensionSet for parsing. Etc. +class LIBPROTOBUF_EXPORT ExtensionSet { + public: + ExtensionSet(); + ~ExtensionSet(); + + // These are called at startup by protocol-compiler-generated code to + // register known extensions. The registrations are used by ParseField() + // to look up extensions for parsed field numbers. Note that dynamic parsing + // does not use ParseField(); only protocol-compiler-generated parsing + // methods do. + static void RegisterExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed); + static void RegisterEnumExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed, + EnumValidityFunc* is_valid); + static void RegisterMessageExtension(const MessageLite* containing_type, + int number, FieldType type, + bool is_repeated, bool is_packed, + const MessageLite* prototype); + + // ================================================================= + + // Add all fields which are currently present to the given vector. This + // is useful to implement Reflection::ListFields(). + void AppendToList(const Descriptor* containing_type, + const DescriptorPool* pool, + vector* output) const; + + // ================================================================= + // Accessors + // + // Generated message classes include type-safe templated wrappers around + // these methods. Generally you should use those rather than call these + // directly, unless you are doing low-level memory management. + // + // When calling any of these accessors, the extension number requested + // MUST exist in the DescriptorPool provided to the constructor. Otheriwse, + // the method will fail an assert. Normally, though, you would not call + // these directly; you would either call the generated accessors of your + // message class (e.g. GetExtension()) or you would call the accessors + // of the reflection interface. In both cases, it is impossible to + // trigger this assert failure: the generated accessors only accept + // linked-in extension types as parameters, while the Reflection interface + // requires you to provide the FieldDescriptor describing the extension. + // + // When calling any of these accessors, a protocol-compiler-generated + // implementation of the extension corresponding to the number MUST + // be linked in, and the FieldDescriptor used to refer to it MUST be + // the one generated by that linked-in code. Otherwise, the method will + // die on an assert failure. The message objects returned by the message + // accessors are guaranteed to be of the correct linked-in type. + // + // These methods pretty much match Reflection except that: + // - They're not virtual. + // - They identify fields by number rather than FieldDescriptors. + // - They identify enum values using integers rather than descriptors. + // - Strings provide Mutable() in addition to Set() accessors. + + bool Has(int number) const; + int ExtensionSize(int number) const; // Size of a repeated extension. + int NumExtensions() const; // The number of extensions + FieldType ExtensionType(int number) const; + void ClearExtension(int number); + + // singular fields ------------------------------------------------- + + int32 GetInt32 (int number, int32 default_value) const; + int64 GetInt64 (int number, int64 default_value) const; + uint32 GetUInt32(int number, uint32 default_value) const; + uint64 GetUInt64(int number, uint64 default_value) const; + float GetFloat (int number, float default_value) const; + double GetDouble(int number, double default_value) const; + bool GetBool (int number, bool default_value) const; + int GetEnum (int number, int default_value) const; + const string & GetString (int number, const string& default_value) const; + const MessageLite& GetMessage(int number, + const MessageLite& default_value) const; + const MessageLite& GetMessage(int number, const Descriptor* message_type, + MessageFactory* factory) const; + + // |descriptor| may be NULL so long as it is known that the descriptor for + // the extension lives in the same pool as the descriptor for the containing + // type. +#define desc const FieldDescriptor* descriptor // avoid line wrapping + void SetInt32 (int number, FieldType type, int32 value, desc); + void SetInt64 (int number, FieldType type, int64 value, desc); + void SetUInt32(int number, FieldType type, uint32 value, desc); + void SetUInt64(int number, FieldType type, uint64 value, desc); + void SetFloat (int number, FieldType type, float value, desc); + void SetDouble(int number, FieldType type, double value, desc); + void SetBool (int number, FieldType type, bool value, desc); + void SetEnum (int number, FieldType type, int value, desc); + void SetString(int number, FieldType type, const string& value, desc); + string * MutableString (int number, FieldType type, desc); + MessageLite* MutableMessage(int number, FieldType type, + const MessageLite& prototype, desc); + MessageLite* MutableMessage(const FieldDescriptor* decsriptor, + MessageFactory* factory); + // Adds the given message to the ExtensionSet, taking ownership of the + // message object. Existing message with the same number will be deleted. + // If "message" is NULL, this is equivalent to "ClearExtension(number)". + void SetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message); + MessageLite* ReleaseMessage(int number, const MessageLite& prototype); + MessageLite* ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); +#undef desc + + // repeated fields ------------------------------------------------- + + void* MutableRawRepeatedField(int number); + + int32 GetRepeatedInt32 (int number, int index) const; + int64 GetRepeatedInt64 (int number, int index) const; + uint32 GetRepeatedUInt32(int number, int index) const; + uint64 GetRepeatedUInt64(int number, int index) const; + float GetRepeatedFloat (int number, int index) const; + double GetRepeatedDouble(int number, int index) const; + bool GetRepeatedBool (int number, int index) const; + int GetRepeatedEnum (int number, int index) const; + const string & GetRepeatedString (int number, int index) const; + const MessageLite& GetRepeatedMessage(int number, int index) const; + + void SetRepeatedInt32 (int number, int index, int32 value); + void SetRepeatedInt64 (int number, int index, int64 value); + void SetRepeatedUInt32(int number, int index, uint32 value); + void SetRepeatedUInt64(int number, int index, uint64 value); + void SetRepeatedFloat (int number, int index, float value); + void SetRepeatedDouble(int number, int index, double value); + void SetRepeatedBool (int number, int index, bool value); + void SetRepeatedEnum (int number, int index, int value); + void SetRepeatedString(int number, int index, const string& value); + string * MutableRepeatedString (int number, int index); + MessageLite* MutableRepeatedMessage(int number, int index); + +#define desc const FieldDescriptor* descriptor // avoid line wrapping + void AddInt32 (int number, FieldType type, bool packed, int32 value, desc); + void AddInt64 (int number, FieldType type, bool packed, int64 value, desc); + void AddUInt32(int number, FieldType type, bool packed, uint32 value, desc); + void AddUInt64(int number, FieldType type, bool packed, uint64 value, desc); + void AddFloat (int number, FieldType type, bool packed, float value, desc); + void AddDouble(int number, FieldType type, bool packed, double value, desc); + void AddBool (int number, FieldType type, bool packed, bool value, desc); + void AddEnum (int number, FieldType type, bool packed, int value, desc); + void AddString(int number, FieldType type, const string& value, desc); + string * AddString (int number, FieldType type, desc); + MessageLite* AddMessage(int number, FieldType type, + const MessageLite& prototype, desc); + MessageLite* AddMessage(const FieldDescriptor* descriptor, + MessageFactory* factory); +#undef desc + + void RemoveLast(int number); + MessageLite* ReleaseLast(int number); + void SwapElements(int number, int index1, int index2); + + // ----------------------------------------------------------------- + // TODO(kenton): Hardcore memory management accessors + + // ================================================================= + // convenience methods for implementing methods of Message + // + // These could all be implemented in terms of the other methods of this + // class, but providing them here helps keep the generated code size down. + + void Clear(); + void MergeFrom(const ExtensionSet& other); + void Swap(ExtensionSet* other); + bool IsInitialized() const; + + // Parses a single extension from the input. The input should start out + // positioned immediately after the tag. + bool ParseField(uint32 tag, io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); + + // Specific versions for lite or full messages (constructs the appropriate + // FieldSkipper automatically). |containing_type| is the default + // instance for the containing message; it is used only to look up the + // extension by number. See RegisterExtension(), above. Unlike the other + // methods of ExtensionSet, this only works for generated message types -- + // it looks up extensions registered using RegisterExtension(). + bool ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type); + bool ParseField(uint32 tag, io::CodedInputStream* input, + const Message* containing_type, + UnknownFieldSet* unknown_fields); + + // Parse an entire message in MessageSet format. Such messages have no + // fields, only extensions. + bool ParseMessageSet(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); + + // Specific versions for lite or full messages (constructs the appropriate + // FieldSkipper automatically). + bool ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type); + bool ParseMessageSet(io::CodedInputStream* input, + const Message* containing_type, + UnknownFieldSet* unknown_fields); + + // Write all extension fields with field numbers in the range + // [start_field_number, end_field_number) + // to the output stream, using the cached sizes computed when ByteSize() was + // last called. Note that the range bounds are inclusive-exclusive. + void SerializeWithCachedSizes(int start_field_number, + int end_field_number, + io::CodedOutputStream* output) const; + + // Same as SerializeWithCachedSizes, but without any bounds checking. + // The caller must ensure that target has sufficient capacity for the + // serialized extensions. + // + // Returns a pointer past the last written byte. + uint8* SerializeWithCachedSizesToArray(int start_field_number, + int end_field_number, + uint8* target) const; + + // Like above but serializes in MessageSet format. + void SerializeMessageSetWithCachedSizes(io::CodedOutputStream* output) const; + uint8* SerializeMessageSetWithCachedSizesToArray(uint8* target) const; + + // Returns the total serialized size of all the extensions. + int ByteSize() const; + + // Like ByteSize() but uses MessageSet format. + int MessageSetByteSize() const; + + // Returns (an estimate of) the total number of bytes used for storing the + // extensions in memory, excluding sizeof(*this). If the ExtensionSet is + // for a lite message (and thus possibly contains lite messages), the results + // are undefined (might work, might crash, might corrupt data, might not even + // be linked in). It's up to the protocol compiler to avoid calling this on + // such ExtensionSets (easy enough since lite messages don't implement + // SpaceUsed()). + int SpaceUsedExcludingSelf() const; + + private: + + // Interface of a lazily parsed singular message extension. + class LIBPROTOBUF_EXPORT LazyMessageExtension { + public: + LazyMessageExtension() {} + virtual ~LazyMessageExtension() {} + + virtual LazyMessageExtension* New() const = 0; + virtual const MessageLite& GetMessage( + const MessageLite& prototype) const = 0; + virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0; + virtual void SetAllocatedMessage(MessageLite *message) = 0; + virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0; + + virtual bool IsInitialized() const = 0; + virtual int ByteSize() const = 0; + virtual int SpaceUsed() const = 0; + + virtual void MergeFrom(const LazyMessageExtension& other) = 0; + virtual void Clear() = 0; + + virtual bool ReadMessage(const MessageLite& prototype, + io::CodedInputStream* input) = 0; + virtual void WriteMessage(int number, + io::CodedOutputStream* output) const = 0; + virtual uint8* WriteMessageToArray(int number, uint8* target) const = 0; + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension); + }; + struct Extension { + // The order of these fields packs Extension into 24 bytes when using 8 + // byte alignment. Consider this when adding or removing fields here. + union { + int32 int32_value; + int64 int64_value; + uint32 uint32_value; + uint64 uint64_value; + float float_value; + double double_value; + bool bool_value; + int enum_value; + string* string_value; + MessageLite* message_value; + LazyMessageExtension* lazymessage_value; + + RepeatedField * repeated_int32_value; + RepeatedField * repeated_int64_value; + RepeatedField * repeated_uint32_value; + RepeatedField * repeated_uint64_value; + RepeatedField * repeated_float_value; + RepeatedField * repeated_double_value; + RepeatedField * repeated_bool_value; + RepeatedField * repeated_enum_value; + RepeatedPtrField* repeated_string_value; + RepeatedPtrField* repeated_message_value; + }; + + FieldType type; + bool is_repeated; + + // For singular types, indicates if the extension is "cleared". This + // happens when an extension is set and then later cleared by the caller. + // We want to keep the Extension object around for reuse, so instead of + // removing it from the map, we just set is_cleared = true. This has no + // meaning for repeated types; for those, the size of the RepeatedField + // simply becomes zero when cleared. + bool is_cleared : 4; + + // For singular message types, indicates whether lazy parsing is enabled + // for this extension. This field is only valid when type == TYPE_MESSAGE + // and !is_repeated because we only support lazy parsing for singular + // message types currently. If is_lazy = true, the extension is stored in + // lazymessage_value. Otherwise, the extension will be message_value. + bool is_lazy : 4; + + // For repeated types, this indicates if the [packed=true] option is set. + bool is_packed; + + // For packed fields, the size of the packed data is recorded here when + // ByteSize() is called then used during serialization. + // TODO(kenton): Use atomic when C++ supports it. + mutable int cached_size; + + // The descriptor for this extension, if one exists and is known. May be + // NULL. Must not be NULL if the descriptor for the extension does not + // live in the same pool as the descriptor for the containing type. + const FieldDescriptor* descriptor; + + // Some helper methods for operations on a single Extension. + void SerializeFieldWithCachedSizes( + int number, + io::CodedOutputStream* output) const; + uint8* SerializeFieldWithCachedSizesToArray( + int number, + uint8* target) const; + void SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const; + uint8* SerializeMessageSetItemWithCachedSizesToArray( + int number, + uint8* target) const; + int ByteSize(int number) const; + int MessageSetItemByteSize(int number) const; + void Clear(); + int GetSize() const; + void Free(); + int SpaceUsedExcludingSelf() const; + }; + + + // Returns true and fills field_number and extension if extension is found. + bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder, + int* field_number, ExtensionInfo* extension); + + // Parses a single extension from the input. The input should start out + // positioned immediately after the wire tag. This method is called in + // ParseField() after field number is extracted from the wire tag and + // ExtensionInfo is found by the field number. + bool ParseFieldWithExtensionInfo(int field_number, + const ExtensionInfo& extension, + io::CodedInputStream* input, + FieldSkipper* field_skipper); + + // Like ParseField(), but this method may parse singular message extensions + // lazily depending on the value of FLAGS_eagerly_parse_message_sets. + bool ParseFieldMaybeLazily(uint32 tag, io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); + + // Gets the extension with the given number, creating it if it does not + // already exist. Returns true if the extension did not already exist. + bool MaybeNewExtension(int number, const FieldDescriptor* descriptor, + Extension** result); + + // Parse a single MessageSet item -- called just after the item group start + // tag has been read. + bool ParseMessageSetItem(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper); + + + // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This + // friendship should automatically extend to ExtensionSet::Extension, but + // unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this + // correctly. So, we must provide helpers for calling methods of that + // class. + + // Defined in extension_set_heavy.cc. + static inline int RepeatedMessage_SpaceUsedExcludingSelf( + RepeatedPtrFieldBase* field); + + // The Extension struct is small enough to be passed by value, so we use it + // directly as the value type in the map rather than use pointers. We use + // a map rather than hash_map here because we expect most ExtensionSets will + // only contain a small number of extensions whereas hash_map is optimized + // for 100 elements or more. Also, we want AppendToList() to order fields + // by field number. + std::map extensions_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); +}; + +// These are just for convenience... +inline void ExtensionSet::SetString(int number, FieldType type, + const string& value, + const FieldDescriptor* descriptor) { + MutableString(number, type, descriptor)->assign(value); +} +inline void ExtensionSet::SetRepeatedString(int number, int index, + const string& value) { + MutableRepeatedString(number, index)->assign(value); +} +inline void ExtensionSet::AddString(int number, FieldType type, + const string& value, + const FieldDescriptor* descriptor) { + AddString(number, type, descriptor)->assign(value); +} + +// =================================================================== +// Glue for generated extension accessors + +// ------------------------------------------------------------------- +// Template magic + +// First we have a set of classes representing "type traits" for different +// field types. A type traits class knows how to implement basic accessors +// for extensions of a particular type given an ExtensionSet. The signature +// for a type traits class looks like this: +// +// class TypeTraits { +// public: +// typedef ? ConstType; +// typedef ? MutableType; +// +// static inline ConstType Get(int number, const ExtensionSet& set); +// static inline void Set(int number, ConstType value, ExtensionSet* set); +// static inline MutableType Mutable(int number, ExtensionSet* set); +// +// // Variants for repeated fields. +// static inline ConstType Get(int number, const ExtensionSet& set, +// int index); +// static inline void Set(int number, int index, +// ConstType value, ExtensionSet* set); +// static inline MutableType Mutable(int number, int index, +// ExtensionSet* set); +// static inline void Add(int number, ConstType value, ExtensionSet* set); +// static inline MutableType Add(int number, ExtensionSet* set); +// }; +// +// Not all of these methods make sense for all field types. For example, the +// "Mutable" methods only make sense for strings and messages, and the +// repeated methods only make sense for repeated types. So, each type +// traits class implements only the set of methods from this signature that it +// actually supports. This will cause a compiler error if the user tries to +// access an extension using a method that doesn't make sense for its type. +// For example, if "foo" is an extension of type "optional int32", then if you +// try to write code like: +// my_message.MutableExtension(foo) +// you will get a compile error because PrimitiveTypeTraits does not +// have a "Mutable()" method. + +// ------------------------------------------------------------------- +// PrimitiveTypeTraits + +// Since the ExtensionSet has different methods for each primitive type, +// we must explicitly define the methods of the type traits class for each +// known type. +template +class PrimitiveTypeTraits { + public: + typedef Type ConstType; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value); + static inline void Set(int number, FieldType field_type, + ConstType value, ExtensionSet* set); +}; + +template +class RepeatedPrimitiveTypeTraits { + public: + typedef Type ConstType; + + static inline Type Get(int number, const ExtensionSet& set, int index); + static inline void Set(int number, int index, Type value, ExtensionSet* set); + static inline void Add(int number, FieldType field_type, + bool is_packed, Type value, ExtensionSet* set); +}; + +#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ +template<> inline TYPE PrimitiveTypeTraits::Get( \ + int number, const ExtensionSet& set, TYPE default_value) { \ + return set.Get##METHOD(number, default_value); \ +} \ +template<> inline void PrimitiveTypeTraits::Set( \ + int number, FieldType field_type, TYPE value, ExtensionSet* set) { \ + set->Set##METHOD(number, field_type, value, NULL); \ +} \ + \ +template<> inline TYPE RepeatedPrimitiveTypeTraits::Get( \ + int number, const ExtensionSet& set, int index) { \ + return set.GetRepeated##METHOD(number, index); \ +} \ +template<> inline void RepeatedPrimitiveTypeTraits::Set( \ + int number, int index, TYPE value, ExtensionSet* set) { \ + set->SetRepeated##METHOD(number, index, value); \ +} \ +template<> inline void RepeatedPrimitiveTypeTraits::Add( \ + int number, FieldType field_type, bool is_packed, \ + TYPE value, ExtensionSet* set) { \ + set->Add##METHOD(number, field_type, is_packed, value, NULL); \ +} + +PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32) +PROTOBUF_DEFINE_PRIMITIVE_TYPE( int64, Int64) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint32, UInt32) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(uint64, UInt64) +PROTOBUF_DEFINE_PRIMITIVE_TYPE( float, Float) +PROTOBUF_DEFINE_PRIMITIVE_TYPE(double, Double) +PROTOBUF_DEFINE_PRIMITIVE_TYPE( bool, Bool) + +#undef PROTOBUF_DEFINE_PRIMITIVE_TYPE + +// ------------------------------------------------------------------- +// StringTypeTraits + +// Strings support both Set() and Mutable(). +class LIBPROTOBUF_EXPORT StringTypeTraits { + public: + typedef const string& ConstType; + typedef string* MutableType; + + static inline const string& Get(int number, const ExtensionSet& set, + ConstType default_value) { + return set.GetString(number, default_value); + } + static inline void Set(int number, FieldType field_type, + const string& value, ExtensionSet* set) { + set->SetString(number, field_type, value, NULL); + } + static inline string* Mutable(int number, FieldType field_type, + ExtensionSet* set) { + return set->MutableString(number, field_type, NULL); + } +}; + +class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { + public: + typedef const string& ConstType; + typedef string* MutableType; + + static inline const string& Get(int number, const ExtensionSet& set, + int index) { + return set.GetRepeatedString(number, index); + } + static inline void Set(int number, int index, + const string& value, ExtensionSet* set) { + set->SetRepeatedString(number, index, value); + } + static inline string* Mutable(int number, int index, ExtensionSet* set) { + return set->MutableRepeatedString(number, index); + } + static inline void Add(int number, FieldType field_type, + bool /*is_packed*/, const string& value, + ExtensionSet* set) { + set->AddString(number, field_type, value, NULL); + } + static inline string* Add(int number, FieldType field_type, + ExtensionSet* set) { + return set->AddString(number, field_type, NULL); + } +}; + +// ------------------------------------------------------------------- +// EnumTypeTraits + +// ExtensionSet represents enums using integers internally, so we have to +// static_cast around. +template +class EnumTypeTraits { + public: + typedef Type ConstType; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value) { + return static_cast(set.GetEnum(number, default_value)); + } + static inline void Set(int number, FieldType field_type, + ConstType value, ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->SetEnum(number, field_type, value, NULL); + } +}; + +template +class RepeatedEnumTypeTraits { + public: + typedef Type ConstType; + + static inline ConstType Get(int number, const ExtensionSet& set, int index) { + return static_cast(set.GetRepeatedEnum(number, index)); + } + static inline void Set(int number, int index, + ConstType value, ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->SetRepeatedEnum(number, index, value); + } + static inline void Add(int number, FieldType field_type, + bool is_packed, ConstType value, ExtensionSet* set) { + GOOGLE_DCHECK(IsValid(value)); + set->AddEnum(number, field_type, is_packed, value, NULL); + } +}; + +// ------------------------------------------------------------------- +// MessageTypeTraits + +// ExtensionSet guarantees that when manipulating extensions with message +// types, the implementation used will be the compiled-in class representing +// that type. So, we can static_cast down to the exact type we expect. +template +class MessageTypeTraits { + public: + typedef const Type& ConstType; + typedef Type* MutableType; + + static inline ConstType Get(int number, const ExtensionSet& set, + ConstType default_value) { + return static_cast( + set.GetMessage(number, default_value)); + } + static inline MutableType Mutable(int number, FieldType field_type, + ExtensionSet* set) { + return static_cast( + set->MutableMessage(number, field_type, Type::default_instance(), NULL)); + } + static inline void SetAllocated(int number, FieldType field_type, + MutableType message, ExtensionSet* set) { + set->SetAllocatedMessage(number, field_type, NULL, message); + } + static inline MutableType Release(int number, FieldType field_type, + ExtensionSet* set) { + return static_cast(set->ReleaseMessage( + number, Type::default_instance())); + } +}; + +template +class RepeatedMessageTypeTraits { + public: + typedef const Type& ConstType; + typedef Type* MutableType; + + static inline ConstType Get(int number, const ExtensionSet& set, int index) { + return static_cast(set.GetRepeatedMessage(number, index)); + } + static inline MutableType Mutable(int number, int index, ExtensionSet* set) { + return static_cast(set->MutableRepeatedMessage(number, index)); + } + static inline MutableType Add(int number, FieldType field_type, + ExtensionSet* set) { + return static_cast( + set->AddMessage(number, field_type, Type::default_instance(), NULL)); + } +}; + +// ------------------------------------------------------------------- +// ExtensionIdentifier + +// This is the type of actual extension objects. E.g. if you have: +// extends Foo with optional int32 bar = 1234; +// then "bar" will be defined in C++ as: +// ExtensionIdentifier, 1, false> bar(1234); +// +// Note that we could, in theory, supply the field number as a template +// parameter, and thus make an instance of ExtensionIdentifier have no +// actual contents. However, if we did that, then using at extension +// identifier would not necessarily cause the compiler to output any sort +// of reference to any simple defined in the extension's .pb.o file. Some +// linkers will actually drop object files that are not explicitly referenced, +// but that would be bad because it would cause this extension to not be +// registered at static initialization, and therefore using it would crash. + +template +class ExtensionIdentifier { + public: + typedef TypeTraitsType TypeTraits; + typedef ExtendeeType Extendee; + + ExtensionIdentifier(int number, typename TypeTraits::ConstType default_value) + : number_(number), default_value_(default_value) {} + inline int number() const { return number_; } + typename TypeTraits::ConstType default_value() const { + return default_value_; + } + + private: + const int number_; + typename TypeTraits::ConstType default_value_; +}; + +// ------------------------------------------------------------------- +// Generated accessors + +// This macro should be expanded in the context of a generated type which +// has extensions. +// +// We use "_proto_TypeTraits" as a type name below because "TypeTraits" +// causes problems if the class has a nested message or enum type with that +// name and "_TypeTraits" is technically reserved for the C++ library since +// it starts with an underscore followed by a capital letter. +// +// For similar reason, we use "_field_type" and "_is_packed" as parameter names +// below, so that "field_type" and "is_packed" can be used as field names. +#define GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(CLASSNAME) \ + /* Has, Size, Clear */ \ + template \ + inline bool HasExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + return _extensions_.Has(id.number()); \ + } \ + \ + template \ + inline void ClearExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + _extensions_.ClearExtension(id.number()); \ + } \ + \ + template \ + inline int ExtensionSize( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + return _extensions_.ExtensionSize(id.number()); \ + } \ + \ + /* Singular accessors */ \ + template \ + inline typename _proto_TypeTraits::ConstType GetExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ + return _proto_TypeTraits::Get(id.number(), _extensions_, \ + id.default_value()); \ + } \ + \ + template \ + inline typename _proto_TypeTraits::MutableType MutableExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Mutable(id.number(), _field_type, \ + &_extensions_); \ + } \ + \ + template \ + inline void SetExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::ConstType value) { \ + _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \ + } \ + \ + template \ + inline void SetAllocatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::MutableType value) { \ + _proto_TypeTraits::SetAllocated(id.number(), _field_type, \ + value, &_extensions_); \ + } \ + template \ + inline typename _proto_TypeTraits::MutableType ReleaseExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Release(id.number(), _field_type, \ + &_extensions_); \ + } \ + \ + /* Repeated accessors */ \ + template \ + inline typename _proto_TypeTraits::ConstType GetExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + int index) const { \ + return _proto_TypeTraits::Get(id.number(), _extensions_, index); \ + } \ + \ + template \ + inline typename _proto_TypeTraits::MutableType MutableExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + int index) { \ + return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_); \ + } \ + \ + template \ + inline void SetExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + int index, typename _proto_TypeTraits::ConstType value) { \ + _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \ + } \ + \ + template \ + inline typename _proto_TypeTraits::MutableType AddExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ + return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \ + } \ + \ + template \ + inline void AddExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ + typename _proto_TypeTraits::ConstType value) { \ + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \ + value, &_extensions_); \ + } + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_EXTENSION_SET_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_heavy.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_heavy.cc new file mode 100644 index 000000000..483d7055d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_heavy.cc @@ -0,0 +1,711 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Contains methods defined in extension_set.h which cannot be part of the +// lite library because they use descriptors or reflection. + +#include +#include +#include +#include +#include +#include +#include + +namespace google { + +namespace protobuf { +namespace internal { + + +// Implementation of ExtensionFinder which finds extensions in a given +// DescriptorPool, using the given MessageFactory to construct sub-objects. +// This class is implemented in extension_set_heavy.cc. +class DescriptorPoolExtensionFinder : public ExtensionFinder { + public: + DescriptorPoolExtensionFinder(const DescriptorPool* pool, + MessageFactory* factory, + const Descriptor* containing_type) + : pool_(pool), factory_(factory), containing_type_(containing_type) {} + virtual ~DescriptorPoolExtensionFinder() {} + + virtual bool Find(int number, ExtensionInfo* output); + + private: + const DescriptorPool* pool_; + MessageFactory* factory_; + const Descriptor* containing_type_; +}; + +void ExtensionSet::AppendToList(const Descriptor* containing_type, + const DescriptorPool* pool, + vector* output) const { + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + bool has = false; + if (iter->second.is_repeated) { + has = iter->second.GetSize() > 0; + } else { + has = !iter->second.is_cleared; + } + + if (has) { + // TODO(kenton): Looking up each field by number is somewhat unfortunate. + // Is there a better way? The problem is that descriptors are lazily- + // initialized, so they might not even be constructed until + // AppendToList() is called. + + if (iter->second.descriptor == NULL) { + output->push_back(pool->FindExtensionByNumber( + containing_type, iter->first)); + } else { + output->push_back(iter->second.descriptor); + } + } + } +} + +inline FieldDescriptor::Type real_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= FieldDescriptor::MAX_TYPE); + return static_cast(type); +} + +inline FieldDescriptor::CppType cpp_type(FieldType type) { + return FieldDescriptor::TypeToCppType( + static_cast(type)); +} + +inline WireFormatLite::FieldType field_type(FieldType type) { + GOOGLE_DCHECK(type > 0 && type <= WireFormatLite::MAX_FIELD_TYPE); + return static_cast(type); +} + +#define GOOGLE_DCHECK_TYPE(EXTENSION, LABEL, CPPTYPE) \ + GOOGLE_DCHECK_EQ((EXTENSION).is_repeated ? FieldDescriptor::LABEL_REPEATED \ + : FieldDescriptor::LABEL_OPTIONAL, \ + FieldDescriptor::LABEL_##LABEL); \ + GOOGLE_DCHECK_EQ(cpp_type((EXTENSION).type), FieldDescriptor::CPPTYPE_##CPPTYPE) + +const MessageLite& ExtensionSet::GetMessage(int number, + const Descriptor* message_type, + MessageFactory* factory) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end() || iter->second.is_cleared) { + // Not present. Return the default value. + return *factory->GetPrototype(message_type); + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + if (iter->second.is_lazy) { + return iter->second.lazymessage_value->GetMessage( + *factory->GetPrototype(message_type)); + } else { + return *iter->second.message_value; + } + } +} + +MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension; + if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { + extension->type = descriptor->type(); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_packed = false; + const MessageLite* prototype = + factory->GetPrototype(descriptor->message_type()); + extension->is_lazy = false; + extension->message_value = prototype->New(); + extension->is_cleared = false; + return extension->message_value; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + extension->is_cleared = false; + if (extension->is_lazy) { + return extension->lazymessage_value->MutableMessage( + *factory->GetPrototype(descriptor->message_type())); + } else { + return extension->message_value; + } + } +} + +MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + map::iterator iter = extensions_.find(descriptor->number()); + if (iter == extensions_.end()) { + // Not present. Return NULL. + return NULL; + } else { + GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE); + MessageLite* ret = NULL; + if (iter->second.is_lazy) { + ret = iter->second.lazymessage_value->ReleaseMessage( + *factory->GetPrototype(descriptor->message_type())); + delete iter->second.lazymessage_value; + } else { + ret = iter->second.message_value; + } + extensions_.erase(descriptor->number()); + return ret; + } +} + +MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, + MessageFactory* factory) { + Extension* extension; + if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) { + extension->type = descriptor->type(); + GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); + extension->is_repeated = true; + extension->repeated_message_value = + new RepeatedPtrField(); + } else { + GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); + } + + // RepeatedPtrField does not know how to Add() since it cannot + // allocate an abstract object, so we have to be tricky. + MessageLite* result = extension->repeated_message_value + ->AddFromCleared >(); + if (result == NULL) { + const MessageLite* prototype; + if (extension->repeated_message_value->size() == 0) { + prototype = factory->GetPrototype(descriptor->message_type()); + GOOGLE_CHECK(prototype != NULL); + } else { + prototype = &extension->repeated_message_value->Get(0); + } + result = prototype->New(); + extension->repeated_message_value->AddAllocated(result); + } + return result; +} + +static bool ValidateEnumUsingDescriptor(const void* arg, int number) { + return reinterpret_cast(arg) + ->FindValueByNumber(number) != NULL; +} + +bool DescriptorPoolExtensionFinder::Find(int number, ExtensionInfo* output) { + const FieldDescriptor* extension = + pool_->FindExtensionByNumber(containing_type_, number); + if (extension == NULL) { + return false; + } else { + output->type = extension->type(); + output->is_repeated = extension->is_repeated(); + output->is_packed = extension->options().packed(); + output->descriptor = extension; + if (extension->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + output->message_prototype = + factory_->GetPrototype(extension->message_type()); + GOOGLE_CHECK(output->message_prototype != NULL) + << "Extension factory's GetPrototype() returned NULL for extension: " + << extension->full_name(); + } else if (extension->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + output->enum_validity_check.func = ValidateEnumUsingDescriptor; + output->enum_validity_check.arg = extension->enum_type(); + } + + return true; + } +} + +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const Message* containing_type, + UnknownFieldSet* unknown_fields) { + UnknownFieldSetFieldSkipper skipper(unknown_fields); + if (input->GetExtensionPool() == NULL) { + GeneratedExtensionFinder finder(containing_type); + return ParseField(tag, input, &finder, &skipper); + } else { + DescriptorPoolExtensionFinder finder(input->GetExtensionPool(), + input->GetExtensionFactory(), + containing_type->GetDescriptor()); + return ParseField(tag, input, &finder, &skipper); + } +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const Message* containing_type, + UnknownFieldSet* unknown_fields) { + UnknownFieldSetFieldSkipper skipper(unknown_fields); + if (input->GetExtensionPool() == NULL) { + GeneratedExtensionFinder finder(containing_type); + return ParseMessageSet(input, &finder, &skipper); + } else { + DescriptorPoolExtensionFinder finder(input->GetExtensionPool(), + input->GetExtensionFactory(), + containing_type->GetDescriptor()); + return ParseMessageSet(input, &finder, &skipper); + } +} + +int ExtensionSet::SpaceUsedExcludingSelf() const { + int total_size = + extensions_.size() * sizeof(map::value_type); + for (map::const_iterator iter = extensions_.begin(), + end = extensions_.end(); + iter != end; + ++iter) { + total_size += iter->second.SpaceUsedExcludingSelf(); + } + return total_size; +} + +inline int ExtensionSet::RepeatedMessage_SpaceUsedExcludingSelf( + RepeatedPtrFieldBase* field) { + return field->SpaceUsedExcludingSelf >(); +} + +int ExtensionSet::Extension::SpaceUsedExcludingSelf() const { + int total_size = 0; + if (is_repeated) { + switch (cpp_type(type)) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE: \ + total_size += sizeof(*repeated_##LOWERCASE##_value) + \ + repeated_##LOWERCASE##_value->SpaceUsedExcludingSelf();\ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE( UINT32, uint32); + HANDLE_TYPE( UINT64, uint64); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( DOUBLE, double); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, enum); + HANDLE_TYPE( STRING, string); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + // repeated_message_value is actually a RepeatedPtrField, + // but MessageLite has no SpaceUsed(), so we must directly call + // RepeatedPtrFieldBase::SpaceUsedExcludingSelf() with a different type + // handler. + total_size += sizeof(*repeated_message_value) + + RepeatedMessage_SpaceUsedExcludingSelf(repeated_message_value); + break; + } + } else { + switch (cpp_type(type)) { + case FieldDescriptor::CPPTYPE_STRING: + total_size += sizeof(*string_value) + + StringSpaceUsedExcludingSelf(*string_value); + break; + case FieldDescriptor::CPPTYPE_MESSAGE: + if (is_lazy) { + total_size += lazymessage_value->SpaceUsed(); + } else { + total_size += down_cast(message_value)->SpaceUsed(); + } + break; + default: + // No extra storage costs for primitive types. + break; + } + } + return total_size; +} + +// The Serialize*ToArray methods are only needed in the heavy library, as +// the lite library only generates SerializeWithCachedSizes. +uint8* ExtensionSet::SerializeWithCachedSizesToArray( + int start_field_number, int end_field_number, + uint8* target) const { + map::const_iterator iter; + for (iter = extensions_.lower_bound(start_field_number); + iter != extensions_.end() && iter->first < end_field_number; + ++iter) { + target = iter->second.SerializeFieldWithCachedSizesToArray(iter->first, + target); + } + return target; +} + +uint8* ExtensionSet::SerializeMessageSetWithCachedSizesToArray( + uint8* target) const { + map::const_iterator iter; + for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { + target = iter->second.SerializeMessageSetItemWithCachedSizesToArray( + iter->first, target); + } + return target; +} + +uint8* ExtensionSet::Extension::SerializeFieldWithCachedSizesToArray( + int number, uint8* target) const { + if (is_repeated) { + if (is_packed) { + if (cached_size == 0) return target; + + target = WireFormatLite::WriteTagToArray(number, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, target); + target = WireFormatLite::WriteInt32NoTagToArray(cached_size, target); + + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case FieldDescriptor::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = WireFormatLite::Write##CAMELCASE##NoTagToArray( \ + repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); + HANDLE_TYPE( ENUM, Enum, enum); +#undef HANDLE_TYPE + + case WireFormatLite::TYPE_STRING: + case WireFormatLite::TYPE_BYTES: + case WireFormatLite::TYPE_GROUP: + case WireFormatLite::TYPE_MESSAGE: + GOOGLE_LOG(FATAL) << "Non-primitive types can't be packed."; + break; + } + } else { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, LOWERCASE) \ + case FieldDescriptor::TYPE_##UPPERCASE: \ + for (int i = 0; i < repeated_##LOWERCASE##_value->size(); i++) { \ + target = WireFormatLite::Write##CAMELCASE##ToArray(number, \ + repeated_##LOWERCASE##_value->Get(i), target); \ + } \ + break + + HANDLE_TYPE( INT32, Int32, int32); + HANDLE_TYPE( INT64, Int64, int64); + HANDLE_TYPE( UINT32, UInt32, uint32); + HANDLE_TYPE( UINT64, UInt64, uint64); + HANDLE_TYPE( SINT32, SInt32, int32); + HANDLE_TYPE( SINT64, SInt64, int64); + HANDLE_TYPE( FIXED32, Fixed32, uint32); + HANDLE_TYPE( FIXED64, Fixed64, uint64); + HANDLE_TYPE(SFIXED32, SFixed32, int32); + HANDLE_TYPE(SFIXED64, SFixed64, int64); + HANDLE_TYPE( FLOAT, Float, float); + HANDLE_TYPE( DOUBLE, Double, double); + HANDLE_TYPE( BOOL, Bool, bool); + HANDLE_TYPE( STRING, String, string); + HANDLE_TYPE( BYTES, Bytes, string); + HANDLE_TYPE( ENUM, Enum, enum); + HANDLE_TYPE( GROUP, Group, message); + HANDLE_TYPE( MESSAGE, Message, message); +#undef HANDLE_TYPE + } + } + } else if (!is_cleared) { + switch (real_type(type)) { +#define HANDLE_TYPE(UPPERCASE, CAMELCASE, VALUE) \ + case FieldDescriptor::TYPE_##UPPERCASE: \ + target = WireFormatLite::Write##CAMELCASE##ToArray( \ + number, VALUE, target); \ + break + + HANDLE_TYPE( INT32, Int32, int32_value); + HANDLE_TYPE( INT64, Int64, int64_value); + HANDLE_TYPE( UINT32, UInt32, uint32_value); + HANDLE_TYPE( UINT64, UInt64, uint64_value); + HANDLE_TYPE( SINT32, SInt32, int32_value); + HANDLE_TYPE( SINT64, SInt64, int64_value); + HANDLE_TYPE( FIXED32, Fixed32, uint32_value); + HANDLE_TYPE( FIXED64, Fixed64, uint64_value); + HANDLE_TYPE(SFIXED32, SFixed32, int32_value); + HANDLE_TYPE(SFIXED64, SFixed64, int64_value); + HANDLE_TYPE( FLOAT, Float, float_value); + HANDLE_TYPE( DOUBLE, Double, double_value); + HANDLE_TYPE( BOOL, Bool, bool_value); + HANDLE_TYPE( STRING, String, *string_value); + HANDLE_TYPE( BYTES, Bytes, *string_value); + HANDLE_TYPE( ENUM, Enum, enum_value); + HANDLE_TYPE( GROUP, Group, *message_value); +#undef HANDLE_TYPE + case FieldDescriptor::TYPE_MESSAGE: + if (is_lazy) { + target = lazymessage_value->WriteMessageToArray(number, target); + } else { + target = WireFormatLite::WriteMessageToArray( + number, *message_value, target); + } + break; + } + } + return target; +} + +uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( + int number, + uint8* target) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + GOOGLE_LOG(WARNING) << "Invalid message set extension."; + return SerializeFieldWithCachedSizesToArray(number, target); + } + + if (is_cleared) return target; + + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + // Write type ID. + target = WireFormatLite::WriteUInt32ToArray( + WireFormatLite::kMessageSetTypeIdNumber, number, target); + // Write message. + if (is_lazy) { + target = lazymessage_value->WriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, target); + } else { + target = WireFormatLite::WriteMessageToArray( + WireFormatLite::kMessageSetMessageNumber, *message_value, target); + } + // End group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + return target; +} + + +bool ExtensionSet::ParseFieldMaybeLazily( + uint32 tag, io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + return ParseField(tag, input, extension_finder, field_skipper); +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + while (true) { + uint32 tag = input->ReadTag(); + switch (tag) { + case 0: + return true; + case WireFormatLite::kMessageSetItemStartTag: + if (!ParseMessageSetItem(input, extension_finder, field_skipper)) { + return false; + } + break; + default: + if (!ParseField(tag, input, extension_finder, field_skipper)) { + return false; + } + break; + } + } +} + +bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, + const MessageLite* containing_type) { + FieldSkipper skipper; + GeneratedExtensionFinder finder(containing_type); + return ParseMessageSet(input, &finder, &skipper); +} + +bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, + ExtensionFinder* extension_finder, + FieldSkipper* field_skipper) { + // TODO(kenton): It would be nice to share code between this and + // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the + // differences would be hard to factor out. + + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + // Once we see a type_id, we'll construct a fake tag for this extension + // which is the tag it would have had under the proto2 extensions wire + // format. + uint32 fake_tag = 0; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. + string message_data; + + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; + fake_tag = WireFormatLite::MakeTag(type_id, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + if (!message_data.empty()) { + // We saw some message data before the type_id. Have to parse it + // now. + io::CodedInputStream sub_input( + reinterpret_cast(message_data.data()), + message_data.size()); + if (!ParseFieldMaybeLazily(fake_tag, &sub_input, + extension_finder, field_skipper)) { + return false; + } + message_data.clear(); + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (fake_tag == 0) { + // We haven't seen a type_id yet. Append this data to message_data. + string temp; + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(&temp, length)) return false; + io::StringOutputStream output_stream(&message_data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteVarint32(length); + coded_output.WriteString(temp); + } else { + // Already saw type_id, so we can parse this directly. + if (!ParseFieldMaybeLazily(fake_tag, input, + extension_finder, field_skipper)) { + return false; + } + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!field_skipper->SkipField(input, tag)) return false; + } + } + } +} + +void ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizes( + int number, + io::CodedOutputStream* output) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but serialize it the normal way. + SerializeFieldWithCachedSizes(number, output); + return; + } + + if (is_cleared) return; + + // Start group. + output->WriteTag(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + number, + output); + // Write message. + if (is_lazy) { + lazymessage_value->WriteMessage( + WireFormatLite::kMessageSetMessageNumber, output); + } else { + WireFormatLite::WriteMessageMaybeToArray( + WireFormatLite::kMessageSetMessageNumber, + *message_value, + output); + } + + // End group. + output->WriteTag(WireFormatLite::kMessageSetItemEndTag); +} + +int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { + if (type != WireFormatLite::TYPE_MESSAGE || is_repeated) { + // Not a valid MessageSet extension, but compute the byte size for it the + // normal way. + return ByteSize(number); + } + + if (is_cleared) return 0; + + int our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(number); + + // message + int message_size = 0; + if (is_lazy) { + message_size = lazymessage_value->ByteSize(); + } else { + message_size = message_value->ByteSize(); + } + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +void ExtensionSet::SerializeMessageSetWithCachedSizes( + io::CodedOutputStream* output) const { + map::const_iterator iter; + for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { + iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); + } +} + +int ExtensionSet::MessageSetByteSize() const { + int total_size = 0; + + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + total_size += iter->second.MessageSetItemByteSize(iter->first); + } + + return total_size; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_unittest.cc new file mode 100644 index 000000000..559de6e13 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/extension_set_unittest.cc @@ -0,0 +1,726 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace google { + +namespace protobuf { +namespace internal { +namespace { + +// This test closely mirrors google/protobuf/compiler/cpp/unittest.cc +// except that it uses extensions rather than regular fields. + +TEST(ExtensionSetTest, Defaults) { + // Check that all default values are set correctly in the initial message. + unittest::TestAllExtensions message; + + TestUtil::ExpectExtensionsClear(message); + + // Messages should return pointers to default instances until first use. + // (This is not checked by ExpectClear() since it is not actually true after + // the fields have been set and then cleared.) + EXPECT_EQ(&unittest::OptionalGroup_extension::default_instance(), + &message.GetExtension(unittest::optionalgroup_extension)); + EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.GetExtension(unittest::optional_nested_message_extension)); + EXPECT_EQ(&unittest::ForeignMessage::default_instance(), + &message.GetExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), + &message.GetExtension(unittest::optional_import_message_extension)); +} + +TEST(ExtensionSetTest, Accessors) { + // Set every field to a unique value then go back and check all those + // values. + unittest::TestAllExtensions message; + + TestUtil::SetAllExtensions(&message); + TestUtil::ExpectAllExtensionsSet(message); + + TestUtil::ModifyRepeatedExtensions(&message); + TestUtil::ExpectRepeatedExtensionsModified(message); +} + +TEST(ExtensionSetTest, Clear) { + // Set every field to a unique value, clear the message, then check that + // it is cleared. + unittest::TestAllExtensions message; + + TestUtil::SetAllExtensions(&message); + message.Clear(); + TestUtil::ExpectExtensionsClear(message); + + // Unlike with the defaults test, we do NOT expect that requesting embedded + // messages will return a pointer to the default instance. Instead, they + // should return the objects that were created when mutable_blah() was + // called. + EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(), + &message.GetExtension(unittest::optionalgroup_extension)); + EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.GetExtension(unittest::optional_nested_message_extension)); + EXPECT_NE(&unittest::ForeignMessage::default_instance(), + &message.GetExtension( + unittest::optional_foreign_message_extension)); + EXPECT_NE(&unittest_import::ImportMessage::default_instance(), + &message.GetExtension(unittest::optional_import_message_extension)); + + // Make sure setting stuff again after clearing works. (This takes slightly + // different code paths since the objects are reused.) + TestUtil::SetAllExtensions(&message); + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(ExtensionSetTest, ClearOneField) { + // Set every field to a unique value, then clear one value and insure that + // only that one value is cleared. + unittest::TestAllExtensions message; + + TestUtil::SetAllExtensions(&message); + int64 original_value = + message.GetExtension(unittest::optional_int64_extension); + + // Clear the field and make sure it shows up as cleared. + message.ClearExtension(unittest::optional_int64_extension); + EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension)); + EXPECT_EQ(0, message.GetExtension(unittest::optional_int64_extension)); + + // Other adjacent fields should not be cleared. + EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension)); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension)); + + // Make sure if we set it again, then all fields are set. + message.SetExtension(unittest::optional_int64_extension, original_value); + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(ExtensionSetTest, SetAllocatedExtensin) { + unittest::TestAllExtensions message; + EXPECT_FALSE(message.HasExtension( + unittest::optional_foreign_message_extension)); + // Add a extension using SetAllocatedExtension + unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage(); + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + foreign_message); + EXPECT_TRUE(message.HasExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, + message.MutableExtension( + unittest::optional_foreign_message_extension)); + EXPECT_EQ(foreign_message, + &message.GetExtension( + unittest::optional_foreign_message_extension)); + + // SetAllocatedExtension should delete the previously existing extension. + // (We reply on unittest to check memory leaks for this case) + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + new unittest::ForeignMessage()); + + // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion. + message.SetAllocatedExtension(unittest::optional_foreign_message_extension, + NULL); + EXPECT_FALSE(message.HasExtension( + unittest::optional_foreign_message_extension)); +} + +TEST(ExtensionSetTest, ReleaseExtension) { + unittest::TestMessageSet message; + EXPECT_FALSE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // Add a extension using SetAllocatedExtension + unittest::TestMessageSetExtension1* extension = + new unittest::TestMessageSetExtension1(); + message.SetAllocatedExtension( + unittest::TestMessageSetExtension1::message_set_extension, + extension); + EXPECT_TRUE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // Release the extension using ReleaseExtension + unittest::TestMessageSetExtension1* released_extension = + message.ReleaseExtension( + unittest::TestMessageSetExtension1::message_set_extension); + EXPECT_EQ(extension, released_extension); + EXPECT_FALSE(message.HasExtension( + unittest::TestMessageSetExtension1::message_set_extension)); + // ReleaseExtension will return the underlying object even after + // ClearExtension is called. + message.SetAllocatedExtension( + unittest::TestMessageSetExtension1::message_set_extension, + extension); + message.ClearExtension( + unittest::TestMessageSetExtension1::message_set_extension); + released_extension = message.ReleaseExtension( + unittest::TestMessageSetExtension1::message_set_extension); + EXPECT_TRUE(released_extension != NULL); + delete released_extension; +} + + +TEST(ExtensionSetTest, CopyFrom) { + unittest::TestAllExtensions message1, message2; + + TestUtil::SetAllExtensions(&message1); + message2.CopyFrom(message1); + TestUtil::ExpectAllExtensionsSet(message2); + message2.CopyFrom(message1); // exercise copy when fields already exist + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ExtensioSetTest, CopyFromPacked) { + unittest::TestPackedExtensions message1, message2; + + TestUtil::SetPackedExtensions(&message1); + message2.CopyFrom(message1); + TestUtil::ExpectPackedExtensionsSet(message2); + message2.CopyFrom(message1); // exercise copy when fields already exist + TestUtil::ExpectPackedExtensionsSet(message2); +} + +TEST(ExtensionSetTest, CopyFromUpcasted) { + unittest::TestAllExtensions message1, message2; + const Message& upcasted_message = message1; + + TestUtil::SetAllExtensions(&message1); + message2.CopyFrom(upcasted_message); + TestUtil::ExpectAllExtensionsSet(message2); + // exercise copy when fields already exist + message2.CopyFrom(upcasted_message); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ExtensionSetTest, SwapWithEmpty) { + unittest::TestAllExtensions message1, message2; + TestUtil::SetAllExtensions(&message1); + + TestUtil::ExpectAllExtensionsSet(message1); + TestUtil::ExpectExtensionsClear(message2); + message1.Swap(&message2); + TestUtil::ExpectAllExtensionsSet(message2); + TestUtil::ExpectExtensionsClear(message1); +} + +TEST(ExtensionSetTest, SwapWithSelf) { + unittest::TestAllExtensions message; + TestUtil::SetAllExtensions(&message); + + TestUtil::ExpectAllExtensionsSet(message); + message.Swap(&message); + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(ExtensionSetTest, SerializationToArray) { + // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire + // compatibility of extensions. + // + // This checks serialization to a flat array by explicitly reserving space in + // the string and calling the generated message's + // SerializeWithCachedSizesToArray. + unittest::TestAllExtensions source; + unittest::TestAllTypes destination; + TestUtil::SetAllExtensions(&source); + int size = source.ByteSize(); + string data; + data.resize(size); + uint8* target = reinterpret_cast(string_as_array(&data)); + uint8* end = source.SerializeWithCachedSizesToArray(target); + EXPECT_EQ(size, end - target); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(destination); +} + +TEST(ExtensionSetTest, SerializationToStream) { + // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire + // compatibility of extensions. + // + // This checks serialization to an output stream by creating an array output + // stream that can only buffer 1 byte at a time - this prevents the message + // from ever jumping to the fast path, ensuring that serialization happens via + // the CodedOutputStream. + unittest::TestAllExtensions source; + unittest::TestAllTypes destination; + TestUtil::SetAllExtensions(&source); + int size = source.ByteSize(); + string data; + data.resize(size); + { + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + source.SerializeWithCachedSizes(&output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(destination); +} + +TEST(ExtensionSetTest, PackedSerializationToArray) { + // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure + // wire compatibility of extensions. + // + // This checks serialization to a flat array by explicitly reserving space in + // the string and calling the generated message's + // SerializeWithCachedSizesToArray. + unittest::TestPackedExtensions source; + unittest::TestPackedTypes destination; + TestUtil::SetPackedExtensions(&source); + int size = source.ByteSize(); + string data; + data.resize(size); + uint8* target = reinterpret_cast(string_as_array(&data)); + uint8* end = source.SerializeWithCachedSizesToArray(target); + EXPECT_EQ(size, end - target); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectPackedFieldsSet(destination); +} + +TEST(ExtensionSetTest, PackedSerializationToStream) { + // Serialize as TestPackedExtensions and parse as TestPackedTypes to insure + // wire compatibility of extensions. + // + // This checks serialization to an output stream by creating an array output + // stream that can only buffer 1 byte at a time - this prevents the message + // from ever jumping to the fast path, ensuring that serialization happens via + // the CodedOutputStream. + unittest::TestPackedExtensions source; + unittest::TestPackedTypes destination; + TestUtil::SetPackedExtensions(&source); + int size = source.ByteSize(); + string data; + data.resize(size); + { + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + source.SerializeWithCachedSizes(&output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectPackedFieldsSet(destination); +} + +TEST(ExtensionSetTest, Parsing) { + // Serialize as TestAllTypes and parse as TestAllExtensions. + unittest::TestAllTypes source; + unittest::TestAllExtensions destination; + string data; + + TestUtil::SetAllFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectAllExtensionsSet(destination); +} + +TEST(ExtensionSetTest, PackedParsing) { + // Serialize as TestPackedTypes and parse as TestPackedExtensions. + unittest::TestPackedTypes source; + unittest::TestPackedExtensions destination; + string data; + + TestUtil::SetPackedFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectPackedExtensionsSet(destination); +} + +TEST(ExtensionSetTest, IsInitialized) { + // Test that IsInitialized() returns false if required fields in nested + // extensions are missing. + unittest::TestAllExtensions message; + + EXPECT_TRUE(message.IsInitialized()); + + message.MutableExtension(unittest::TestRequired::single); + EXPECT_FALSE(message.IsInitialized()); + + message.MutableExtension(unittest::TestRequired::single)->set_a(1); + EXPECT_FALSE(message.IsInitialized()); + message.MutableExtension(unittest::TestRequired::single)->set_b(2); + EXPECT_FALSE(message.IsInitialized()); + message.MutableExtension(unittest::TestRequired::single)->set_c(3); + EXPECT_TRUE(message.IsInitialized()); + + message.AddExtension(unittest::TestRequired::multi); + EXPECT_FALSE(message.IsInitialized()); + + message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1); + EXPECT_FALSE(message.IsInitialized()); + message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2); + EXPECT_FALSE(message.IsInitialized()); + message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3); + EXPECT_TRUE(message.IsInitialized()); +} + +TEST(ExtensionSetTest, MutableString) { + // Test the mutable string accessors. + unittest::TestAllExtensions message; + + message.MutableExtension(unittest::optional_string_extension)->assign("foo"); + EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension)); + EXPECT_EQ("foo", message.GetExtension(unittest::optional_string_extension)); + + message.AddExtension(unittest::repeated_string_extension)->assign("bar"); + ASSERT_EQ(1, message.ExtensionSize(unittest::repeated_string_extension)); + EXPECT_EQ("bar", + message.GetExtension(unittest::repeated_string_extension, 0)); +} + +TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { + // Scalar primitive extensions should increase the extension set size by a + // minimum of the size of the primitive type. +#define TEST_SCALAR_EXTENSIONS_SPACE_USED(type, value) \ + do { \ + unittest::TestAllExtensions message; \ + const int base_size = message.SpaceUsed(); \ + message.SetExtension(unittest::optional_##type##_extension, value); \ + int min_expected_size = base_size + \ + sizeof(message.GetExtension(unittest::optional_##type##_extension)); \ + EXPECT_LE(min_expected_size, message.SpaceUsed()); \ + } while (0) + + TEST_SCALAR_EXTENSIONS_SPACE_USED(int32 , 101); + TEST_SCALAR_EXTENSIONS_SPACE_USED(int64 , 102); + TEST_SCALAR_EXTENSIONS_SPACE_USED(uint32 , 103); + TEST_SCALAR_EXTENSIONS_SPACE_USED(uint64 , 104); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sint32 , 105); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sint64 , 106); + TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed32 , 107); + TEST_SCALAR_EXTENSIONS_SPACE_USED(fixed64 , 108); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed32, 109); + TEST_SCALAR_EXTENSIONS_SPACE_USED(sfixed64, 110); + TEST_SCALAR_EXTENSIONS_SPACE_USED(float , 111); + TEST_SCALAR_EXTENSIONS_SPACE_USED(double , 112); + TEST_SCALAR_EXTENSIONS_SPACE_USED(bool , true); +#undef TEST_SCALAR_EXTENSIONS_SPACE_USED + { + unittest::TestAllExtensions message; + const int base_size = message.SpaceUsed(); + message.SetExtension(unittest::optional_nested_enum_extension, + unittest::TestAllTypes::FOO); + int min_expected_size = base_size + + sizeof(message.GetExtension(unittest::optional_nested_enum_extension)); + EXPECT_LE(min_expected_size, message.SpaceUsed()); + } + { + // Strings may cause extra allocations depending on their length; ensure + // that gets included as well. + unittest::TestAllExtensions message; + const int base_size = message.SpaceUsed(); + const string s("this is a fairly large string that will cause some " + "allocation in order to store it in the extension"); + message.SetExtension(unittest::optional_string_extension, s); + int min_expected_size = base_size + s.length(); + EXPECT_LE(min_expected_size, message.SpaceUsed()); + } + { + // Messages also have additional allocation that need to be counted. + unittest::TestAllExtensions message; + const int base_size = message.SpaceUsed(); + unittest::ForeignMessage foreign; + foreign.set_c(42); + message.MutableExtension(unittest::optional_foreign_message_extension)-> + CopyFrom(foreign); + int min_expected_size = base_size + foreign.SpaceUsed(); + EXPECT_LE(min_expected_size, message.SpaceUsed()); + } + + // Repeated primitive extensions will increase space used by at least a + // RepeatedField, and will cause additional allocations when the array + // gets too big for the initial space. + // This macro: + // - Adds a value to the repeated extension, then clears it, establishing + // the base size. + // - Adds a small number of values, testing that it doesn't increase the + // SpaceUsed() + // - Adds a large number of values (requiring allocation in the repeated + // field), and ensures that that allocation is included in SpaceUsed() +#define TEST_REPEATED_EXTENSIONS_SPACE_USED(type, cpptype, value) \ + do { \ + unittest::TestAllExtensions message; \ + const int base_size = message.SpaceUsed(); \ + int min_expected_size = sizeof(RepeatedField) + base_size; \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + message.ClearExtension(unittest::repeated_##type##_extension); \ + const int empty_repeated_field_size = message.SpaceUsed(); \ + EXPECT_LE(min_expected_size, empty_repeated_field_size) << #type; \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + EXPECT_EQ(empty_repeated_field_size, message.SpaceUsed()) << #type; \ + message.ClearExtension(unittest::repeated_##type##_extension); \ + for (int i = 0; i < 16; ++i) { \ + message.AddExtension(unittest::repeated_##type##_extension, value); \ + } \ + int expected_size = sizeof(cpptype) * (16 - \ + kMinRepeatedFieldAllocationSize) + empty_repeated_field_size; \ + EXPECT_EQ(expected_size, message.SpaceUsed()) << #type; \ + } while (0) + + TEST_REPEATED_EXTENSIONS_SPACE_USED(int32 , int32 , 101); + TEST_REPEATED_EXTENSIONS_SPACE_USED(int64 , int64 , 102); + TEST_REPEATED_EXTENSIONS_SPACE_USED(uint32 , uint32, 103); + TEST_REPEATED_EXTENSIONS_SPACE_USED(uint64 , uint64, 104); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sint32 , int32 , 105); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sint64 , int64 , 106); + TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed32 , uint32, 107); + TEST_REPEATED_EXTENSIONS_SPACE_USED(fixed64 , uint64, 108); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed32, int32 , 109); + TEST_REPEATED_EXTENSIONS_SPACE_USED(sfixed64, int64 , 110); + TEST_REPEATED_EXTENSIONS_SPACE_USED(float , float , 111); + TEST_REPEATED_EXTENSIONS_SPACE_USED(double , double, 112); + TEST_REPEATED_EXTENSIONS_SPACE_USED(bool , bool , true); + TEST_REPEATED_EXTENSIONS_SPACE_USED(nested_enum, int, + unittest::TestAllTypes::FOO); +#undef TEST_REPEATED_EXTENSIONS_SPACE_USED + // Repeated strings + { + unittest::TestAllExtensions message; + const int base_size = message.SpaceUsed(); + int min_expected_size = sizeof(RepeatedPtrField) + base_size; + const string value(256, 'x'); + // Once items are allocated, they may stick around even when cleared so + // without the hardcore memory management accessors there isn't a notion of + // the empty repeated field memory usage as there is with primitive types. + for (int i = 0; i < 16; ++i) { + message.AddExtension(unittest::repeated_string_extension, value); + } + min_expected_size += (sizeof(value) + value.size()) * + (16 - kMinRepeatedFieldAllocationSize); + EXPECT_LE(min_expected_size, message.SpaceUsed()); + } + // Repeated messages + { + unittest::TestAllExtensions message; + const int base_size = message.SpaceUsed(); + int min_expected_size = sizeof(RepeatedPtrField) + + base_size; + unittest::ForeignMessage prototype; + prototype.set_c(2); + for (int i = 0; i < 16; ++i) { + message.AddExtension(unittest::repeated_foreign_message_extension)-> + CopyFrom(prototype); + } + min_expected_size += + (16 - kMinRepeatedFieldAllocationSize) * prototype.SpaceUsed(); + EXPECT_LE(min_expected_size, message.SpaceUsed()); + } +} + +#ifdef PROTOBUF_HAS_DEATH_TEST + +TEST(ExtensionSetTest, InvalidEnumDeath) { + unittest::TestAllExtensions message; + EXPECT_DEBUG_DEATH( + message.SetExtension(unittest::optional_foreign_enum_extension, + static_cast(53)), + "IsValid"); +} + +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(ExtensionSetTest, DynamicExtensions) { + // Test adding a dynamic extension to a compiled-in message object. + + FileDescriptorProto dynamic_proto; + dynamic_proto.set_name("dynamic_extensions_test.proto"); + dynamic_proto.add_dependency( + unittest::TestAllExtensions::descriptor()->file()->name()); + dynamic_proto.set_package("dynamic_extensions"); + + // Copy the fields and nested types from TestDynamicExtensions into our new + // proto, converting the fields into extensions. + const Descriptor* template_descriptor = + unittest::TestDynamicExtensions::descriptor(); + DescriptorProto template_descriptor_proto; + template_descriptor->CopyTo(&template_descriptor_proto); + dynamic_proto.mutable_message_type()->MergeFrom( + template_descriptor_proto.nested_type()); + dynamic_proto.mutable_enum_type()->MergeFrom( + template_descriptor_proto.enum_type()); + dynamic_proto.mutable_extension()->MergeFrom( + template_descriptor_proto.field()); + + // For each extension that we added... + for (int i = 0; i < dynamic_proto.extension_size(); i++) { + // Set its extendee to TestAllExtensions. + FieldDescriptorProto* extension = dynamic_proto.mutable_extension(i); + extension->set_extendee( + unittest::TestAllExtensions::descriptor()->full_name()); + + // If the field refers to one of the types nested in TestDynamicExtensions, + // make it refer to the type in our dynamic proto instead. + string prefix = "." + template_descriptor->full_name() + "."; + if (extension->has_type_name()) { + string* type_name = extension->mutable_type_name(); + if (HasPrefixString(*type_name, prefix)) { + type_name->replace(0, prefix.size(), ".dynamic_extensions."); + } + } + } + + // Now build the file, using the generated pool as an underlay. + DescriptorPool dynamic_pool(DescriptorPool::generated_pool()); + const FileDescriptor* file = dynamic_pool.BuildFile(dynamic_proto); + ASSERT_TRUE(file != NULL); + DynamicMessageFactory dynamic_factory(&dynamic_pool); + dynamic_factory.SetDelegateToGeneratedFactory(true); + + // Construct a message that we can parse with the extensions we defined. + // Since the extensions were based off of the fields of TestDynamicExtensions, + // we can use that message to create this test message. + string data; + { + unittest::TestDynamicExtensions message; + message.set_scalar_extension(123); + message.set_enum_extension(unittest::FOREIGN_BAR); + message.set_dynamic_enum_extension( + unittest::TestDynamicExtensions::DYNAMIC_BAZ); + message.mutable_message_extension()->set_c(456); + message.mutable_dynamic_message_extension()->set_dynamic_field(789); + message.add_repeated_extension("foo"); + message.add_repeated_extension("bar"); + message.add_packed_extension(12); + message.add_packed_extension(-34); + message.add_packed_extension(56); + message.add_packed_extension(-78); + + // Also add some unknown fields. + + // An unknown enum value (for a known field). + message.mutable_unknown_fields()->AddVarint( + unittest::TestDynamicExtensions::kDynamicEnumExtensionFieldNumber, + 12345); + // A regular unknown field. + message.mutable_unknown_fields()->AddLengthDelimited(54321, "unknown"); + + message.SerializeToString(&data); + } + + // Now we can parse this using our dynamic extension definitions... + unittest::TestAllExtensions message; + { + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory); + ASSERT_TRUE(message.ParseFromCodedStream(&input)); + ASSERT_TRUE(input.ConsumedEntireMessage()); + } + + // Can we print it? + EXPECT_EQ( + "[dynamic_extensions.scalar_extension]: 123\n" + "[dynamic_extensions.enum_extension]: FOREIGN_BAR\n" + "[dynamic_extensions.dynamic_enum_extension]: DYNAMIC_BAZ\n" + "[dynamic_extensions.message_extension] {\n" + " c: 456\n" + "}\n" + "[dynamic_extensions.dynamic_message_extension] {\n" + " dynamic_field: 789\n" + "}\n" + "[dynamic_extensions.repeated_extension]: \"foo\"\n" + "[dynamic_extensions.repeated_extension]: \"bar\"\n" + "[dynamic_extensions.packed_extension]: 12\n" + "[dynamic_extensions.packed_extension]: -34\n" + "[dynamic_extensions.packed_extension]: 56\n" + "[dynamic_extensions.packed_extension]: -78\n" + "2002: 12345\n" + "54321: \"unknown\"\n", + message.DebugString()); + + // Can we serialize it? + // (Don't use EXPECT_EQ because we don't want to dump raw binary data to the + // terminal on failure.) + EXPECT_TRUE(message.SerializeAsString() == data); + + // What if we parse using the reflection-based parser? + { + unittest::TestAllExtensions message2; + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetExtensionRegistry(&dynamic_pool, &dynamic_factory); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message2)); + ASSERT_TRUE(input.ConsumedEntireMessage()); + EXPECT_EQ(message.DebugString(), message2.DebugString()); + } + + // Are the embedded generated types actually using the generated objects? + { + const FieldDescriptor* message_extension = + file->FindExtensionByName("message_extension"); + ASSERT_TRUE(message_extension != NULL); + const Message& sub_message = + message.GetReflection()->GetMessage(message, message_extension); + const unittest::ForeignMessage* typed_sub_message = +#ifdef GOOGLE_PROTOBUF_NO_RTTI + static_cast(&sub_message); +#else + dynamic_cast(&sub_message); +#endif + ASSERT_TRUE(typed_sub_message != NULL); + EXPECT_EQ(456, typed_sub_message->c()); + } + + // What does GetMessage() return for the embedded dynamic type if it isn't + // present? + { + const FieldDescriptor* dynamic_message_extension = + file->FindExtensionByName("dynamic_message_extension"); + ASSERT_TRUE(dynamic_message_extension != NULL); + const Message& parent = unittest::TestAllExtensions::default_instance(); + const Message& sub_message = + parent.GetReflection()->GetMessage(parent, dynamic_message_extension, + &dynamic_factory); + const Message* prototype = + dynamic_factory.GetPrototype(dynamic_message_extension->message_type()); + EXPECT_EQ(prototype, &sub_message); + } +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_enum_reflection.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_enum_reflection.h new file mode 100644 index 000000000..a09a540bf --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_enum_reflection.h @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: jasonh@google.com (Jason Hsueh) +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. +// It provides reflection support for generated enums, and is included in +// generated .pb.h files and should have minimal dependencies. The methods are +// implemented in generated_message_reflection.cc. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ + +#include + +namespace google { +namespace protobuf { + class EnumDescriptor; +} // namespace protobuf + +namespace protobuf { + +// Returns the EnumDescriptor for enum type E, which must be a +// proto-declared enum type. Code generated by the protocol compiler +// will include specializations of this template for each enum type declared. +template +const EnumDescriptor* GetEnumDescriptor(); + +namespace internal { + +// Helper for EnumType_Parse functions: try to parse the string 'name' as an +// enum name of the given type, returning true and filling in value on success, +// or returning false and leaving value unchanged on failure. +LIBPROTOBUF_EXPORT bool ParseNamedEnum(const EnumDescriptor* descriptor, + const string& name, + int* value); + +template +bool ParseNamedEnum(const EnumDescriptor* descriptor, + const string& name, + EnumType* value) { + int tmp; + if (!ParseNamedEnum(descriptor, name, &tmp)) return false; + *value = static_cast(tmp); + return true; +} + +// Just a wrapper around printing the name of a value. The main point of this +// function is not to be inlined, so that you can do this without including +// descriptor.h. +LIBPROTOBUF_EXPORT const string& NameOfEnum(const EnumDescriptor* descriptor, int value); + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.cc new file mode 100644 index 000000000..f4d0851d2 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.cc @@ -0,0 +1,1293 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +int StringSpaceUsedExcludingSelf(const string& str) { + const void* start = &str; + const void* end = &str + 1; + + if (start <= str.data() && str.data() <= end) { + // The string's data is stored inside the string object itself. + return 0; + } else { + return str.capacity(); + } +} + +bool ParseNamedEnum(const EnumDescriptor* descriptor, + const string& name, + int* value) { + const EnumValueDescriptor* d = descriptor->FindValueByName(name); + if (d == NULL) return false; + *value = d->number(); + return true; +} + +const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { + const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); + return (d == NULL ? kEmptyString : d->name()); +} + +// =================================================================== +// Helpers for reporting usage errors (e.g. trying to use GetInt32() on +// a string field). + +namespace { + +void ReportReflectionUsageError( + const Descriptor* descriptor, const FieldDescriptor* field, + const char* method, const char* description) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" << method << "\n" + " Message type: " << descriptor->full_name() << "\n" + " Field : " << field->full_name() << "\n" + " Problem : " << description; +} + +const char* cpptype_names_[FieldDescriptor::MAX_CPPTYPE + 1] = { + "INVALID_CPPTYPE", + "CPPTYPE_INT32", + "CPPTYPE_INT64", + "CPPTYPE_UINT32", + "CPPTYPE_UINT64", + "CPPTYPE_DOUBLE", + "CPPTYPE_FLOAT", + "CPPTYPE_BOOL", + "CPPTYPE_ENUM", + "CPPTYPE_STRING", + "CPPTYPE_MESSAGE" +}; + +static void ReportReflectionUsageTypeError( + const Descriptor* descriptor, const FieldDescriptor* field, + const char* method, + FieldDescriptor::CppType expected_type) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" << method << "\n" + " Message type: " << descriptor->full_name() << "\n" + " Field : " << field->full_name() << "\n" + " Problem : Field is not the right type for this message:\n" + " Expected : " << cpptype_names_[expected_type] << "\n" + " Field type: " << cpptype_names_[field->cpp_type()]; +} + +static void ReportReflectionUsageEnumTypeError( + const Descriptor* descriptor, const FieldDescriptor* field, + const char* method, const EnumValueDescriptor* value) { + GOOGLE_LOG(FATAL) + << "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::" << method << "\n" + " Message type: " << descriptor->full_name() << "\n" + " Field : " << field->full_name() << "\n" + " Problem : Enum value did not match field type:\n" + " Expected : " << field->enum_type()->full_name() << "\n" + " Actual : " << value->full_name(); +} + +#define USAGE_CHECK(CONDITION, METHOD, ERROR_DESCRIPTION) \ + if (!(CONDITION)) \ + ReportReflectionUsageError(descriptor_, field, #METHOD, ERROR_DESCRIPTION) +#define USAGE_CHECK_EQ(A, B, METHOD, ERROR_DESCRIPTION) \ + USAGE_CHECK((A) == (B), METHOD, ERROR_DESCRIPTION) +#define USAGE_CHECK_NE(A, B, METHOD, ERROR_DESCRIPTION) \ + USAGE_CHECK((A) != (B), METHOD, ERROR_DESCRIPTION) + +#define USAGE_CHECK_TYPE(METHOD, CPPTYPE) \ + if (field->cpp_type() != FieldDescriptor::CPPTYPE_##CPPTYPE) \ + ReportReflectionUsageTypeError(descriptor_, field, #METHOD, \ + FieldDescriptor::CPPTYPE_##CPPTYPE) + +#define USAGE_CHECK_ENUM_VALUE(METHOD) \ + if (value->type() != field->enum_type()) \ + ReportReflectionUsageEnumTypeError(descriptor_, field, #METHOD, value) + +#define USAGE_CHECK_MESSAGE_TYPE(METHOD) \ + USAGE_CHECK_EQ(field->containing_type(), descriptor_, \ + METHOD, "Field does not match message type."); +#define USAGE_CHECK_SINGULAR(METHOD) \ + USAGE_CHECK_NE(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ + "Field is repeated; the method requires a singular field.") +#define USAGE_CHECK_REPEATED(METHOD) \ + USAGE_CHECK_EQ(field->label(), FieldDescriptor::LABEL_REPEATED, METHOD, \ + "Field is singular; the method requires a repeated field.") + +#define USAGE_CHECK_ALL(METHOD, LABEL, CPPTYPE) \ + USAGE_CHECK_MESSAGE_TYPE(METHOD); \ + USAGE_CHECK_##LABEL(METHOD); \ + USAGE_CHECK_TYPE(METHOD, CPPTYPE) + +} // namespace + +// =================================================================== + +GeneratedMessageReflection::GeneratedMessageReflection( + const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const DescriptorPool* descriptor_pool, + MessageFactory* factory, + int object_size) + : descriptor_ (descriptor), + default_instance_ (default_instance), + offsets_ (offsets), + has_bits_offset_ (has_bits_offset), + unknown_fields_offset_(unknown_fields_offset), + extensions_offset_(extensions_offset), + object_size_ (object_size), + descriptor_pool_ ((descriptor_pool == NULL) ? + DescriptorPool::generated_pool() : + descriptor_pool), + message_factory_ (factory) { +} + +GeneratedMessageReflection::~GeneratedMessageReflection() {} + +const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( + const Message& message) const { + const void* ptr = reinterpret_cast(&message) + + unknown_fields_offset_; + return *reinterpret_cast(ptr); +} +UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields( + Message* message) const { + void* ptr = reinterpret_cast(message) + unknown_fields_offset_; + return reinterpret_cast(ptr); +} + +int GeneratedMessageReflection::SpaceUsed(const Message& message) const { + // object_size_ already includes the in-memory representation of each field + // in the message, so we only need to account for additional memory used by + // the fields. + int total_size = object_size_; + + total_size += GetUnknownFields(message).SpaceUsedExcludingSelf(); + + if (extensions_offset_ != -1) { + total_size += GetExtensionSet(message).SpaceUsedExcludingSelf(); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + total_size += GetRaw >(message, field) \ + .SpaceUsedExcludingSelf(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + total_size += GetRaw >(message, field) + .SpaceUsedExcludingSelf(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + total_size += + GetRaw(message, field) + .SpaceUsedExcludingSelf >(); + break; + } + } else { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32 : + case FieldDescriptor::CPPTYPE_INT64 : + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT : + case FieldDescriptor::CPPTYPE_BOOL : + case FieldDescriptor::CPPTYPE_ENUM : + // Field is inline, so we've already counted it. + break; + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + const string* ptr = GetField(message, field); + + // Initially, the string points to the default value stored in + // the prototype. Only count the string if it has been changed + // from the default value. + const string* default_ptr = DefaultRaw(field); + + if (ptr != default_ptr) { + // string fields are represented by just a pointer, so also + // include sizeof(string) as well. + total_size += sizeof(*ptr) + StringSpaceUsedExcludingSelf(*ptr); + } + break; + } + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + if (&message == default_instance_) { + // For singular fields, the prototype just stores a pointer to the + // external type's prototype, so there is no extra memory usage. + } else { + const Message* sub_message = GetRaw(message, field); + if (sub_message != NULL) { + total_size += sub_message->SpaceUsed(); + } + } + break; + } + } + } + + return total_size; +} + +void GeneratedMessageReflection::Swap( + Message* message1, + Message* message2) const { + if (message1 == message2) return; + + // TODO(kenton): Other Reflection methods should probably check this too. + GOOGLE_CHECK_EQ(message1->GetReflection(), this) + << "First argument to Swap() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + GOOGLE_CHECK_EQ(message2->GetReflection(), this) + << "Second argument to Swap() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + + uint32* has_bits1 = MutableHasBits(message1); + uint32* has_bits2 = MutableHasBits(message2); + int has_bits_size = (descriptor_->field_count() + 31) / 32; + + for (int i = 0; i < has_bits_size; i++) { + std::swap(has_bits1[i], has_bits2[i]); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw >(message1, field)->Swap( \ + MutableRaw >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32 , int32 ); + SWAP_ARRAYS(INT64 , int64 ); + SWAP_ARRAYS(UINT32, uint32); + SWAP_ARRAYS(UINT64, uint64); + SWAP_ARRAYS(FLOAT , float ); + SWAP_ARRAYS(DOUBLE, double); + SWAP_ARRAYS(BOOL , bool ); + SWAP_ARRAYS(ENUM , int ); +#undef SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message1, field)->Swap( + MutableRaw(message2, field)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } else { + switch (field->cpp_type()) { +#define SWAP_VALUES(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + std::swap(*MutableRaw(message1, field), \ + *MutableRaw(message2, field)); \ + break; + + SWAP_VALUES(INT32 , int32 ); + SWAP_VALUES(INT64 , int64 ); + SWAP_VALUES(UINT32, uint32); + SWAP_VALUES(UINT64, uint64); + SWAP_VALUES(FLOAT , float ); + SWAP_VALUES(DOUBLE, double); + SWAP_VALUES(BOOL , bool ); + SWAP_VALUES(ENUM , int ); +#undef SWAP_VALUES + case FieldDescriptor::CPPTYPE_MESSAGE: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + } + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } + } + + if (extensions_offset_ != -1) { + MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); + } + + MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); +} + +// ------------------------------------------------------------------- + +bool GeneratedMessageReflection::HasField(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(HasField); + USAGE_CHECK_SINGULAR(HasField); + + if (field->is_extension()) { + return GetExtensionSet(message).Has(field->number()); + } else { + return HasBit(message, field); + } +} + +int GeneratedMessageReflection::FieldSize(const Message& message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(FieldSize); + USAGE_CHECK_REPEATED(FieldSize); + + if (field->is_extension()) { + return GetExtensionSet(message).ExtensionSize(field->number()); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + return GetRaw >(message, field).size() + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return GetRaw(message, field).size(); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return 0; + } +} + +void GeneratedMessageReflection::ClearField( + Message* message, const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(ClearField); + + if (field->is_extension()) { + MutableExtensionSet(message)->ClearExtension(field->number()); + } else if (!field->is_repeated()) { + if (HasBit(*message, field)) { + ClearBit(message, field); + + // We need to set the field back to its default value. + switch (field->cpp_type()) { +#define CLEAR_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + *MutableRaw(message, field) = \ + field->default_value_##TYPE(); \ + break; + + CLEAR_TYPE(INT32 , int32 ); + CLEAR_TYPE(INT64 , int64 ); + CLEAR_TYPE(UINT32, uint32); + CLEAR_TYPE(UINT64, uint64); + CLEAR_TYPE(FLOAT , float ); + CLEAR_TYPE(DOUBLE, double); + CLEAR_TYPE(BOOL , bool ); +#undef CLEAR_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + *MutableRaw(message, field) = + field->default_value_enum()->number(); + break; + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + const string* default_ptr = DefaultRaw(field); + string** value = MutableRaw(message, field); + if (*value != default_ptr) { + if (field->has_default_value()) { + (*value)->assign(field->default_value_string()); + } else { + (*value)->clear(); + } + } + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + (*MutableRaw(message, field))->Clear(); + break; + } + } + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field)->Clear(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRaw >(message, field)->Clear(); + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: { + // We don't know which subclass of RepeatedPtrFieldBase the type is, + // so we use RepeatedPtrFieldBase directly. + MutableRaw(message, field) + ->Clear >(); + break; + } + } + } +} + +void GeneratedMessageReflection::RemoveLast( + Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_MESSAGE_TYPE(RemoveLast); + USAGE_CHECK_REPEATED(RemoveLast); + + if (field->is_extension()) { + MutableExtensionSet(message)->RemoveLast(field->number()); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field)->RemoveLast(); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + MutableRaw >(message, field)->RemoveLast(); + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message, field) + ->RemoveLast >(); + break; + } + } +} + +Message* GeneratedMessageReflection::ReleaseLast( + Message* message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE); + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->ReleaseLast(field->number())); + } else { + return MutableRaw(message, field) + ->ReleaseLast >(); + } +} + +void GeneratedMessageReflection::SwapElements( + Message* message, + const FieldDescriptor* field, + int index1, + int index2) const { + USAGE_CHECK_MESSAGE_TYPE(Swap); + USAGE_CHECK_REPEATED(Swap); + + if (field->is_extension()) { + MutableExtensionSet(message)->SwapElements(field->number(), index1, index2); + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(UPPERCASE, LOWERCASE) \ + case FieldDescriptor::CPPTYPE_##UPPERCASE : \ + MutableRaw >(message, field) \ + ->SwapElements(index1, index2); \ + break + + HANDLE_TYPE( INT32, int32); + HANDLE_TYPE( INT64, int64); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE( FLOAT, float); + HANDLE_TYPE( BOOL, bool); + HANDLE_TYPE( ENUM, int); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message, field) + ->SwapElements(index1, index2); + break; + } + } +} + +namespace { +// Comparison functor for sorting FieldDescriptors by field number. +struct FieldNumberSorter { + bool operator()(const FieldDescriptor* left, + const FieldDescriptor* right) const { + return left->number() < right->number(); + } +}; +} // namespace + +void GeneratedMessageReflection::ListFields( + const Message& message, + vector* output) const { + output->clear(); + + // Optimization: The default instance never has any fields set. + if (&message == default_instance_) return; + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_repeated()) { + if (FieldSize(message, field) > 0) { + output->push_back(field); + } + } else { + if (HasBit(message, field)) { + output->push_back(field); + } + } + } + + if (extensions_offset_ != -1) { + GetExtensionSet(message).AppendToList(descriptor_, descriptor_pool_, + output); + } + + // ListFields() must sort output by field number. + sort(output->begin(), output->end(), FieldNumberSorter()); +} + +// ------------------------------------------------------------------- + +#undef DEFINE_PRIMITIVE_ACCESSORS +#define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE) \ + PASSTYPE GeneratedMessageReflection::Get##TYPENAME( \ + const Message& message, const FieldDescriptor* field) const { \ + USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).Get##TYPENAME( \ + field->number(), field->default_value_##PASSTYPE()); \ + } else { \ + return GetField(message, field); \ + } \ + } \ + \ + void GeneratedMessageReflection::Set##TYPENAME( \ + Message* message, const FieldDescriptor* field, \ + PASSTYPE value) const { \ + USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE); \ + if (field->is_extension()) { \ + return MutableExtensionSet(message)->Set##TYPENAME( \ + field->number(), field->type(), value, field); \ + } else { \ + SetField(message, field, value); \ + } \ + } \ + \ + PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME( \ + const Message& message, \ + const FieldDescriptor* field, int index) const { \ + USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + return GetExtensionSet(message).GetRepeated##TYPENAME( \ + field->number(), index); \ + } else { \ + return GetRepeatedField(message, field, index); \ + } \ + } \ + \ + void GeneratedMessageReflection::SetRepeated##TYPENAME( \ + Message* message, const FieldDescriptor* field, \ + int index, PASSTYPE value) const { \ + USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->SetRepeated##TYPENAME( \ + field->number(), index, value); \ + } else { \ + SetRepeatedField(message, field, index, value); \ + } \ + } \ + \ + void GeneratedMessageReflection::Add##TYPENAME( \ + Message* message, const FieldDescriptor* field, \ + PASSTYPE value) const { \ + USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE); \ + if (field->is_extension()) { \ + MutableExtensionSet(message)->Add##TYPENAME( \ + field->number(), field->type(), field->options().packed(), value, \ + field); \ + } else { \ + AddField(message, field, value); \ + } \ + } + +DEFINE_PRIMITIVE_ACCESSORS(Int32 , int32 , int32 , INT32 ) +DEFINE_PRIMITIVE_ACCESSORS(Int64 , int64 , int64 , INT64 ) +DEFINE_PRIMITIVE_ACCESSORS(UInt32, uint32, uint32, UINT32) +DEFINE_PRIMITIVE_ACCESSORS(UInt64, uint64, uint64, UINT64) +DEFINE_PRIMITIVE_ACCESSORS(Float , float , float , FLOAT ) +DEFINE_PRIMITIVE_ACCESSORS(Double, double, double, DOUBLE) +DEFINE_PRIMITIVE_ACCESSORS(Bool , bool , bool , BOOL ) +#undef DEFINE_PRIMITIVE_ACCESSORS + +// ------------------------------------------------------------------- + +string GeneratedMessageReflection::GetString( + const Message& message, const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetString, SINGULAR, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetString(field->number(), + field->default_value_string()); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return *GetField(message, field); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return kEmptyString; // Make compiler happy. + } +} + +const string& GeneratedMessageReflection::GetStringReference( + const Message& message, + const FieldDescriptor* field, string* scratch) const { + USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetString(field->number(), + field->default_value_string()); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return *GetField(message, field); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return kEmptyString; // Make compiler happy. + } +} + + +void GeneratedMessageReflection::SetString( + Message* message, const FieldDescriptor* field, + const string& value) const { + USAGE_CHECK_ALL(SetString, SINGULAR, STRING); + if (field->is_extension()) { + return MutableExtensionSet(message)->SetString(field->number(), + field->type(), value, field); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + string** ptr = MutableField(message, field); + if (*ptr == DefaultRaw(field)) { + *ptr = new string(value); + } else { + (*ptr)->assign(value); + } + break; + } + } + } +} + + +string GeneratedMessageReflection::GetRepeatedString( + const Message& message, const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetRepeatedString(field->number(), index); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return GetRepeatedPtrField(message, field, index); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return kEmptyString; // Make compiler happy. + } +} + +const string& GeneratedMessageReflection::GetRepeatedStringReference( + const Message& message, const FieldDescriptor* field, + int index, string* scratch) const { + USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); + if (field->is_extension()) { + return GetExtensionSet(message).GetRepeatedString(field->number(), index); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + return GetRepeatedPtrField(message, field, index); + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return kEmptyString; // Make compiler happy. + } +} + + +void GeneratedMessageReflection::SetRepeatedString( + Message* message, const FieldDescriptor* field, + int index, const string& value) const { + USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING); + if (field->is_extension()) { + MutableExtensionSet(message)->SetRepeatedString( + field->number(), index, value); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + *MutableRepeatedField(message, field, index) = value; + break; + } + } +} + + +void GeneratedMessageReflection::AddString( + Message* message, const FieldDescriptor* field, + const string& value) const { + USAGE_CHECK_ALL(AddString, REPEATED, STRING); + if (field->is_extension()) { + MutableExtensionSet(message)->AddString(field->number(), + field->type(), value, field); + } else { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + *AddField(message, field) = value; + break; + } + } +} + + +// ------------------------------------------------------------------- + +const EnumValueDescriptor* GeneratedMessageReflection::GetEnum( + const Message& message, const FieldDescriptor* field) const { + USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM); + + int value; + if (field->is_extension()) { + value = GetExtensionSet(message).GetEnum( + field->number(), field->default_value_enum()->number()); + } else { + value = GetField(message, field); + } + const EnumValueDescriptor* result = + field->enum_type()->FindValueByNumber(value); + GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field " + << field->full_name() << " of type " + << field->enum_type()->full_name() << "."; + return result; +} + +void GeneratedMessageReflection::SetEnum( + Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { + USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM); + USAGE_CHECK_ENUM_VALUE(SetEnum); + + if (field->is_extension()) { + MutableExtensionSet(message)->SetEnum(field->number(), field->type(), + value->number(), field); + } else { + SetField(message, field, value->number()); + } +} + +const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum( + const Message& message, const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM); + + int value; + if (field->is_extension()) { + value = GetExtensionSet(message).GetRepeatedEnum(field->number(), index); + } else { + value = GetRepeatedField(message, field, index); + } + const EnumValueDescriptor* result = + field->enum_type()->FindValueByNumber(value); + GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field " + << field->full_name() << " of type " + << field->enum_type()->full_name() << "."; + return result; +} + +void GeneratedMessageReflection::SetRepeatedEnum( + Message* message, + const FieldDescriptor* field, int index, + const EnumValueDescriptor* value) const { + USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM); + USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum); + + if (field->is_extension()) { + MutableExtensionSet(message)->SetRepeatedEnum( + field->number(), index, value->number()); + } else { + SetRepeatedField(message, field, index, value->number()); + } +} + +void GeneratedMessageReflection::AddEnum( + Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const { + USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM); + USAGE_CHECK_ENUM_VALUE(AddEnum); + + if (field->is_extension()) { + MutableExtensionSet(message)->AddEnum(field->number(), field->type(), + field->options().packed(), + value->number(), field); + } else { + AddField(message, field, value->number()); + } +} + +// ------------------------------------------------------------------- + +const Message& GeneratedMessageReflection::GetMessage( + const Message& message, const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE); + + if (factory == NULL) factory = message_factory_; + + if (field->is_extension()) { + return static_cast( + GetExtensionSet(message).GetMessage( + field->number(), field->message_type(), factory)); + } else { + const Message* result; + result = GetRaw(message, field); + if (result == NULL) { + result = DefaultRaw(field); + } + return *result; + } +} + +Message* GeneratedMessageReflection::MutableMessage( + Message* message, const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + + if (factory == NULL) factory = message_factory_; + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->MutableMessage(field, factory)); + } else { + Message* result; + Message** result_holder = MutableField(message, field); + if (*result_holder == NULL) { + const Message* default_message = DefaultRaw(field); + *result_holder = default_message->New(); + } + result = *result_holder; + return result; + } +} + +Message* GeneratedMessageReflection::ReleaseMessage( + Message* message, + const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE); + + if (factory == NULL) factory = message_factory_; + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->ReleaseMessage(field, factory)); + } else { + ClearBit(message, field); + Message** result = MutableRaw(message, field); + Message* ret = *result; + *result = NULL; + return ret; + } +} + +const Message& GeneratedMessageReflection::GetRepeatedMessage( + const Message& message, const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + return static_cast( + GetExtensionSet(message).GetRepeatedMessage(field->number(), index)); + } else { + return GetRaw(message, field) + .Get >(index); + } +} + +Message* GeneratedMessageReflection::MutableRepeatedMessage( + Message* message, const FieldDescriptor* field, int index) const { + USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE); + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->MutableRepeatedMessage( + field->number(), index)); + } else { + return MutableRaw(message, field) + ->Mutable >(index); + } +} + +Message* GeneratedMessageReflection::AddMessage( + Message* message, const FieldDescriptor* field, + MessageFactory* factory) const { + USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE); + + if (factory == NULL) factory = message_factory_; + + if (field->is_extension()) { + return static_cast( + MutableExtensionSet(message)->AddMessage(field, factory)); + } else { + // We can't use AddField() because RepeatedPtrFieldBase doesn't + // know how to allocate one. + RepeatedPtrFieldBase* repeated = + MutableRaw(message, field); + Message* result = repeated->AddFromCleared >(); + if (result == NULL) { + // We must allocate a new object. + const Message* prototype; + if (repeated->size() == 0) { + prototype = factory->GetPrototype(field->message_type()); + } else { + prototype = &repeated->Get >(0); + } + result = prototype->New(); + repeated->AddAllocated >(result); + } + return result; + } +} + +void* GeneratedMessageReflection::MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, + FieldDescriptor::CppType cpptype, + int ctype, const Descriptor* desc) const { + USAGE_CHECK_REPEATED("MutableRawRepeatedField"); + if (field->cpp_type() != cpptype) + ReportReflectionUsageTypeError(descriptor_, + field, "MutableRawRepeatedField", cpptype); + if (ctype >= 0) + GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch"; + if (desc != NULL) + GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; + if (field->is_extension()) + return MutableExtensionSet(message)->MutableRawRepeatedField( + field->number()); + else + return reinterpret_cast(message) + offsets_[field->index()]; +} + +// ----------------------------------------------------------------------------- + +const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( + const string& name) const { + if (extensions_offset_ == -1) return NULL; + + const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name); + if (result != NULL && result->containing_type() == descriptor_) { + return result; + } + + if (descriptor_->options().message_set_wire_format()) { + // MessageSet extensions may be identified by type name. + const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name); + if (type != NULL) { + // Look for a matching extension in the foreign type's scope. + for (int i = 0; i < type->extension_count(); i++) { + const FieldDescriptor* extension = type->extension(i); + if (extension->containing_type() == descriptor_ && + extension->type() == FieldDescriptor::TYPE_MESSAGE && + extension->is_optional() && + extension->message_type() == type) { + // Found it. + return extension; + } + } + } + } + + return NULL; +} + +const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( + int number) const { + if (extensions_offset_ == -1) return NULL; + return descriptor_pool_->FindExtensionByNumber(descriptor_, number); +} + +// =================================================================== +// Some private helpers. + +// These simple template accessors obtain pointers (or references) to +// the given field. +template +inline const Type& GeneratedMessageReflection::GetRaw( + const Message& message, const FieldDescriptor* field) const { + const void* ptr = reinterpret_cast(&message) + + offsets_[field->index()]; + return *reinterpret_cast(ptr); +} + +template +inline Type* GeneratedMessageReflection::MutableRaw( + Message* message, const FieldDescriptor* field) const { + void* ptr = reinterpret_cast(message) + offsets_[field->index()]; + return reinterpret_cast(ptr); +} + +template +inline const Type& GeneratedMessageReflection::DefaultRaw( + const FieldDescriptor* field) const { + const void* ptr = reinterpret_cast(default_instance_) + + offsets_[field->index()]; + return *reinterpret_cast(ptr); +} + +inline const uint32* GeneratedMessageReflection::GetHasBits( + const Message& message) const { + const void* ptr = reinterpret_cast(&message) + has_bits_offset_; + return reinterpret_cast(ptr); +} +inline uint32* GeneratedMessageReflection::MutableHasBits( + Message* message) const { + void* ptr = reinterpret_cast(message) + has_bits_offset_; + return reinterpret_cast(ptr); +} + +inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet( + const Message& message) const { + GOOGLE_DCHECK_NE(extensions_offset_, -1); + const void* ptr = reinterpret_cast(&message) + + extensions_offset_; + return *reinterpret_cast(ptr); +} +inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet( + Message* message) const { + GOOGLE_DCHECK_NE(extensions_offset_, -1); + void* ptr = reinterpret_cast(message) + extensions_offset_; + return reinterpret_cast(ptr); +} + +// Simple accessors for manipulating has_bits_. +inline bool GeneratedMessageReflection::HasBit( + const Message& message, const FieldDescriptor* field) const { + return GetHasBits(message)[field->index() / 32] & + (1 << (field->index() % 32)); +} + +inline void GeneratedMessageReflection::SetBit( + Message* message, const FieldDescriptor* field) const { + MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32)); +} + +inline void GeneratedMessageReflection::ClearBit( + Message* message, const FieldDescriptor* field) const { + MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32)); +} + +// Template implementations of basic accessors. Inline because each +// template instance is only called from one location. These are +// used for all types except messages. +template +inline const Type& GeneratedMessageReflection::GetField( + const Message& message, const FieldDescriptor* field) const { + return GetRaw(message, field); +} + +template +inline void GeneratedMessageReflection::SetField( + Message* message, const FieldDescriptor* field, const Type& value) const { + *MutableRaw(message, field) = value; + SetBit(message, field); +} + +template +inline Type* GeneratedMessageReflection::MutableField( + Message* message, const FieldDescriptor* field) const { + SetBit(message, field); + return MutableRaw(message, field); +} + +template +inline const Type& GeneratedMessageReflection::GetRepeatedField( + const Message& message, const FieldDescriptor* field, int index) const { + return GetRaw >(message, field).Get(index); +} + +template +inline const Type& GeneratedMessageReflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field, int index) const { + return GetRaw >(message, field).Get(index); +} + +template +inline void GeneratedMessageReflection::SetRepeatedField( + Message* message, const FieldDescriptor* field, + int index, Type value) const { + MutableRaw >(message, field)->Set(index, value); +} + +template +inline Type* GeneratedMessageReflection::MutableRepeatedField( + Message* message, const FieldDescriptor* field, int index) const { + RepeatedPtrField* repeated = + MutableRaw >(message, field); + return repeated->Mutable(index); +} + +template +inline void GeneratedMessageReflection::AddField( + Message* message, const FieldDescriptor* field, const Type& value) const { + MutableRaw >(message, field)->Add(value); +} + +template +inline Type* GeneratedMessageReflection::AddField( + Message* message, const FieldDescriptor* field) const { + RepeatedPtrField* repeated = + MutableRaw >(message, field); + return repeated->Add(); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.h new file mode 100644 index 000000000..c1c142fa8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection.h @@ -0,0 +1,419 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ + +#include +#include +#include +// TODO(jasonh): Remove this once the compiler change to directly include this +// is released to components. +#include +#include +#include + + +namespace google { +namespace upb { +namespace google_opensource { +class GMR_Handlers; +} // namespace google_opensource +} // namespace upb + +namespace protobuf { + class DescriptorPool; +} + +namespace protobuf { +namespace internal { + +// Defined in this file. +class GeneratedMessageReflection; + +// Defined in other files. +class ExtensionSet; // extension_set.h + +// THIS CLASS IS NOT INTENDED FOR DIRECT USE. It is intended for use +// by generated code. This class is just a big hack that reduces code +// size. +// +// A GeneratedMessageReflection is an implementation of Reflection +// which expects all fields to be backed by simple variables located in +// memory. The locations are given using a base pointer and a set of +// offsets. +// +// It is required that the user represents fields of each type in a standard +// way, so that GeneratedMessageReflection can cast the void* pointer to +// the appropriate type. For primitive fields and string fields, each field +// should be represented using the obvious C++ primitive type. Enums and +// Messages are different: +// - Singular Message fields are stored as a pointer to a Message. These +// should start out NULL, except for in the default instance where they +// should start out pointing to other default instances. +// - Enum fields are stored as an int. This int must always contain +// a valid value, such that EnumDescriptor::FindValueByNumber() would +// not return NULL. +// - Repeated fields are stored as RepeatedFields or RepeatedPtrFields +// of whatever type the individual field would be. Strings and +// Messages use RepeatedPtrFields while everything else uses +// RepeatedFields. +class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { + public: + // Constructs a GeneratedMessageReflection. + // Parameters: + // descriptor: The descriptor for the message type being implemented. + // default_instance: The default instance of the message. This is only + // used to obtain pointers to default instances of embedded + // messages, which GetMessage() will return if the particular + // sub-message has not been initialized yet. (Thus, all + // embedded message fields *must* have non-NULL pointers + // in the default instance.) + // offsets: An array of ints giving the byte offsets, relative to + // the start of the message object, of each field. These can + // be computed at compile time using the + // GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro, defined + // below. + // has_bits_offset: Offset in the message of an array of uint32s of size + // descriptor->field_count()/32, rounded up. This is a + // bitfield where each bit indicates whether or not the + // corresponding field of the message has been initialized. + // The bit for field index i is obtained by the expression: + // has_bits[i / 32] & (1 << (i % 32)) + // unknown_fields_offset: Offset in the message of the UnknownFieldSet for + // the message. + // extensions_offset: Offset in the message of the ExtensionSet for the + // message, or -1 if the message type has no extension + // ranges. + // pool: DescriptorPool to search for extension definitions. Only + // used by FindKnownExtensionByName() and + // FindKnownExtensionByNumber(). + // factory: MessageFactory to use to construct extension messages. + // object_size: The size of a message object of this type, as measured + // by sizeof(). + GeneratedMessageReflection(const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const DescriptorPool* pool, + MessageFactory* factory, + int object_size); + ~GeneratedMessageReflection(); + + // implements Reflection ------------------------------------------- + + const UnknownFieldSet& GetUnknownFields(const Message& message) const; + UnknownFieldSet* MutableUnknownFields(Message* message) const; + + int SpaceUsed(const Message& message) const; + + bool HasField(const Message& message, const FieldDescriptor* field) const; + int FieldSize(const Message& message, const FieldDescriptor* field) const; + void ClearField(Message* message, const FieldDescriptor* field) const; + void RemoveLast(Message* message, const FieldDescriptor* field) const; + Message* ReleaseLast(Message* message, const FieldDescriptor* field) const; + void Swap(Message* message1, Message* message2) const; + void SwapElements(Message* message, const FieldDescriptor* field, + int index1, int index2) const; + void ListFields(const Message& message, + vector* output) const; + + int32 GetInt32 (const Message& message, + const FieldDescriptor* field) const; + int64 GetInt64 (const Message& message, + const FieldDescriptor* field) const; + uint32 GetUInt32(const Message& message, + const FieldDescriptor* field) const; + uint64 GetUInt64(const Message& message, + const FieldDescriptor* field) const; + float GetFloat (const Message& message, + const FieldDescriptor* field) const; + double GetDouble(const Message& message, + const FieldDescriptor* field) const; + bool GetBool (const Message& message, + const FieldDescriptor* field) const; + string GetString(const Message& message, + const FieldDescriptor* field) const; + const string& GetStringReference(const Message& message, + const FieldDescriptor* field, + string* scratch) const; + const EnumValueDescriptor* GetEnum(const Message& message, + const FieldDescriptor* field) const; + const Message& GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const; + + void SetInt32 (Message* message, + const FieldDescriptor* field, int32 value) const; + void SetInt64 (Message* message, + const FieldDescriptor* field, int64 value) const; + void SetUInt32(Message* message, + const FieldDescriptor* field, uint32 value) const; + void SetUInt64(Message* message, + const FieldDescriptor* field, uint64 value) const; + void SetFloat (Message* message, + const FieldDescriptor* field, float value) const; + void SetDouble(Message* message, + const FieldDescriptor* field, double value) const; + void SetBool (Message* message, + const FieldDescriptor* field, bool value) const; + void SetString(Message* message, + const FieldDescriptor* field, + const string& value) const; + void SetEnum (Message* message, const FieldDescriptor* field, + const EnumValueDescriptor* value) const; + Message* MutableMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = NULL) const; + Message* ReleaseMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = NULL) const; + + int32 GetRepeatedInt32 (const Message& message, + const FieldDescriptor* field, int index) const; + int64 GetRepeatedInt64 (const Message& message, + const FieldDescriptor* field, int index) const; + uint32 GetRepeatedUInt32(const Message& message, + const FieldDescriptor* field, int index) const; + uint64 GetRepeatedUInt64(const Message& message, + const FieldDescriptor* field, int index) const; + float GetRepeatedFloat (const Message& message, + const FieldDescriptor* field, int index) const; + double GetRepeatedDouble(const Message& message, + const FieldDescriptor* field, int index) const; + bool GetRepeatedBool (const Message& message, + const FieldDescriptor* field, int index) const; + string GetRepeatedString(const Message& message, + const FieldDescriptor* field, int index) const; + const string& GetRepeatedStringReference(const Message& message, + const FieldDescriptor* field, + int index, string* scratch) const; + const EnumValueDescriptor* GetRepeatedEnum(const Message& message, + const FieldDescriptor* field, + int index) const; + const Message& GetRepeatedMessage(const Message& message, + const FieldDescriptor* field, + int index) const; + + // Set the value of a field. + void SetRepeatedInt32 (Message* message, + const FieldDescriptor* field, int index, int32 value) const; + void SetRepeatedInt64 (Message* message, + const FieldDescriptor* field, int index, int64 value) const; + void SetRepeatedUInt32(Message* message, + const FieldDescriptor* field, int index, uint32 value) const; + void SetRepeatedUInt64(Message* message, + const FieldDescriptor* field, int index, uint64 value) const; + void SetRepeatedFloat (Message* message, + const FieldDescriptor* field, int index, float value) const; + void SetRepeatedDouble(Message* message, + const FieldDescriptor* field, int index, double value) const; + void SetRepeatedBool (Message* message, + const FieldDescriptor* field, int index, bool value) const; + void SetRepeatedString(Message* message, + const FieldDescriptor* field, int index, + const string& value) const; + void SetRepeatedEnum(Message* message, const FieldDescriptor* field, + int index, const EnumValueDescriptor* value) const; + // Get a mutable pointer to a field with a message type. + Message* MutableRepeatedMessage(Message* message, + const FieldDescriptor* field, + int index) const; + + void AddInt32 (Message* message, + const FieldDescriptor* field, int32 value) const; + void AddInt64 (Message* message, + const FieldDescriptor* field, int64 value) const; + void AddUInt32(Message* message, + const FieldDescriptor* field, uint32 value) const; + void AddUInt64(Message* message, + const FieldDescriptor* field, uint64 value) const; + void AddFloat (Message* message, + const FieldDescriptor* field, float value) const; + void AddDouble(Message* message, + const FieldDescriptor* field, double value) const; + void AddBool (Message* message, + const FieldDescriptor* field, bool value) const; + void AddString(Message* message, + const FieldDescriptor* field, const string& value) const; + void AddEnum(Message* message, + const FieldDescriptor* field, + const EnumValueDescriptor* value) const; + Message* AddMessage(Message* message, const FieldDescriptor* field, + MessageFactory* factory = NULL) const; + + const FieldDescriptor* FindKnownExtensionByName(const string& name) const; + const FieldDescriptor* FindKnownExtensionByNumber(int number) const; + + protected: + virtual void* MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, + int ctype, const Descriptor* desc) const; + + private: + friend class GeneratedMessage; + + // To parse directly into a proto2 generated class, the class GMR_Handlers + // needs access to member offsets and hasbits. + friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + + const Descriptor* descriptor_; + const Message* default_instance_; + const int* offsets_; + + int has_bits_offset_; + int unknown_fields_offset_; + int extensions_offset_; + int object_size_; + + const DescriptorPool* descriptor_pool_; + MessageFactory* message_factory_; + + template + inline const Type& GetRaw(const Message& message, + const FieldDescriptor* field) const; + template + inline Type* MutableRaw(Message* message, + const FieldDescriptor* field) const; + template + inline const Type& DefaultRaw(const FieldDescriptor* field) const; + + inline const uint32* GetHasBits(const Message& message) const; + inline uint32* MutableHasBits(Message* message) const; + inline const ExtensionSet& GetExtensionSet(const Message& message) const; + inline ExtensionSet* MutableExtensionSet(Message* message) const; + + inline bool HasBit(const Message& message, + const FieldDescriptor* field) const; + inline void SetBit(Message* message, + const FieldDescriptor* field) const; + inline void ClearBit(Message* message, + const FieldDescriptor* field) const; + + template + inline const Type& GetField(const Message& message, + const FieldDescriptor* field) const; + template + inline void SetField(Message* message, + const FieldDescriptor* field, const Type& value) const; + template + inline Type* MutableField(Message* message, + const FieldDescriptor* field) const; + template + inline const Type& GetRepeatedField(const Message& message, + const FieldDescriptor* field, + int index) const; + template + inline const Type& GetRepeatedPtrField(const Message& message, + const FieldDescriptor* field, + int index) const; + template + inline void SetRepeatedField(Message* message, + const FieldDescriptor* field, int index, + Type value) const; + template + inline Type* MutableRepeatedField(Message* message, + const FieldDescriptor* field, + int index) const; + template + inline void AddField(Message* message, + const FieldDescriptor* field, const Type& value) const; + template + inline Type* AddField(Message* message, + const FieldDescriptor* field) const; + + int GetExtensionNumberOrDie(const Descriptor* type) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection); +}; + +// Returns the offset of the given field within the given aggregate type. +// This is equivalent to the ANSI C offsetof() macro. However, according +// to the C++ standard, offsetof() only works on POD types, and GCC +// enforces this requirement with a warning. In practice, this rule is +// unnecessarily strict; there is probably no compiler or platform on +// which the offsets of the direct fields of a class are non-constant. +// Fields inherited from superclasses *can* have non-constant offsets, +// but that's not what this macro will be used for. +// +// Note that we calculate relative to the pointer value 16 here since if we +// just use zero, GCC complains about dereferencing a NULL pointer. We +// choose 16 rather than some other number just in case the compiler would +// be confused by an unaligned pointer. +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \ + static_cast( \ + reinterpret_cast( \ + &reinterpret_cast(16)->FIELD) - \ + reinterpret_cast(16)) + +// There are some places in proto2 where dynamic_cast would be useful as an +// optimization. For example, take Message::MergeFrom(const Message& other). +// For a given generated message FooMessage, we generate these two methods: +// void MergeFrom(const FooMessage& other); +// void MergeFrom(const Message& other); +// The former method can be implemented directly in terms of FooMessage's +// inline accessors, but the latter method must work with the reflection +// interface. However, if the parameter to the latter method is actually of +// type FooMessage, then we'd like to be able to just call the other method +// as an optimization. So, we use dynamic_cast to check this. +// +// That said, dynamic_cast requires RTTI, which many people like to disable +// for performance and code size reasons. When RTTI is not available, we +// still need to produce correct results. So, in this case we have to fall +// back to using reflection, which is what we would have done anyway if the +// objects were not of the exact same class. +// +// dynamic_cast_if_available() implements this logic. If RTTI is +// enabled, it does a dynamic_cast. If RTTI is disabled, it just returns +// NULL. +// +// If you need to compile without RTTI, simply #define GOOGLE_PROTOBUF_NO_RTTI. +// On MSVC, this should be detected automatically. +template +inline To dynamic_cast_if_available(From from) { +#if defined(GOOGLE_PROTOBUF_NO_RTTI) || (defined(_MSC_VER)&&!defined(_CPPRTTI)) + return NULL; +#else + return dynamic_cast(from); +#endif +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc new file mode 100644 index 000000000..39aa55fb4 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_reflection_unittest.cc @@ -0,0 +1,484 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// To test GeneratedMessageReflection, we actually let the protocol compiler +// generate a full protocol message implementation and then test its +// reflection interface. This is much easier and more maintainable than +// trying to create our own Message class for GeneratedMessageReflection +// to wrap. +// +// The tests here closely mirror some of the tests in +// compiler/cpp/unittest, except using the reflection interface +// rather than generated accessors. + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace { + +// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. +const FieldDescriptor* F(const string& name) { + const FieldDescriptor* result = + unittest::TestAllTypes::descriptor()->FindFieldByName(name); + GOOGLE_CHECK(result != NULL); + return result; +} + +TEST(GeneratedMessageReflectionTest, Defaults) { + // Check that all default values are set correctly in the initial message. + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + reflection_tester.ExpectClearViaReflection(message); + + const Reflection* reflection = message.GetReflection(); + + // Messages should return pointers to default instances until first use. + // (This is not checked by ExpectClear() since it is not actually true after + // the fields have been set and then cleared.) + EXPECT_EQ(&unittest::TestAllTypes::OptionalGroup::default_instance(), + &reflection->GetMessage(message, F("optionalgroup"))); + EXPECT_EQ(&unittest::TestAllTypes::NestedMessage::default_instance(), + &reflection->GetMessage(message, F("optional_nested_message"))); + EXPECT_EQ(&unittest::ForeignMessage::default_instance(), + &reflection->GetMessage(message, F("optional_foreign_message"))); + EXPECT_EQ(&unittest_import::ImportMessage::default_instance(), + &reflection->GetMessage(message, F("optional_import_message"))); +} + +TEST(GeneratedMessageReflectionTest, Accessors) { + // Set every field to a unique value then go back and check all those + // values. + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + reflection_tester.SetAllFieldsViaReflection(&message); + TestUtil::ExpectAllFieldsSet(message); + reflection_tester.ExpectAllFieldsSetViaReflection(message); + + reflection_tester.ModifyRepeatedFieldsViaReflection(&message); + TestUtil::ExpectRepeatedFieldsModified(message); +} + +TEST(GeneratedMessageReflectionTest, GetStringReference) { + // Test that GetStringReference() returns the underlying string when it is + // a normal string field. + unittest::TestAllTypes message; + message.set_optional_string("foo"); + message.add_repeated_string("foo"); + + const Reflection* reflection = message.GetReflection(); + string scratch; + + EXPECT_EQ(&message.optional_string(), + &reflection->GetStringReference(message, F("optional_string"), &scratch)) + << "For simple string fields, GetStringReference() should return a " + "reference to the underlying string."; + EXPECT_EQ(&message.repeated_string(0), + &reflection->GetRepeatedStringReference(message, F("repeated_string"), + 0, &scratch)) + << "For simple string fields, GetRepeatedStringReference() should return " + "a reference to the underlying string."; +} + + +TEST(GeneratedMessageReflectionTest, DefaultsAfterClear) { + // Check that after setting all fields and then clearing, getting an + // embedded message does NOT return the default instance. + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + TestUtil::SetAllFields(&message); + message.Clear(); + + const Reflection* reflection = message.GetReflection(); + + EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(), + &reflection->GetMessage(message, F("optionalgroup"))); + EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), + &reflection->GetMessage(message, F("optional_nested_message"))); + EXPECT_NE(&unittest::ForeignMessage::default_instance(), + &reflection->GetMessage(message, F("optional_foreign_message"))); + EXPECT_NE(&unittest_import::ImportMessage::default_instance(), + &reflection->GetMessage(message, F("optional_import_message"))); +} + + +TEST(GeneratedMessageReflectionTest, Swap) { + unittest::TestAllTypes message1; + unittest::TestAllTypes message2; + + TestUtil::SetAllFields(&message1); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectClear(message1); + TestUtil::ExpectAllFieldsSet(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapWithBothSet) { + unittest::TestAllTypes message1; + unittest::TestAllTypes message2; + + TestUtil::SetAllFields(&message1); + TestUtil::SetAllFields(&message2); + TestUtil::ModifyRepeatedFields(&message2); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectRepeatedFieldsModified(message1); + TestUtil::ExpectAllFieldsSet(message2); + + message1.set_optional_int32(532819); + + reflection->Swap(&message1, &message2); + + EXPECT_EQ(532819, message2.optional_int32()); +} + +TEST(GeneratedMessageReflectionTest, SwapExtensions) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectExtensionsClear(message1); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapUnknown) { + unittest::TestEmptyMessage message1, message2; + + message1.mutable_unknown_fields()->AddVarint(1234, 1); + + EXPECT_EQ(1, message1.unknown_fields().field_count()); + EXPECT_EQ(0, message2.unknown_fields().field_count()); + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + EXPECT_EQ(0, message1.unknown_fields().field_count()); + EXPECT_EQ(1, message2.unknown_fields().field_count()); +} + +TEST(GeneratedMessageReflectionTest, RemoveLast) { + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + TestUtil::SetAllFields(&message); + + reflection_tester.RemoveLastRepeatedsViaReflection(&message); + + TestUtil::ExpectLastRepeatedsRemoved(message); +} + +TEST(GeneratedMessageReflectionTest, RemoveLastExtensions) { + unittest::TestAllExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + + TestUtil::SetAllExtensions(&message); + + reflection_tester.RemoveLastRepeatedsViaReflection(&message); + + TestUtil::ExpectLastRepeatedExtensionsRemoved(message); +} + +TEST(GeneratedMessageReflectionTest, ReleaseLast) { + unittest::TestAllTypes message; + const Descriptor* descriptor = message.GetDescriptor(); + TestUtil::ReflectionTester reflection_tester(descriptor); + + TestUtil::SetAllFields(&message); + + reflection_tester.ReleaseLastRepeatedsViaReflection(&message, false); + + TestUtil::ExpectLastRepeatedsReleased(message); + + // Now test that we actually release the right message. + message.Clear(); + TestUtil::SetAllFields(&message); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + const protobuf_unittest::ForeignMessage* expected = + message.mutable_repeated_foreign_message(1); + scoped_ptr released(message.GetReflection()->ReleaseLast( + &message, descriptor->FindFieldByName("repeated_foreign_message"))); + EXPECT_EQ(expected, released.get()); +} + +TEST(GeneratedMessageReflectionTest, ReleaseLastExtensions) { + unittest::TestAllExtensions message; + const Descriptor* descriptor = message.GetDescriptor(); + TestUtil::ReflectionTester reflection_tester(descriptor); + + TestUtil::SetAllExtensions(&message); + + reflection_tester.ReleaseLastRepeatedsViaReflection(&message, true); + + TestUtil::ExpectLastRepeatedExtensionsReleased(message); + + // Now test that we actually release the right message. + message.Clear(); + TestUtil::SetAllExtensions(&message); + ASSERT_EQ(2, message.ExtensionSize( + unittest::repeated_foreign_message_extension)); + const protobuf_unittest::ForeignMessage* expected = message.MutableExtension( + unittest::repeated_foreign_message_extension, 1); + scoped_ptr released(message.GetReflection()->ReleaseLast( + &message, descriptor->file()->FindExtensionByName( + "repeated_foreign_message_extension"))); + EXPECT_EQ(expected, released.get()); + +} + +TEST(GeneratedMessageReflectionTest, SwapRepeatedElements) { + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + TestUtil::SetAllFields(&message); + + // Swap and test that fields are all swapped. + reflection_tester.SwapRepeatedsViaReflection(&message); + TestUtil::ExpectRepeatedsSwapped(message); + + // Swap back and test that fields are all back to original values. + reflection_tester.SwapRepeatedsViaReflection(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GeneratedMessageReflectionTest, SwapRepeatedElementsExtension) { + unittest::TestAllExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + + TestUtil::SetAllExtensions(&message); + + // Swap and test that fields are all swapped. + reflection_tester.SwapRepeatedsViaReflection(&message); + TestUtil::ExpectRepeatedExtensionsSwapped(message); + + // Swap back and test that fields are all back to original values. + reflection_tester.SwapRepeatedsViaReflection(&message); + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(GeneratedMessageReflectionTest, Extensions) { + // Set every extension to a unique value then go back and check all those + // values. + unittest::TestAllExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + + reflection_tester.SetAllFieldsViaReflection(&message); + TestUtil::ExpectAllExtensionsSet(message); + reflection_tester.ExpectAllFieldsSetViaReflection(message); + + reflection_tester.ModifyRepeatedFieldsViaReflection(&message); + TestUtil::ExpectRepeatedExtensionsModified(message); +} + +TEST(GeneratedMessageReflectionTest, FindExtensionTypeByNumber) { + const Reflection* reflection = + unittest::TestAllExtensions::default_instance().GetReflection(); + + const FieldDescriptor* extension1 = + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "optional_int32_extension"); + const FieldDescriptor* extension2 = + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "repeated_string_extension"); + + EXPECT_EQ(extension1, + reflection->FindKnownExtensionByNumber(extension1->number())); + EXPECT_EQ(extension2, + reflection->FindKnownExtensionByNumber(extension2->number())); + + // Non-existent extension. + EXPECT_TRUE(reflection->FindKnownExtensionByNumber(62341) == NULL); + + // Extensions of TestAllExtensions should not show up as extensions of + // other types. + EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()-> + FindKnownExtensionByNumber(extension1->number()) == NULL); +} + +TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { + const Reflection* reflection = + unittest::TestAllExtensions::default_instance().GetReflection(); + + const FieldDescriptor* extension1 = + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "optional_int32_extension"); + const FieldDescriptor* extension2 = + unittest::TestAllExtensions::descriptor()->file()->FindExtensionByName( + "repeated_string_extension"); + + EXPECT_EQ(extension1, + reflection->FindKnownExtensionByName(extension1->full_name())); + EXPECT_EQ(extension2, + reflection->FindKnownExtensionByName(extension2->full_name())); + + // Non-existent extension. + EXPECT_TRUE(reflection->FindKnownExtensionByName("no_such_ext") == NULL); + + // Extensions of TestAllExtensions should not show up as extensions of + // other types. + EXPECT_TRUE(unittest::TestAllTypes::default_instance().GetReflection()-> + FindKnownExtensionByName(extension1->full_name()) == NULL); +} + +TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) { + unittest::TestAllTypes message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + + // When nothing is set, we expect all released messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are set we should get non-NULL releases. + reflection_tester.SetAllFieldsViaReflection(&message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::NOT_NULL); + + // After Clear() we may or may not get a message from ReleaseMessage(). + // This is implementation specific. + reflection_tester.SetAllFieldsViaReflection(&message); + message.Clear(); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::CAN_BE_NULL); + + // Test a different code path for setting after releasing. + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) { + unittest::TestAllExtensions message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + + // When nothing is set, we expect all released messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are set we should get non-NULL releases. + reflection_tester.SetAllFieldsViaReflection(&message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::NOT_NULL); + + // After Clear() we may or may not get a message from ReleaseMessage(). + // This is implementation specific. + reflection_tester.SetAllFieldsViaReflection(&message); + message.Clear(); + reflection_tester.ExpectMessagesReleasedViaReflection( + &message, TestUtil::ReflectionTester::CAN_BE_NULL); + + // Test a different code path for setting after releasing. + TestUtil::SetAllExtensions(&message); + TestUtil::ExpectAllExtensionsSet(message); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST + +TEST(GeneratedMessageReflectionTest, UsageErrors) { + unittest::TestAllTypes message; + const Reflection* reflection = message.GetReflection(); + const Descriptor* descriptor = message.GetDescriptor(); + +#define f(NAME) descriptor->FindFieldByName(NAME) + + // Testing every single failure mode would be too much work. Let's just + // check a few. + EXPECT_DEATH( + reflection->GetInt32( + message, descriptor->FindFieldByName("optional_int64")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest\\.TestAllTypes\n" + " Field : protobuf_unittest\\.TestAllTypes\\.optional_int64\n" + " Problem : Field is not the right type for this message:\n" + " Expected : CPPTYPE_INT32\n" + " Field type: CPPTYPE_INT64"); + EXPECT_DEATH( + reflection->GetInt32( + message, descriptor->FindFieldByName("repeated_int32")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.TestAllTypes.repeated_int32\n" + " Problem : Field is repeated; the method requires a singular field."); + EXPECT_DEATH( + reflection->GetInt32( + message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::GetInt32\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.ForeignMessage.c\n" + " Problem : Field does not match message type."); + EXPECT_DEATH( + reflection->HasField( + message, unittest::ForeignMessage::descriptor()->FindFieldByName("c")), + "Protocol Buffer reflection usage error:\n" + " Method : google::protobuf::Reflection::HasField\n" + " Message type: protobuf_unittest.TestAllTypes\n" + " Field : protobuf_unittest.ForeignMessage.c\n" + " Problem : Field does not match message type."); + +#undef f +} + +#endif // PROTOBUF_HAS_DEATH_TEST + + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.cc new file mode 100644 index 000000000..ac3215014 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.cc @@ -0,0 +1,54 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +namespace google { +namespace protobuf { +namespace internal { + +double Infinity() { + return std::numeric_limits::infinity(); +} +double NaN() { + return std::numeric_limits::quiet_NaN(); +} + +const ::std::string kEmptyString; + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.h new file mode 100644 index 000000000..b2fb8f0be --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/generated_message_util.h @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains miscellaneous helper code used by generated code -- +// including lite types -- but which should not be used directly by users. + +#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ + +#include + +#include +namespace google { +namespace protobuf { +namespace internal { + +// Annotation for the compiler to emit a deprecation message if a field marked +// with option 'deprecated=true' is used in the code, or for other things in +// generated code which are deprecated. +// +// For internal use in the pb.cc files, deprecation warnings are suppressed +// there. +#undef DEPRECATED_PROTOBUF_FIELD +#define PROTOBUF_DEPRECATED + + +// Constants for special floating point values. +LIBPROTOBUF_EXPORT double Infinity(); +LIBPROTOBUF_EXPORT double NaN(); + +// Constant used for empty default strings. +LIBPROTOBUF_EXPORT extern const ::std::string kEmptyString; + +// Defined in generated_message_reflection.cc -- not actually part of the lite +// library. +// +// TODO(jasonh): The various callers get this declaration from a variety of +// places: probably in most cases repeated_field.h. Clean these up so they all +// get the declaration from this file. +LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.cc new file mode 100644 index 000000000..36add8c3e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.cc @@ -0,0 +1,857 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 implementation is heavily optimized to make reads and writes +// of small values (especially varints) as fast as possible. In +// particular, we optimize for the common case that a read or a write +// will not cross the end of the buffer, since we can avoid a lot +// of branching in this case. + +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace io { + +namespace { + +static const int kMaxVarintBytes = 10; +static const int kMaxVarint32Bytes = 5; + + +inline bool NextNonEmpty(ZeroCopyInputStream* input, + const void** data, int* size) { + bool success; + do { + success = input->Next(data, size); + } while (success && *size == 0); + return success; +} + +} // namespace + +// CodedInputStream ================================================== + +CodedInputStream::~CodedInputStream() { + if (input_ != NULL) { + BackUpInputToCurrentPosition(); + } + + if (total_bytes_warning_threshold_ == -2) { + GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_; + } +} + +// Static. +int CodedInputStream::default_recursion_limit_ = 100; + + +void CodedInputStream::BackUpInputToCurrentPosition() { + int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; + if (backup_bytes > 0) { + input_->BackUp(backup_bytes); + + // total_bytes_read_ doesn't include overflow_bytes_. + total_bytes_read_ -= BufferSize() + buffer_size_after_limit_; + buffer_end_ = buffer_; + buffer_size_after_limit_ = 0; + overflow_bytes_ = 0; + } +} + +inline void CodedInputStream::RecomputeBufferLimits() { + buffer_end_ += buffer_size_after_limit_; + int closest_limit = min(current_limit_, total_bytes_limit_); + if (closest_limit < total_bytes_read_) { + // The limit position is in the current buffer. We must adjust + // the buffer size accordingly. + buffer_size_after_limit_ = total_bytes_read_ - closest_limit; + buffer_end_ -= buffer_size_after_limit_; + } else { + buffer_size_after_limit_ = 0; + } +} + +CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { + // Current position relative to the beginning of the stream. + int current_position = CurrentPosition(); + + Limit old_limit = current_limit_; + + // security: byte_limit is possibly evil, so check for negative values + // and overflow. + if (byte_limit >= 0 && + byte_limit <= INT_MAX - current_position) { + current_limit_ = current_position + byte_limit; + } else { + // Negative or overflow. + current_limit_ = INT_MAX; + } + + // We need to enforce all limits, not just the new one, so if the previous + // limit was before the new requested limit, we continue to enforce the + // previous limit. + current_limit_ = min(current_limit_, old_limit); + + RecomputeBufferLimits(); + return old_limit; +} + +void CodedInputStream::PopLimit(Limit limit) { + // The limit passed in is actually the *old* limit, which we returned from + // PushLimit(). + current_limit_ = limit; + RecomputeBufferLimits(); + + // We may no longer be at a legitimate message end. ReadTag() needs to be + // called again to find out. + legitimate_message_end_ = false; +} + +int CodedInputStream::BytesUntilLimit() const { + if (current_limit_ == INT_MAX) return -1; + int current_position = CurrentPosition(); + + return current_limit_ - current_position; +} + +void CodedInputStream::SetTotalBytesLimit( + int total_bytes_limit, int warning_threshold) { + // Make sure the limit isn't already past, since this could confuse other + // code. + int current_position = CurrentPosition(); + total_bytes_limit_ = max(current_position, total_bytes_limit); + if (warning_threshold >= 0) { + total_bytes_warning_threshold_ = warning_threshold; + } else { + // warning_threshold is negative + total_bytes_warning_threshold_ = -1; + } + RecomputeBufferLimits(); +} + +void CodedInputStream::PrintTotalBytesLimitError() { + GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " + "big (more than " << total_bytes_limit_ + << " bytes). To increase the limit (or to disable these " + "warnings), see CodedInputStream::SetTotalBytesLimit() " + "in google/protobuf/io/coded_stream.h."; +} + +bool CodedInputStream::Skip(int count) { + if (count < 0) return false; // security: count is often user-supplied + + const int original_buffer_size = BufferSize(); + + if (count <= original_buffer_size) { + // Just skipping within the current buffer. Easy. + Advance(count); + return true; + } + + if (buffer_size_after_limit_ > 0) { + // We hit a limit inside this buffer. Advance to the limit and fail. + Advance(original_buffer_size); + return false; + } + + count -= original_buffer_size; + buffer_ = NULL; + buffer_end_ = buffer_; + + // Make sure this skip doesn't try to skip past the current limit. + int closest_limit = min(current_limit_, total_bytes_limit_); + int bytes_until_limit = closest_limit - total_bytes_read_; + if (bytes_until_limit < count) { + // We hit the limit. Skip up to it then fail. + if (bytes_until_limit > 0) { + total_bytes_read_ = closest_limit; + input_->Skip(bytes_until_limit); + } + return false; + } + + total_bytes_read_ += count; + return input_->Skip(count); +} + +bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { + if (BufferSize() == 0 && !Refresh()) return false; + + *data = buffer_; + *size = BufferSize(); + return true; +} + +bool CodedInputStream::ReadRaw(void* buffer, int size) { + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Reading past end of buffer. Copy what we have, then refresh. + memcpy(buffer, buffer_, current_buffer_size); + buffer = reinterpret_cast(buffer) + current_buffer_size; + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + memcpy(buffer, buffer_, size); + Advance(size); + + return true; +} + +bool CodedInputStream::ReadString(string* buffer, int size) { + if (size < 0) return false; // security: size is often user-supplied + return InternalReadStringInline(buffer, size); +} + +bool CodedInputStream::ReadStringFallback(string* buffer, int size) { + if (!buffer->empty()) { + buffer->clear(); + } + + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Some STL implementations "helpfully" crash on buffer->append(NULL, 0). + if (current_buffer_size != 0) { + // Note: string1.append(string2) is O(string2.size()) (as opposed to + // O(string1.size() + string2.size()), which would be bad). + buffer->append(reinterpret_cast(buffer_), + current_buffer_size); + } + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + buffer->append(reinterpret_cast(buffer_), size); + Advance(size); + + return true; +} + + +bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) { + uint8 bytes[sizeof(*value)]; + + const uint8* ptr; + if (BufferSize() >= sizeof(*value)) { + // Fast path: Enough bytes in the buffer to read directly. + ptr = buffer_; + Advance(sizeof(*value)); + } else { + // Slow path: Had to read past the end of the buffer. + if (!ReadRaw(bytes, sizeof(*value))) return false; + ptr = bytes; + } + ReadLittleEndian32FromArray(ptr, value); + return true; +} + +bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) { + uint8 bytes[sizeof(*value)]; + + const uint8* ptr; + if (BufferSize() >= sizeof(*value)) { + // Fast path: Enough bytes in the buffer to read directly. + ptr = buffer_; + Advance(sizeof(*value)); + } else { + // Slow path: Had to read past the end of the buffer. + if (!ReadRaw(bytes, sizeof(*value))) return false; + ptr = bytes; + } + ReadLittleEndian64FromArray(ptr, value); + return true; +} + +namespace { + +inline const uint8* ReadVarint32FromArray( + const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this read won't cross the end, so we can skip the checks. + const uint8* ptr = buffer; + uint32 b; + uint32 result; + + b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done; + b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; + b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; + b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done; + + // If the input is larger than 32 bits, we still need to read it all + // and discard the high-order bits. + for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) { + b = *(ptr++); if (!(b & 0x80)) goto done; + } + + // We have overrun the maximum size of a varint (10 bytes). Assume + // the data is corrupt. + return NULL; + + done: + *value = result; + return ptr; +} + +} // namespace + +bool CodedInputStream::ReadVarint32Slow(uint32* value) { + uint64 result; + // Directly invoke ReadVarint64Fallback, since we already tried to optimize + // for one-byte varints. + if (!ReadVarint64Fallback(&result)) return false; + *value = (uint32)result; + return true; +} + +bool CodedInputStream::ReadVarint32Fallback(uint32* value) { + if (BufferSize() >= kMaxVarintBytes || + // Optimization: If the varint ends at exactly the end of the buffer, + // we can detect that and still use the fast path. + (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + const uint8* end = ReadVarint32FromArray(buffer_, value); + if (end == NULL) return false; + buffer_ = end; + return true; + } else { + // Really slow case: we will incur the cost of an extra function call here, + // but moving this out of line reduces the size of this function, which + // improves the common case. In micro benchmarks, this is worth about 10-15% + return ReadVarint32Slow(value); + } +} + +uint32 CodedInputStream::ReadTagSlow() { + if (buffer_ == buffer_end_) { + // Call refresh. + if (!Refresh()) { + // Refresh failed. Make sure that it failed due to EOF, not because + // we hit total_bytes_limit_, which, unlike normal limits, is not a + // valid place to end a message. + int current_position = total_bytes_read_ - buffer_size_after_limit_; + if (current_position >= total_bytes_limit_) { + // Hit total_bytes_limit_. But if we also hit the normal limit, + // we're still OK. + legitimate_message_end_ = current_limit_ == total_bytes_limit_; + } else { + legitimate_message_end_ = true; + } + return 0; + } + } + + // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags + // again, since we have now refreshed the buffer. + uint64 result = 0; + if (!ReadVarint64(&result)) return 0; + return static_cast(result); +} + +uint32 CodedInputStream::ReadTagFallback() { + const int buf_size = BufferSize(); + if (buf_size >= kMaxVarintBytes || + // Optimization: If the varint ends at exactly the end of the buffer, + // we can detect that and still use the fast path. + (buf_size > 0 && !(buffer_end_[-1] & 0x80))) { + uint32 tag; + const uint8* end = ReadVarint32FromArray(buffer_, &tag); + if (end == NULL) { + return 0; + } + buffer_ = end; + return tag; + } else { + // We are commonly at a limit when attempting to read tags. Try to quickly + // detect this case without making another function call. + if ((buf_size == 0) && + ((buffer_size_after_limit_ > 0) || + (total_bytes_read_ == current_limit_)) && + // Make sure that the limit we hit is not total_bytes_limit_, since + // in that case we still need to call Refresh() so that it prints an + // error. + total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) { + // We hit a byte limit. + legitimate_message_end_ = true; + return 0; + } + return ReadTagSlow(); + } +} + +bool CodedInputStream::ReadVarint64Slow(uint64* value) { + // Slow path: This read might cross the end of the buffer, so we + // need to check and refresh the buffer if and when it does. + + uint64 result = 0; + int count = 0; + uint32 b; + + do { + if (count == kMaxVarintBytes) return false; + while (buffer_ == buffer_end_) { + if (!Refresh()) return false; + } + b = *buffer_; + result |= static_cast(b & 0x7F) << (7 * count); + Advance(1); + ++count; + } while (b & 0x80); + + *value = result; + return true; +} + +bool CodedInputStream::ReadVarint64Fallback(uint64* value) { + if (BufferSize() >= kMaxVarintBytes || + // Optimization: If the varint ends at exactly the end of the buffer, + // we can detect that and still use the fast path. + (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this read won't cross the end, so we can skip the checks. + + const uint8* ptr = buffer_; + uint32 b; + + // Splitting into 32-bit pieces gives better performance on 32-bit + // processors. + uint32 part0 = 0, part1 = 0, part2 = 0; + + b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done; + b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; + b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; + b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done; + b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; + b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; + b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done; + b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + + // We have overrun the maximum size of a varint (10 bytes). The data + // must be corrupt. + return false; + + done: + Advance(ptr - buffer_); + *value = (static_cast(part0) ) | + (static_cast(part1) << 28) | + (static_cast(part2) << 56); + return true; + } else { + return ReadVarint64Slow(value); + } +} + +bool CodedInputStream::Refresh() { + GOOGLE_DCHECK_EQ(0, BufferSize()); + + if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 || + total_bytes_read_ == current_limit_) { + // We've hit a limit. Stop. + int current_position = total_bytes_read_ - buffer_size_after_limit_; + + if (current_position >= total_bytes_limit_ && + total_bytes_limit_ != current_limit_) { + // Hit total_bytes_limit_. + PrintTotalBytesLimitError(); + } + + return false; + } + + if (total_bytes_warning_threshold_ >= 0 && + total_bytes_read_ >= total_bytes_warning_threshold_) { + GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If the " + "message turns out to be larger than " + << total_bytes_limit_ << " bytes, parsing will be halted " + "for security reasons. To increase the limit (or to " + "disable these warnings), see " + "CodedInputStream::SetTotalBytesLimit() in " + "google/protobuf/io/coded_stream.h."; + + // Don't warn again for this stream, and print total size at the end. + total_bytes_warning_threshold_ = -2; + } + + const void* void_buffer; + int buffer_size; + if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { + buffer_ = reinterpret_cast(void_buffer); + buffer_end_ = buffer_ + buffer_size; + GOOGLE_CHECK_GE(buffer_size, 0); + + if (total_bytes_read_ <= INT_MAX - buffer_size) { + total_bytes_read_ += buffer_size; + } else { + // Overflow. Reset buffer_end_ to not include the bytes beyond INT_MAX. + // We can't get that far anyway, because total_bytes_limit_ is guaranteed + // to be less than it. We need to keep track of the number of bytes + // we discarded, though, so that we can call input_->BackUp() to back + // up over them on destruction. + + // The following line is equivalent to: + // overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX; + // except that it avoids overflows. Signed integer overflow has + // undefined results according to the C standard. + overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size); + buffer_end_ -= overflow_bytes_; + total_bytes_read_ = INT_MAX; + } + + RecomputeBufferLimits(); + return true; + } else { + buffer_ = NULL; + buffer_end_ = NULL; + return false; + } +} + +// CodedOutputStream ================================================= + +CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) + : output_(output), + buffer_(NULL), + buffer_size_(0), + total_bytes_(0), + had_error_(false) { + // Eagerly Refresh() so buffer space is immediately available. + Refresh(); + // The Refresh() may have failed. If the client doesn't write any data, + // though, don't consider this an error. If the client does write data, then + // another Refresh() will be attempted and it will set the error once again. + had_error_ = false; +} + +CodedOutputStream::~CodedOutputStream() { + if (buffer_size_ > 0) { + output_->BackUp(buffer_size_); + } +} + +bool CodedOutputStream::Skip(int count) { + if (count < 0) return false; + + while (count > buffer_size_) { + count -= buffer_size_; + if (!Refresh()) return false; + } + + Advance(count); + return true; +} + +bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) { + if (buffer_size_ == 0 && !Refresh()) return false; + + *data = buffer_; + *size = buffer_size_; + return true; +} + +void CodedOutputStream::WriteRaw(const void* data, int size) { + while (buffer_size_ < size) { + memcpy(buffer_, data, buffer_size_); + size -= buffer_size_; + data = reinterpret_cast(data) + buffer_size_; + if (!Refresh()) return; + } + + memcpy(buffer_, data, size); + Advance(size); +} + +uint8* CodedOutputStream::WriteRawToArray( + const void* data, int size, uint8* target) { + memcpy(target, data, size); + return target + size; +} + + +void CodedOutputStream::WriteLittleEndian32(uint32 value) { + uint8 bytes[sizeof(value)]; + + bool use_fast = buffer_size_ >= sizeof(value); + uint8* ptr = use_fast ? buffer_ : bytes; + + WriteLittleEndian32ToArray(value, ptr); + + if (use_fast) { + Advance(sizeof(value)); + } else { + WriteRaw(bytes, sizeof(value)); + } +} + +void CodedOutputStream::WriteLittleEndian64(uint64 value) { + uint8 bytes[sizeof(value)]; + + bool use_fast = buffer_size_ >= sizeof(value); + uint8* ptr = use_fast ? buffer_ : bytes; + + WriteLittleEndian64ToArray(value, ptr); + + if (use_fast) { + Advance(sizeof(value)); + } else { + WriteRaw(bytes, sizeof(value)); + } +} + +inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline( + uint32 value, uint8* target) { + target[0] = static_cast(value | 0x80); + if (value >= (1 << 7)) { + target[1] = static_cast((value >> 7) | 0x80); + if (value >= (1 << 14)) { + target[2] = static_cast((value >> 14) | 0x80); + if (value >= (1 << 21)) { + target[3] = static_cast((value >> 21) | 0x80); + if (value >= (1 << 28)) { + target[4] = static_cast(value >> 28); + return target + 5; + } else { + target[3] &= 0x7F; + return target + 4; + } + } else { + target[2] &= 0x7F; + return target + 3; + } + } else { + target[1] &= 0x7F; + return target + 2; + } + } else { + target[0] &= 0x7F; + return target + 1; + } +} + +void CodedOutputStream::WriteVarint32(uint32 value) { + if (buffer_size_ >= kMaxVarint32Bytes) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this write won't cross the end, so we can skip the checks. + uint8* target = buffer_; + uint8* end = WriteVarint32FallbackToArrayInline(value, target); + int size = end - target; + Advance(size); + } else { + // Slow path: This write might cross the end of the buffer, so we + // compose the bytes first then use WriteRaw(). + uint8 bytes[kMaxVarint32Bytes]; + int size = 0; + while (value > 0x7F) { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + WriteRaw(bytes, size); + } +} + +uint8* CodedOutputStream::WriteVarint32FallbackToArray( + uint32 value, uint8* target) { + return WriteVarint32FallbackToArrayInline(value, target); +} + +inline uint8* CodedOutputStream::WriteVarint64ToArrayInline( + uint64 value, uint8* target) { + // Splitting into 32-bit pieces gives better performance on 32-bit + // processors. + uint32 part0 = static_cast(value ); + uint32 part1 = static_cast(value >> 28); + uint32 part2 = static_cast(value >> 56); + + int size; + + // Here we can't really optimize for small numbers, since the value is + // split into three parts. Cheking for numbers < 128, for instance, + // would require three comparisons, since you'd have to make sure part1 + // and part2 are zero. However, if the caller is using 64-bit integers, + // it is likely that they expect the numbers to often be very large, so + // we probably don't want to optimize for small numbers anyway. Thus, + // we end up with a hardcoded binary search tree... + if (part2 == 0) { + if (part1 == 0) { + if (part0 < (1 << 14)) { + if (part0 < (1 << 7)) { + size = 1; goto size1; + } else { + size = 2; goto size2; + } + } else { + if (part0 < (1 << 21)) { + size = 3; goto size3; + } else { + size = 4; goto size4; + } + } + } else { + if (part1 < (1 << 14)) { + if (part1 < (1 << 7)) { + size = 5; goto size5; + } else { + size = 6; goto size6; + } + } else { + if (part1 < (1 << 21)) { + size = 7; goto size7; + } else { + size = 8; goto size8; + } + } + } + } else { + if (part2 < (1 << 7)) { + size = 9; goto size9; + } else { + size = 10; goto size10; + } + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + + size10: target[9] = static_cast((part2 >> 7) | 0x80); + size9 : target[8] = static_cast((part2 ) | 0x80); + size8 : target[7] = static_cast((part1 >> 21) | 0x80); + size7 : target[6] = static_cast((part1 >> 14) | 0x80); + size6 : target[5] = static_cast((part1 >> 7) | 0x80); + size5 : target[4] = static_cast((part1 ) | 0x80); + size4 : target[3] = static_cast((part0 >> 21) | 0x80); + size3 : target[2] = static_cast((part0 >> 14) | 0x80); + size2 : target[1] = static_cast((part0 >> 7) | 0x80); + size1 : target[0] = static_cast((part0 ) | 0x80); + + target[size-1] &= 0x7F; + return target + size; +} + +void CodedOutputStream::WriteVarint64(uint64 value) { + if (buffer_size_ >= kMaxVarintBytes) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this write won't cross the end, so we can skip the checks. + uint8* target = buffer_; + + uint8* end = WriteVarint64ToArrayInline(value, target); + int size = end - target; + Advance(size); + } else { + // Slow path: This write might cross the end of the buffer, so we + // compose the bytes first then use WriteRaw(). + uint8 bytes[kMaxVarintBytes]; + int size = 0; + while (value > 0x7F) { + bytes[size++] = (static_cast(value) & 0x7F) | 0x80; + value >>= 7; + } + bytes[size++] = static_cast(value) & 0x7F; + WriteRaw(bytes, size); + } +} + +uint8* CodedOutputStream::WriteVarint64ToArray( + uint64 value, uint8* target) { + return WriteVarint64ToArrayInline(value, target); +} + +bool CodedOutputStream::Refresh() { + void* void_buffer; + if (output_->Next(&void_buffer, &buffer_size_)) { + buffer_ = reinterpret_cast(void_buffer); + total_bytes_ += buffer_size_; + return true; + } else { + buffer_ = NULL; + buffer_size_ = 0; + had_error_ = true; + return false; + } +} + +int CodedOutputStream::VarintSize32Fallback(uint32 value) { + if (value < (1 << 7)) { + return 1; + } else if (value < (1 << 14)) { + return 2; + } else if (value < (1 << 21)) { + return 3; + } else if (value < (1 << 28)) { + return 4; + } else { + return 5; + } +} + +int CodedOutputStream::VarintSize64(uint64 value) { + if (value < (1ull << 35)) { + if (value < (1ull << 7)) { + return 1; + } else if (value < (1ull << 14)) { + return 2; + } else if (value < (1ull << 21)) { + return 3; + } else if (value < (1ull << 28)) { + return 4; + } else { + return 5; + } + } else { + if (value < (1ull << 42)) { + return 6; + } else if (value < (1ull << 49)) { + return 7; + } else if (value < (1ull << 56)) { + return 8; + } else if (value < (1ull << 63)) { + return 9; + } else { + return 10; + } + } +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.h new file mode 100644 index 000000000..66cbee003 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream.h @@ -0,0 +1,1136 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains the CodedInputStream and CodedOutputStream classes, +// which wrap a ZeroCopyInputStream or ZeroCopyOutputStream, respectively, +// and allow you to read or write individual pieces of data in various +// formats. In particular, these implement the varint encoding for +// integers, a simple variable-length encoding in which smaller numbers +// take fewer bytes. +// +// Typically these classes will only be used internally by the protocol +// buffer library in order to encode and decode protocol buffers. Clients +// of the library only need to know about this class if they wish to write +// custom message parsing or serialization procedures. +// +// CodedOutputStream example: +// // Write some data to "myfile". First we write a 4-byte "magic number" +// // to identify the file type, then write a length-delimited string. The +// // string is composed of a varint giving the length followed by the raw +// // bytes. +// int fd = open("myfile", O_WRONLY); +// ZeroCopyOutputStream* raw_output = new FileOutputStream(fd); +// CodedOutputStream* coded_output = new CodedOutputStream(raw_output); +// +// int magic_number = 1234; +// char text[] = "Hello world!"; +// coded_output->WriteLittleEndian32(magic_number); +// coded_output->WriteVarint32(strlen(text)); +// coded_output->WriteRaw(text, strlen(text)); +// +// delete coded_output; +// delete raw_output; +// close(fd); +// +// CodedInputStream example: +// // Read a file created by the above code. +// int fd = open("myfile", O_RDONLY); +// ZeroCopyInputStream* raw_input = new FileInputStream(fd); +// CodedInputStream coded_input = new CodedInputStream(raw_input); +// +// coded_input->ReadLittleEndian32(&magic_number); +// if (magic_number != 1234) { +// cerr << "File not in expected format." << endl; +// return; +// } +// +// uint32 size; +// coded_input->ReadVarint32(&size); +// +// char* text = new char[size + 1]; +// coded_input->ReadRaw(buffer, size); +// text[size] = '\0'; +// +// delete coded_input; +// delete raw_input; +// close(fd); +// +// cout << "Text is: " << text << endl; +// delete [] text; +// +// For those who are interested, varint encoding is defined as follows: +// +// The encoding operates on unsigned integers of up to 64 bits in length. +// Each byte of the encoded value has the format: +// * bits 0-6: Seven bits of the number being encoded. +// * bit 7: Zero if this is the last byte in the encoding (in which +// case all remaining bits of the number are zero) or 1 if +// more bytes follow. +// The first byte contains the least-significant 7 bits of the number, the +// second byte (if present) contains the next-least-significant 7 bits, +// and so on. So, the binary number 1011000101011 would be encoded in two +// bytes as "10101011 00101100". +// +// In theory, varint could be used to encode integers of any length. +// However, for practicality we set a limit at 64 bits. The maximum encoded +// length of a number is thus 10 bytes. + +#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ + +#include +#ifdef _MSC_VER + #if defined(_M_IX86) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 + // 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(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif +#include + + +namespace google { +namespace protobuf { + +class DescriptorPool; +class MessageFactory; + +namespace io { + +// Defined in this file. +class CodedInputStream; +class CodedOutputStream; + +// Defined in other files. +class ZeroCopyInputStream; // zero_copy_stream.h +class ZeroCopyOutputStream; // zero_copy_stream.h + +// Class which reads and decodes binary data which is composed of varint- +// encoded integers and fixed-width pieces. Wraps a ZeroCopyInputStream. +// Most users will not need to deal with CodedInputStream. +// +// Most methods of CodedInputStream that return a bool return false if an +// underlying I/O error occurs or if the data is malformed. Once such a +// failure occurs, the CodedInputStream is broken and is no longer useful. +class LIBPROTOBUF_EXPORT CodedInputStream { + public: + // Create a CodedInputStream that reads from the given ZeroCopyInputStream. + explicit CodedInputStream(ZeroCopyInputStream* input); + + // Create a CodedInputStream that reads from the given flat array. This is + // faster than using an ArrayInputStream. PushLimit(size) is implied by + // this constructor. + explicit CodedInputStream(const uint8* buffer, int size); + + // Destroy the CodedInputStream and position the underlying + // ZeroCopyInputStream at the first unread byte. If an error occurred while + // reading (causing a method to return false), then the exact position of + // the input stream may be anywhere between the last value that was read + // successfully and the stream's byte limit. + ~CodedInputStream(); + + // Return true if this CodedInputStream reads from a flat array instead of + // a ZeroCopyInputStream. + inline bool IsFlat() const; + + // Skips a number of bytes. Returns false if an underlying read error + // occurs. + bool Skip(int count); + + // Sets *data to point directly at the unread part of the CodedInputStream's + // underlying buffer, and *size to the size of that buffer, but does not + // advance the stream's current position. This will always either produce + // a non-empty buffer or return false. If the caller consumes any of + // this data, it should then call Skip() to skip over the consumed bytes. + // This may be useful for implementing external fast parsing routines for + // types of data not covered by the CodedInputStream interface. + bool GetDirectBufferPointer(const void** data, int* size); + + // Like GetDirectBufferPointer, but this method is inlined, and does not + // attempt to Refresh() if the buffer is currently empty. + inline void GetDirectBufferPointerInline(const void** data, + int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + // Read raw bytes, copying them into the given buffer. + bool ReadRaw(void* buffer, int size); + + // Like ReadRaw, but reads into a string. + // + // Implementation Note: ReadString() grows the string gradually as it + // reads in the data, rather than allocating the entire requested size + // upfront. This prevents denial-of-service attacks in which a client + // could claim that a string is going to be MAX_INT bytes long in order to + // crash the server because it can't allocate this much space at once. + bool ReadString(string* buffer, int size); + // Like the above, with inlined optimizations. This should only be used + // by the protobuf implementation. + inline bool InternalReadStringInline(string* buffer, + int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + + // Read a 32-bit little-endian integer. + bool ReadLittleEndian32(uint32* value); + // Read a 64-bit little-endian integer. + bool ReadLittleEndian64(uint64* value); + + // These methods read from an externally provided buffer. The caller is + // responsible for ensuring that the buffer has sufficient space. + // Read a 32-bit little-endian integer. + static const uint8* ReadLittleEndian32FromArray(const uint8* buffer, + uint32* value); + // Read a 64-bit little-endian integer. + static const uint8* ReadLittleEndian64FromArray(const uint8* buffer, + uint64* value); + + // Read an unsigned integer with Varint encoding, truncating to 32 bits. + // Reading a 32-bit value is equivalent to reading a 64-bit one and casting + // it to uint32, but may be more efficient. + bool ReadVarint32(uint32* value); + // Read an unsigned integer with Varint encoding. + bool ReadVarint64(uint64* value); + + // Read a tag. This calls ReadVarint32() and returns the result, or returns + // zero (which is not a valid tag) if ReadVarint32() fails. Also, it updates + // the last tag value, which can be checked with LastTagWas(). + // Always inline because this is only called in once place per parse loop + // but it is called for every iteration of said loop, so it should be fast. + // GCC doesn't want to inline this by default. + uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + // Usually returns true if calling ReadVarint32() now would produce the given + // value. Will always return false if ReadVarint32() would not return the + // given value. If ExpectTag() returns true, it also advances past + // the varint. For best performance, use a compile-time constant as the + // parameter. + // Always inline because this collapses to a small number of instructions + // when given a constant parameter, but GCC doesn't want to inline by default. + bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + // Like above, except this reads from the specified buffer. The caller is + // responsible for ensuring that the buffer is large enough to read a varint + // of the expected size. For best performance, use a compile-time constant as + // the expected tag parameter. + // + // Returns a pointer beyond the expected tag if it was found, or NULL if it + // was not. + static const uint8* ExpectTagFromArray( + const uint8* buffer, + uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + // Usually returns true if no more bytes can be read. Always returns false + // if more bytes can be read. If ExpectAtEnd() returns true, a subsequent + // call to LastTagWas() will act as if ReadTag() had been called and returned + // zero, and ConsumedEntireMessage() will return true. + bool ExpectAtEnd(); + + // If the last call to ReadTag() returned the given value, returns true. + // Otherwise, returns false; + // + // This is needed because parsers for some types of embedded messages + // (with field type TYPE_GROUP) don't actually know that they've reached the + // end of a message until they see an ENDGROUP tag, which was actually part + // of the enclosing message. The enclosing message would like to check that + // tag to make sure it had the right number, so it calls LastTagWas() on + // return from the embedded parser to check. + bool LastTagWas(uint32 expected); + + // When parsing message (but NOT a group), this method must be called + // immediately after MergeFromCodedStream() returns (if it returns true) + // to further verify that the message ended in a legitimate way. For + // example, this verifies that parsing did not end on an end-group tag. + // It also checks for some cases where, due to optimizations, + // MergeFromCodedStream() can incorrectly return true. + bool ConsumedEntireMessage(); + + // Limits ---------------------------------------------------------- + // Limits are used when parsing length-delimited embedded messages. + // After the message's length is read, PushLimit() is used to prevent + // the CodedInputStream from reading beyond that length. Once the + // embedded message has been parsed, PopLimit() is called to undo the + // limit. + + // Opaque type used with PushLimit() and PopLimit(). Do not modify + // values of this type yourself. The only reason that this isn't a + // struct with private internals is for efficiency. + typedef int Limit; + + // Places a limit on the number of bytes that the stream may read, + // starting from the current position. Once the stream hits this limit, + // it will act like the end of the input has been reached until PopLimit() + // is called. + // + // As the names imply, the stream conceptually has a stack of limits. The + // shortest limit on the stack is always enforced, even if it is not the + // top limit. + // + // The value returned by PushLimit() is opaque to the caller, and must + // be passed unchanged to the corresponding call to PopLimit(). + Limit PushLimit(int byte_limit); + + // Pops the last limit pushed by PushLimit(). The input must be the value + // returned by that call to PushLimit(). + void PopLimit(Limit limit); + + // Returns the number of bytes left until the nearest limit on the + // stack is hit, or -1 if no limits are in place. + int BytesUntilLimit() const; + + // Returns current position relative to the beginning of the input stream. + int CurrentPosition() const; + + // Total Bytes Limit ----------------------------------------------- + // To prevent malicious users from sending excessively large messages + // and causing integer overflows or memory exhaustion, CodedInputStream + // imposes a hard limit on the total number of bytes it will read. + + // Sets the maximum number of bytes that this CodedInputStream will read + // before refusing to continue. To prevent integer overflows in the + // protocol buffers implementation, as well as to prevent servers from + // allocating enormous amounts of memory to hold parsed messages, the + // maximum message length should be limited to the shortest length that + // will not harm usability. The theoretical shortest message that could + // cause integer overflows is 512MB. The default limit is 64MB. Apps + // should set shorter limits if possible. If warning_threshold is not -1, + // a warning will be printed to stderr after warning_threshold bytes are + // read. For backwards compatibility all negative values get squached to -1, + // as other negative values might have special internal meanings. + // An error will always be printed to stderr if the limit is reached. + // + // This is unrelated to PushLimit()/PopLimit(). + // + // Hint: If you are reading this because your program is printing a + // warning about dangerously large protocol messages, you may be + // confused about what to do next. The best option is to change your + // design such that excessively large messages are not necessary. + // For example, try to design file formats to consist of many small + // messages rather than a single large one. If this is infeasible, + // you will need to increase the limit. Chances are, though, that + // your code never constructs a CodedInputStream on which the limit + // can be set. You probably parse messages by calling things like + // Message::ParseFromString(). In this case, you will need to change + // your code to instead construct some sort of ZeroCopyInputStream + // (e.g. an ArrayInputStream), construct a CodedInputStream around + // that, then call Message::ParseFromCodedStream() instead. Then + // you can adjust the limit. Yes, it's more work, but you're doing + // something unusual. + void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold); + + // Recursion Limit ------------------------------------------------- + // To prevent corrupt or malicious messages from causing stack overflows, + // we must keep track of the depth of recursion when parsing embedded + // messages and groups. CodedInputStream keeps track of this because it + // is the only object that is passed down the stack during parsing. + + // Sets the maximum recursion depth. The default is 100. + void SetRecursionLimit(int limit); + + + // Increments the current recursion depth. Returns true if the depth is + // under the limit, false if it has gone over. + bool IncrementRecursionDepth(); + + // Decrements the recursion depth. + void DecrementRecursionDepth(); + + // Extension Registry ---------------------------------------------- + // ADVANCED USAGE: 99.9% of people can ignore this section. + // + // By default, when parsing extensions, the parser looks for extension + // definitions in the pool which owns the outer message's Descriptor. + // However, you may call SetExtensionRegistry() to provide an alternative + // pool instead. This makes it possible, for example, to parse a message + // using a generated class, but represent some extensions using + // DynamicMessage. + + // Set the pool used to look up extensions. Most users do not need to call + // this as the correct pool will be chosen automatically. + // + // WARNING: It is very easy to misuse this. Carefully read the requirements + // below. Do not use this unless you are sure you need it. Almost no one + // does. + // + // Let's say you are parsing a message into message object m, and you want + // to take advantage of SetExtensionRegistry(). You must follow these + // requirements: + // + // The given DescriptorPool must contain m->GetDescriptor(). It is not + // sufficient for it to simply contain a descriptor that has the same name + // and content -- it must be the *exact object*. In other words: + // assert(pool->FindMessageTypeByName(m->GetDescriptor()->full_name()) == + // m->GetDescriptor()); + // There are two ways to satisfy this requirement: + // 1) Use m->GetDescriptor()->pool() as the pool. This is generally useless + // because this is the pool that would be used anyway if you didn't call + // SetExtensionRegistry() at all. + // 2) Use a DescriptorPool which has m->GetDescriptor()->pool() as an + // "underlay". Read the documentation for DescriptorPool for more + // information about underlays. + // + // You must also provide a MessageFactory. This factory will be used to + // construct Message objects representing extensions. The factory's + // GetPrototype() MUST return non-NULL for any Descriptor which can be found + // through the provided pool. + // + // If the provided factory might return instances of protocol-compiler- + // generated (i.e. compiled-in) types, or if the outer message object m is + // a generated type, then the given factory MUST have this property: If + // GetPrototype() is given a Descriptor which resides in + // DescriptorPool::generated_pool(), the factory MUST return the same + // prototype which MessageFactory::generated_factory() would return. That + // is, given a descriptor for a generated type, the factory must return an + // instance of the generated class (NOT DynamicMessage). However, when + // given a descriptor for a type that is NOT in generated_pool, the factory + // is free to return any implementation. + // + // The reason for this requirement is that generated sub-objects may be + // accessed via the standard (non-reflection) extension accessor methods, + // and these methods will down-cast the object to the generated class type. + // If the object is not actually of that type, the results would be undefined. + // On the other hand, if an extension is not compiled in, then there is no + // way the code could end up accessing it via the standard accessors -- the + // only way to access the extension is via reflection. When using reflection, + // DynamicMessage and generated messages are indistinguishable, so it's fine + // if these objects are represented using DynamicMessage. + // + // Using DynamicMessageFactory on which you have called + // SetDelegateToGeneratedFactory(true) should be sufficient to satisfy the + // above requirement. + // + // If either pool or factory is NULL, both must be NULL. + // + // Note that this feature is ignored when parsing "lite" messages as they do + // not have descriptors. + void SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory); + + // Get the DescriptorPool set via SetExtensionRegistry(), or NULL if no pool + // has been provided. + const DescriptorPool* GetExtensionPool(); + + // Get the MessageFactory set via SetExtensionRegistry(), or NULL if no + // factory has been provided. + MessageFactory* GetExtensionFactory(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream); + + ZeroCopyInputStream* input_; + const uint8* buffer_; + const uint8* buffer_end_; // pointer to the end of the buffer. + int total_bytes_read_; // total bytes read from input_, including + // the current buffer + + // If total_bytes_read_ surpasses INT_MAX, we record the extra bytes here + // so that we can BackUp() on destruction. + int overflow_bytes_; + + // LastTagWas() stuff. + uint32 last_tag_; // result of last ReadTag(). + + // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly + // at EOF, or by ExpectAtEnd() when it returns true. This happens when we + // reach the end of a message and attempt to read another tag. + bool legitimate_message_end_; + + // See EnableAliasing(). + bool aliasing_enabled_; + + // Limits + Limit current_limit_; // if position = -1, no limit is applied + + // For simplicity, if the current buffer crosses a limit (either a normal + // limit created by PushLimit() or the total bytes limit), buffer_size_ + // only tracks the number of bytes before that limit. This field + // contains the number of bytes after it. Note that this implies that if + // buffer_size_ == 0 and buffer_size_after_limit_ > 0, we know we've + // hit a limit. However, if both are zero, it doesn't necessarily mean + // we aren't at a limit -- the buffer may have ended exactly at the limit. + int buffer_size_after_limit_; + + // Maximum number of bytes to read, period. This is unrelated to + // current_limit_. Set using SetTotalBytesLimit(). + int total_bytes_limit_; + + // If positive/0: Limit for bytes read after which a warning due to size + // should be logged. + // If -1: Printing of warning disabled. Can be set by client. + // If -2: Internal: Limit has been reached, print full size when destructing. + int total_bytes_warning_threshold_; + + // Current recursion depth, controlled by IncrementRecursionDepth() and + // DecrementRecursionDepth(). + int recursion_depth_; + // Recursion depth limit, set by SetRecursionLimit(). + int recursion_limit_; + + // See SetExtensionRegistry(). + const DescriptorPool* extension_pool_; + MessageFactory* extension_factory_; + + // Private member functions. + + // Advance the buffer by a given number of bytes. + void Advance(int amount); + + // Back up input_ to the current buffer position. + void BackUpInputToCurrentPosition(); + + // Recomputes the value of buffer_size_after_limit_. Must be called after + // current_limit_ or total_bytes_limit_ changes. + void RecomputeBufferLimits(); + + // Writes an error message saying that we hit total_bytes_limit_. + void PrintTotalBytesLimitError(); + + // Called when the buffer runs out to request more data. Implies an + // Advance(BufferSize()). + bool Refresh(); + + // When parsing varints, we optimize for the common case of small values, and + // then optimize for the case when the varint fits within the current buffer + // piece. The Fallback method is used when we can't use the one-byte + // optimization. The Slow method is yet another fallback when the buffer is + // not large enough. Making the slow path out-of-line speeds up the common + // case by 10-15%. The slow path is fairly uncommon: it only triggers when a + // message crosses multiple buffers. + bool ReadVarint32Fallback(uint32* value); + bool ReadVarint64Fallback(uint64* value); + bool ReadVarint32Slow(uint32* value); + bool ReadVarint64Slow(uint64* value); + bool ReadLittleEndian32Fallback(uint32* value); + bool ReadLittleEndian64Fallback(uint64* value); + // Fallback/slow methods for reading tags. These do not update last_tag_, + // but will set legitimate_message_end_ if we are at the end of the input + // stream. + uint32 ReadTagFallback(); + uint32 ReadTagSlow(); + bool ReadStringFallback(string* buffer, int size); + + // Return the size of the buffer. + int BufferSize() const; + + static const int kDefaultTotalBytesLimit = 64 << 20; // 64MB + + static const int kDefaultTotalBytesWarningThreshold = 32 << 20; // 32MB + + static int default_recursion_limit_; // 100 by default. +}; + +// Class which encodes and writes binary data which is composed of varint- +// encoded integers and fixed-width pieces. Wraps a ZeroCopyOutputStream. +// Most users will not need to deal with CodedOutputStream. +// +// Most methods of CodedOutputStream which return a bool return false if an +// underlying I/O error occurs. Once such a failure occurs, the +// CodedOutputStream is broken and is no longer useful. The Write* methods do +// not return the stream status, but will invalidate the stream if an error +// occurs. The client can probe HadError() to determine the status. +// +// Note that every method of CodedOutputStream which writes some data has +// a corresponding static "ToArray" version. These versions write directly +// to the provided buffer, returning a pointer past the last written byte. +// They require that the buffer has sufficient capacity for the encoded data. +// This allows an optimization where we check if an output stream has enough +// space for an entire message before we start writing and, if there is, we +// call only the ToArray methods to avoid doing bound checks for each +// individual value. +// i.e., in the example above: +// +// CodedOutputStream coded_output = new CodedOutputStream(raw_output); +// int magic_number = 1234; +// char text[] = "Hello world!"; +// +// int coded_size = sizeof(magic_number) + +// CodedOutputStream::VarintSize32(strlen(text)) + +// strlen(text); +// +// uint8* buffer = +// coded_output->GetDirectBufferForNBytesAndAdvance(coded_size); +// if (buffer != NULL) { +// // The output stream has enough space in the buffer: write directly to +// // the array. +// buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number, +// buffer); +// buffer = CodedOutputStream::WriteVarint32ToArray(strlen(text), buffer); +// buffer = CodedOutputStream::WriteRawToArray(text, strlen(text), buffer); +// } else { +// // Make bound-checked writes, which will ask the underlying stream for +// // more space as needed. +// coded_output->WriteLittleEndian32(magic_number); +// coded_output->WriteVarint32(strlen(text)); +// coded_output->WriteRaw(text, strlen(text)); +// } +// +// delete coded_output; +class LIBPROTOBUF_EXPORT CodedOutputStream { + public: + // Create an CodedOutputStream that writes to the given ZeroCopyOutputStream. + explicit CodedOutputStream(ZeroCopyOutputStream* output); + + // Destroy the CodedOutputStream and position the underlying + // ZeroCopyOutputStream immediately after the last byte written. + ~CodedOutputStream(); + + // Skips a number of bytes, leaving the bytes unmodified in the underlying + // buffer. Returns false if an underlying write error occurs. This is + // mainly useful with GetDirectBufferPointer(). + bool Skip(int count); + + // Sets *data to point directly at the unwritten part of the + // CodedOutputStream's underlying buffer, and *size to the size of that + // buffer, but does not advance the stream's current position. This will + // always either produce a non-empty buffer or return false. If the caller + // writes any data to this buffer, it should then call Skip() to skip over + // the consumed bytes. This may be useful for implementing external fast + // serialization routines for types of data not covered by the + // CodedOutputStream interface. + bool GetDirectBufferPointer(void** data, int* size); + + // If there are at least "size" bytes available in the current buffer, + // returns a pointer directly into the buffer and advances over these bytes. + // The caller may then write directly into this buffer (e.g. using the + // *ToArray static methods) rather than go through CodedOutputStream. If + // there are not enough bytes available, returns NULL. The return pointer is + // invalidated as soon as any other non-const method of CodedOutputStream + // is called. + inline uint8* GetDirectBufferForNBytesAndAdvance(int size); + + // Write raw bytes, copying them from the given buffer. + void WriteRaw(const void* buffer, int size); + // Like WriteRaw() but writing directly to the target array. + // This is _not_ inlined, as the compiler often optimizes memcpy into inline + // copy loops. Since this gets called by every field with string or bytes + // type, inlining may lead to a significant amount of code bloat, with only a + // minor performance gain. + static uint8* WriteRawToArray(const void* buffer, int size, uint8* target); + + // Equivalent to WriteRaw(str.data(), str.size()). + void WriteString(const string& str); + // Like WriteString() but writing directly to the target array. + static uint8* WriteStringToArray(const string& str, uint8* target); + + + // Write a 32-bit little-endian integer. + void WriteLittleEndian32(uint32 value); + // Like WriteLittleEndian32() but writing directly to the target array. + static uint8* WriteLittleEndian32ToArray(uint32 value, uint8* target); + // Write a 64-bit little-endian integer. + void WriteLittleEndian64(uint64 value); + // Like WriteLittleEndian64() but writing directly to the target array. + static uint8* WriteLittleEndian64ToArray(uint64 value, uint8* target); + + // Write an unsigned integer with Varint encoding. Writing a 32-bit value + // is equivalent to casting it to uint64 and writing it as a 64-bit value, + // but may be more efficient. + void WriteVarint32(uint32 value); + // Like WriteVarint32() but writing directly to the target array. + static uint8* WriteVarint32ToArray(uint32 value, uint8* target); + // Write an unsigned integer with Varint encoding. + void WriteVarint64(uint64 value); + // Like WriteVarint64() but writing directly to the target array. + static uint8* WriteVarint64ToArray(uint64 value, uint8* target); + + // Equivalent to WriteVarint32() except when the value is negative, + // in which case it must be sign-extended to a full 10 bytes. + void WriteVarint32SignExtended(int32 value); + // Like WriteVarint32SignExtended() but writing directly to the target array. + static uint8* WriteVarint32SignExtendedToArray(int32 value, uint8* target); + + // This is identical to WriteVarint32(), but optimized for writing tags. + // In particular, if the input is a compile-time constant, this method + // compiles down to a couple instructions. + // Always inline because otherwise the aformentioned optimization can't work, + // but GCC by default doesn't want to inline this. + void WriteTag(uint32 value); + // Like WriteTag() but writing directly to the target array. + static uint8* WriteTagToArray( + uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + // Returns the number of bytes needed to encode the given value as a varint. + static int VarintSize32(uint32 value); + // Returns the number of bytes needed to encode the given value as a varint. + static int VarintSize64(uint64 value); + + // If negative, 10 bytes. Otheriwse, same as VarintSize32(). + static int VarintSize32SignExtended(int32 value); + + // Compile-time equivalent of VarintSize32(). + template + struct StaticVarintSize32 { + static const int value = + (Value < (1 << 7)) + ? 1 + : (Value < (1 << 14)) + ? 2 + : (Value < (1 << 21)) + ? 3 + : (Value < (1 << 28)) + ? 4 + : 5; + }; + + // Returns the total number of bytes written since this object was created. + inline int ByteCount() const; + + // Returns true if there was an underlying I/O error since this object was + // created. + bool HadError() const { return had_error_; } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream); + + ZeroCopyOutputStream* output_; + uint8* buffer_; + int buffer_size_; + int total_bytes_; // Sum of sizes of all buffers seen so far. + bool had_error_; // Whether an error occurred during output. + + // Advance the buffer by a given number of bytes. + void Advance(int amount); + + // Called when the buffer runs out to request more data. Implies an + // Advance(buffer_size_). + bool Refresh(); + + static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target); + + // Always-inlined versions of WriteVarint* functions so that code can be + // reused, while still controlling size. For instance, WriteVarint32ToArray() + // should not directly call this: since it is inlined itself, doing so + // would greatly increase the size of generated code. Instead, it should call + // WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already + // out-of-line, so it should just invoke this directly to avoid any extra + // function call overhead. + static uint8* WriteVarint32FallbackToArrayInline( + uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + static uint8* WriteVarint64ToArrayInline( + uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + static int VarintSize32Fallback(uint32 value); +}; + +// inline methods ==================================================== +// The vast majority of varints are only one byte. These inline +// methods optimize for that case. + +inline bool CodedInputStream::ReadVarint32(uint32* value) { + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { + *value = *buffer_; + Advance(1); + return true; + } else { + return ReadVarint32Fallback(value); + } +} + +inline bool CodedInputStream::ReadVarint64(uint64* value) { + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { + *value = *buffer_; + Advance(1); + return true; + } else { + return ReadVarint64Fallback(value); + } +} + +// static +inline const uint8* CodedInputStream::ReadLittleEndian32FromArray( + const uint8* buffer, + uint32* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + memcpy(value, buffer, sizeof(*value)); + return buffer + sizeof(*value); +#else + *value = (static_cast(buffer[0]) ) | + (static_cast(buffer[1]) << 8) | + (static_cast(buffer[2]) << 16) | + (static_cast(buffer[3]) << 24); + return buffer + sizeof(*value); +#endif +} +// static +inline const uint8* CodedInputStream::ReadLittleEndian64FromArray( + const uint8* buffer, + uint64* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + memcpy(value, buffer, sizeof(*value)); + return buffer + sizeof(*value); +#else + uint32 part0 = (static_cast(buffer[0]) ) | + (static_cast(buffer[1]) << 8) | + (static_cast(buffer[2]) << 16) | + (static_cast(buffer[3]) << 24); + uint32 part1 = (static_cast(buffer[4]) ) | + (static_cast(buffer[5]) << 8) | + (static_cast(buffer[6]) << 16) | + (static_cast(buffer[7]) << 24); + *value = static_cast(part0) | + (static_cast(part1) << 32); + return buffer + sizeof(*value); +#endif +} + +inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + memcpy(value, buffer_, sizeof(*value)); + Advance(sizeof(*value)); + return true; + } else { + return ReadLittleEndian32Fallback(value); + } +#else + return ReadLittleEndian32Fallback(value); +#endif +} + +inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { + memcpy(value, buffer_, sizeof(*value)); + Advance(sizeof(*value)); + return true; + } else { + return ReadLittleEndian64Fallback(value); + } +#else + return ReadLittleEndian64Fallback(value); +#endif +} + +inline uint32 CodedInputStream::ReadTag() { + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) { + last_tag_ = buffer_[0]; + Advance(1); + return last_tag_; + } else { + last_tag_ = ReadTagFallback(); + return last_tag_; + } +} + +inline bool CodedInputStream::LastTagWas(uint32 expected) { + return last_tag_ == expected; +} + +inline bool CodedInputStream::ConsumedEntireMessage() { + return legitimate_message_end_; +} + +inline bool CodedInputStream::ExpectTag(uint32 expected) { + if (expected < (1 << 7)) { + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] == expected) { + Advance(1); + return true; + } else { + return false; + } + } else if (expected < (1 << 14)) { + if (GOOGLE_PREDICT_TRUE(BufferSize() >= 2) && + buffer_[0] == static_cast(expected | 0x80) && + buffer_[1] == static_cast(expected >> 7)) { + Advance(2); + return true; + } else { + return false; + } + } else { + // Don't bother optimizing for larger values. + return false; + } +} + +inline const uint8* CodedInputStream::ExpectTagFromArray( + const uint8* buffer, uint32 expected) { + if (expected < (1 << 7)) { + if (buffer[0] == expected) { + return buffer + 1; + } + } else if (expected < (1 << 14)) { + if (buffer[0] == static_cast(expected | 0x80) && + buffer[1] == static_cast(expected >> 7)) { + return buffer + 2; + } + } + return NULL; +} + +inline void CodedInputStream::GetDirectBufferPointerInline(const void** data, + int* size) { + *data = buffer_; + *size = buffer_end_ - buffer_; +} + +inline bool CodedInputStream::ExpectAtEnd() { + // If we are at a limit we know no more bytes can be read. Otherwise, it's + // hard to say without calling Refresh(), and we'd rather not do that. + + if (buffer_ == buffer_end_ && + ((buffer_size_after_limit_ != 0) || + (total_bytes_read_ == current_limit_))) { + last_tag_ = 0; // Pretend we called ReadTag()... + legitimate_message_end_ = true; // ... and it hit EOF. + return true; + } else { + return false; + } +} + +inline int CodedInputStream::CurrentPosition() const { + return total_bytes_read_ - (BufferSize() + buffer_size_after_limit_); +} + +inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) { + if (buffer_size_ < size) { + return NULL; + } else { + uint8* result = buffer_; + Advance(size); + return result; + } +} + +inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value, + uint8* target) { + if (value < 0x80) { + *target = value; + return target + 1; + } else { + return WriteVarint32FallbackToArray(value, target); + } +} + +inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) { + if (value < 0) { + WriteVarint64(static_cast(value)); + } else { + WriteVarint32(static_cast(value)); + } +} + +inline uint8* CodedOutputStream::WriteVarint32SignExtendedToArray( + int32 value, uint8* target) { + if (value < 0) { + return WriteVarint64ToArray(static_cast(value), target); + } else { + return WriteVarint32ToArray(static_cast(value), target); + } +} + +inline uint8* CodedOutputStream::WriteLittleEndian32ToArray(uint32 value, + uint8* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + memcpy(target, &value, sizeof(value)); +#else + target[0] = static_cast(value); + target[1] = static_cast(value >> 8); + target[2] = static_cast(value >> 16); + target[3] = static_cast(value >> 24); +#endif + return target + sizeof(value); +} + +inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, + uint8* target) { +#if defined(PROTOBUF_LITTLE_ENDIAN) + memcpy(target, &value, sizeof(value)); +#else + uint32 part0 = static_cast(value); + uint32 part1 = static_cast(value >> 32); + + target[0] = static_cast(part0); + target[1] = static_cast(part0 >> 8); + target[2] = static_cast(part0 >> 16); + target[3] = static_cast(part0 >> 24); + target[4] = static_cast(part1); + target[5] = static_cast(part1 >> 8); + target[6] = static_cast(part1 >> 16); + target[7] = static_cast(part1 >> 24); +#endif + return target + sizeof(value); +} + +inline void CodedOutputStream::WriteTag(uint32 value) { + WriteVarint32(value); +} + +inline uint8* CodedOutputStream::WriteTagToArray( + uint32 value, uint8* target) { + if (value < (1 << 7)) { + target[0] = value; + return target + 1; + } else if (value < (1 << 14)) { + target[0] = static_cast(value | 0x80); + target[1] = static_cast(value >> 7); + return target + 2; + } else { + return WriteVarint32FallbackToArray(value, target); + } +} + +inline int CodedOutputStream::VarintSize32(uint32 value) { + if (value < (1 << 7)) { + return 1; + } else { + return VarintSize32Fallback(value); + } +} + +inline int CodedOutputStream::VarintSize32SignExtended(int32 value) { + if (value < 0) { + return 10; // TODO(kenton): Make this a symbolic constant. + } else { + return VarintSize32(static_cast(value)); + } +} + +inline void CodedOutputStream::WriteString(const string& str) { + WriteRaw(str.data(), static_cast(str.size())); +} + +inline uint8* CodedOutputStream::WriteStringToArray( + const string& str, uint8* target) { + return WriteRawToArray(str.data(), static_cast(str.size()), target); +} + +inline int CodedOutputStream::ByteCount() const { + return total_bytes_ - buffer_size_; +} + +inline void CodedInputStream::Advance(int amount) { + buffer_ += amount; +} + +inline void CodedOutputStream::Advance(int amount) { + buffer_ += amount; + buffer_size_ -= amount; +} + +inline void CodedInputStream::SetRecursionLimit(int limit) { + recursion_limit_ = limit; +} + +inline bool CodedInputStream::IncrementRecursionDepth() { + ++recursion_depth_; + return recursion_depth_ <= recursion_limit_; +} + +inline void CodedInputStream::DecrementRecursionDepth() { + if (recursion_depth_ > 0) --recursion_depth_; +} + +inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, + MessageFactory* factory) { + extension_pool_ = pool; + extension_factory_ = factory; +} + +inline const DescriptorPool* CodedInputStream::GetExtensionPool() { + return extension_pool_; +} + +inline MessageFactory* CodedInputStream::GetExtensionFactory() { + return extension_factory_; +} + +inline int CodedInputStream::BufferSize() const { + return buffer_end_ - buffer_; +} + +inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) + : input_(input), + buffer_(NULL), + buffer_end_(NULL), + total_bytes_read_(0), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(kint32max), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), + recursion_depth_(0), + recursion_limit_(default_recursion_limit_), + extension_pool_(NULL), + extension_factory_(NULL) { + // Eagerly Refresh() so buffer space is immediately available. + Refresh(); +} + +inline CodedInputStream::CodedInputStream(const uint8* buffer, int size) + : input_(NULL), + buffer_(buffer), + buffer_end_(buffer + size), + total_bytes_read_(size), + overflow_bytes_(0), + last_tag_(0), + legitimate_message_end_(false), + aliasing_enabled_(false), + current_limit_(size), + buffer_size_after_limit_(0), + total_bytes_limit_(kDefaultTotalBytesLimit), + total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold), + recursion_depth_(0), + recursion_limit_(default_recursion_limit_), + extension_pool_(NULL), + extension_factory_(NULL) { + // Note that setting current_limit_ == size is important to prevent some + // code paths from trying to access input_ and segfaulting. +} + +inline bool CodedInputStream::IsFlat() const { + return input_ == NULL; +} + +} // namespace io +} // namespace protobuf + + +#if defined(_MSC_VER) && _MSC_VER >= 1300 + #pragma runtime_checks("c", restore) +#endif // _MSC_VER + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_inl.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_inl.h new file mode 100644 index 000000000..144f44f06 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_inl.h @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: jasonh@google.com (Jason Hsueh) +// +// Implements methods of coded_stream.h that need to be inlined for performance +// reasons, but should not be defined in a public header. + +#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ +#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { + +inline bool CodedInputStream::InternalReadStringInline(string* buffer, + int size) { + if (size < 0) return false; // security: size is often user-supplied + + if (BufferSize() >= size) { + STLStringResizeUninitialized(buffer, size); + // When buffer is empty, string_as_array(buffer) will return NULL but memcpy + // requires non-NULL pointers even when size is 0. Hench this check. + if (size > 0) { + memcpy(string_as_array(buffer), buffer_, size); + Advance(size); + } + return true; + } + + return ReadStringFallback(buffer, size); +} + +} // namespace io +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_unittest.cc new file mode 100644 index 000000000..2daab194c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/coded_stream_unittest.cc @@ -0,0 +1,1191 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains tests and benchmarks. + +#include + +#include + +#include + +#include +#include +#include +#include + + +// This declares an unsigned long long integer literal in a portable way. +// (The original macro is way too big and ruins my formatting.) +#undef ULL +#define ULL(x) GOOGLE_ULONGLONG(x) + +namespace google { +namespace protobuf { +namespace io { +namespace { + +// =================================================================== +// Data-Driven Test Infrastructure + +// TEST_1D and TEST_2D are macros I'd eventually like to see added to +// gTest. These macros can be used to declare tests which should be +// run multiple times, once for each item in some input array. TEST_1D +// tests all cases in a single input array. TEST_2D tests all +// combinations of cases from two arrays. The arrays must be statically +// defined such that the GOOGLE_ARRAYSIZE() macro works on them. Example: +// +// int kCases[] = {1, 2, 3, 4} +// TEST_1D(MyFixture, MyTest, kCases) { +// EXPECT_GT(kCases_case, 0); +// } +// +// This test iterates through the numbers 1, 2, 3, and 4 and tests that +// they are all grater than zero. In case of failure, the exact case +// which failed will be printed. The case type must be printable using +// ostream::operator<<. + +// TODO(kenton): gTest now supports "parameterized tests" which would be +// a better way to accomplish this. Rewrite when time permits. + +#define TEST_1D(FIXTURE, NAME, CASES) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType& CASES##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES " case #" << i << ": " << CASES[i]); \ + DoSingleCase(CASES[i]); \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case) + +#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ + for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ + << #CASES2 " case #" << j << ": " << CASES2[j]); \ + DoSingleCase(CASES1[i], CASES2[j]); \ + } \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case) + +// =================================================================== + +class CodedStreamTest : public testing::Test { + protected: + // Helper method used by tests for bytes warning. See implementation comment + // for further information. + static void SetupTotalBytesLimitWarningTest( + int total_bytes_limit, int warning_threshold, + vector* out_errors, vector* out_warnings); + + // Buffer used during most of the tests. This assumes tests run sequentially. + static const int kBufferSize = 1024 * 64; + static uint8 buffer_[kBufferSize]; +}; + +uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize]; + +// We test each operation over a variety of block sizes to insure that +// we test cases where reads or writes cross buffer boundaries, cases +// where they don't, and cases where there is so much buffer left that +// we can use special optimized paths that don't worry about bounds +// checks. +const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024}; + +// ------------------------------------------------------------------- +// Varint tests. + +struct VarintCase { + uint8 bytes[10]; // Encoded bytes. + int size; // Encoded size, in bytes. + uint64 value; // Parsed value. +}; + +inline std::ostream& operator<<(std::ostream& os, const VarintCase& c) { + return os << c.value; +} + +VarintCase kVarintCases[] = { + // 32-bit values + {{0x00} , 1, 0}, + {{0x01} , 1, 1}, + {{0x7f} , 1, 127}, + {{0xa2, 0x74}, 2, (0x22 << 0) | (0x74 << 7)}, // 14882 + {{0xbe, 0xf7, 0x92, 0x84, 0x0b}, 5, // 2961488830 + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | + (ULL(0x0b) << 28)}, + + // 64-bit + {{0xbe, 0xf7, 0x92, 0x84, 0x1b}, 5, // 7256456126 + (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | + (ULL(0x1b) << 28)}, + {{0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49}, 8, // 41256202580718336 + (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | + (ULL(0x43) << 28) | (ULL(0x49) << 35) | (ULL(0x24) << 42) | + (ULL(0x49) << 49)}, + // 11964378330978735131 + {{0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01}, 10, + (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | + (ULL(0x3b) << 28) | (ULL(0x56) << 35) | (ULL(0x00) << 42) | + (ULL(0x05) << 49) | (ULL(0x26) << 56) | (ULL(0x01) << 63)}, +}; + +TEST_2D(CodedStreamTest, ReadVarint32, kVarintCases, kBlockSizes) { + memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint32 value; + EXPECT_TRUE(coded_input.ReadVarint32(&value)); + EXPECT_EQ(static_cast(kVarintCases_case.value), value); + } + + EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); +} + +TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) { + memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint32 expected_value = static_cast(kVarintCases_case.value); + EXPECT_EQ(expected_value, coded_input.ReadTag()); + + EXPECT_TRUE(coded_input.LastTagWas(expected_value)); + EXPECT_FALSE(coded_input.LastTagWas(expected_value + 1)); + } + + EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); +} + +// This is the regression test that verifies that there is no issues +// with the empty input buffers handling. +TEST_F(CodedStreamTest, EmptyInputBeforeEos) { + class In : public ZeroCopyInputStream { + public: + In() : count_(0) {} + private: + virtual bool Next(const void** data, int* size) { + *data = NULL; + *size = 0; + return count_++ < 2; + } + virtual void BackUp(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + } + virtual bool Skip(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + return false; + } + virtual int64 ByteCount() const { return 0; } + int count_; + } in; + CodedInputStream input(&in); + input.ReadTag(); + EXPECT_TRUE(input.ConsumedEntireMessage()); +} + +TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { + // Leave one byte at the beginning of the buffer so we can read it + // to force the first buffer to be loaded. + buffer_[0] = '\0'; + memcpy(buffer_ + 1, kVarintCases_case.bytes, kVarintCases_case.size); + ArrayInputStream input(buffer_, sizeof(buffer_)); + + { + CodedInputStream coded_input(&input); + + // Read one byte to force coded_input.Refill() to be called. Otherwise, + // ExpectTag() will return a false negative. + uint8 dummy; + coded_input.ReadRaw(&dummy, 1); + EXPECT_EQ((uint)'\0', (uint)dummy); + + uint32 expected_value = static_cast(kVarintCases_case.value); + + // ExpectTag() produces false negatives for large values. + if (kVarintCases_case.size <= 2) { + EXPECT_FALSE(coded_input.ExpectTag(expected_value + 1)); + EXPECT_TRUE(coded_input.ExpectTag(expected_value)); + } else { + EXPECT_FALSE(coded_input.ExpectTag(expected_value)); + } + } + + if (kVarintCases_case.size <= 2) { + EXPECT_EQ(kVarintCases_case.size + 1, input.ByteCount()); + } else { + EXPECT_EQ(1, input.ByteCount()); + } +} + +TEST_1D(CodedStreamTest, ExpectTagFromArray, kVarintCases) { + memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); + + const uint32 expected_value = static_cast(kVarintCases_case.value); + + // If the expectation succeeds, it should return a pointer past the tag. + if (kVarintCases_case.size <= 2) { + EXPECT_TRUE(NULL == + CodedInputStream::ExpectTagFromArray(buffer_, + expected_value + 1)); + EXPECT_TRUE(buffer_ + kVarintCases_case.size == + CodedInputStream::ExpectTagFromArray(buffer_, expected_value)); + } else { + EXPECT_TRUE(NULL == + CodedInputStream::ExpectTagFromArray(buffer_, expected_value)); + } +} + +TEST_2D(CodedStreamTest, ReadVarint64, kVarintCases, kBlockSizes) { + memcpy(buffer_, kVarintCases_case.bytes, kVarintCases_case.size); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint64 value; + EXPECT_TRUE(coded_input.ReadVarint64(&value)); + EXPECT_EQ(kVarintCases_case.value, value); + } + + EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); +} + +TEST_2D(CodedStreamTest, WriteVarint32, kVarintCases, kBlockSizes) { + if (kVarintCases_case.value > ULL(0x00000000FFFFFFFF)) { + // Skip this test for the 64-bit values. + return; + } + + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteVarint32(static_cast(kVarintCases_case.value)); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount()); + } + + EXPECT_EQ(kVarintCases_case.size, output.ByteCount()); + EXPECT_EQ(0, + memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); +} + +TEST_2D(CodedStreamTest, WriteVarint64, kVarintCases, kBlockSizes) { + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteVarint64(kVarintCases_case.value); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(kVarintCases_case.size, coded_output.ByteCount()); + } + + EXPECT_EQ(kVarintCases_case.size, output.ByteCount()); + EXPECT_EQ(0, + memcmp(buffer_, kVarintCases_case.bytes, kVarintCases_case.size)); +} + +// This test causes gcc 3.3.5 (and earlier?) to give the cryptic error: +// "sorry, unimplemented: `method_call_expr' not supported by dump_expr" +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) + +int32 kSignExtendedVarintCases[] = { + 0, 1, -1, 1237894, -37895138 +}; + +TEST_2D(CodedStreamTest, WriteVarint32SignExtended, + kSignExtendedVarintCases, kBlockSizes) { + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteVarint32SignExtended(kSignExtendedVarintCases_case); + EXPECT_FALSE(coded_output.HadError()); + + if (kSignExtendedVarintCases_case < 0) { + EXPECT_EQ(10, coded_output.ByteCount()); + } else { + EXPECT_LE(coded_output.ByteCount(), 5); + } + } + + if (kSignExtendedVarintCases_case < 0) { + EXPECT_EQ(10, output.ByteCount()); + } else { + EXPECT_LE(output.ByteCount(), 5); + } + + // Read value back in as a varint64 and insure it matches. + ArrayInputStream input(buffer_, sizeof(buffer_)); + + { + CodedInputStream coded_input(&input); + + uint64 value; + EXPECT_TRUE(coded_input.ReadVarint64(&value)); + + EXPECT_EQ(kSignExtendedVarintCases_case, static_cast(value)); + } + + EXPECT_EQ(output.ByteCount(), input.ByteCount()); +} + +#endif + + +// ------------------------------------------------------------------- +// Varint failure test. + +struct VarintErrorCase { + uint8 bytes[12]; + int size; + bool can_parse; +}; + +inline std::ostream& operator<<(std::ostream& os, const VarintErrorCase& c) { + return os << "size " << c.size; +} + +const VarintErrorCase kVarintErrorCases[] = { + // Control case. (Insures that there isn't something else wrong that + // makes parsing always fail.) + {{0x00}, 1, true}, + + // No input data. + {{}, 0, false}, + + // Input ends unexpectedly. + {{0xf0, 0xab}, 2, false}, + + // Input ends unexpectedly after 32 bits. + {{0xf0, 0xab, 0xc9, 0x9a, 0xf8, 0xb2}, 6, false}, + + // Longer than 10 bytes. + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01}, + 11, false}, +}; + +TEST_2D(CodedStreamTest, ReadVarint32Error, kVarintErrorCases, kBlockSizes) { + memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); + ArrayInputStream input(buffer_, kVarintErrorCases_case.size, + kBlockSizes_case); + CodedInputStream coded_input(&input); + + uint32 value; + EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint32(&value)); +} + +TEST_2D(CodedStreamTest, ReadVarint64Error, kVarintErrorCases, kBlockSizes) { + memcpy(buffer_, kVarintErrorCases_case.bytes, kVarintErrorCases_case.size); + ArrayInputStream input(buffer_, kVarintErrorCases_case.size, + kBlockSizes_case); + CodedInputStream coded_input(&input); + + uint64 value; + EXPECT_EQ(kVarintErrorCases_case.can_parse, coded_input.ReadVarint64(&value)); +} + +// ------------------------------------------------------------------- +// VarintSize + +struct VarintSizeCase { + uint64 value; + int size; +}; + +inline std::ostream& operator<<(std::ostream& os, const VarintSizeCase& c) { + return os << c.value; +} + +VarintSizeCase kVarintSizeCases[] = { + {0u, 1}, + {1u, 1}, + {127u, 1}, + {128u, 2}, + {758923u, 3}, + {4000000000u, 5}, + {ULL(41256202580718336), 8}, + {ULL(11964378330978735131), 10}, +}; + +TEST_1D(CodedStreamTest, VarintSize32, kVarintSizeCases) { + if (kVarintSizeCases_case.value > 0xffffffffu) { + // Skip 64-bit values. + return; + } + + EXPECT_EQ(kVarintSizeCases_case.size, + CodedOutputStream::VarintSize32( + static_cast(kVarintSizeCases_case.value))); +} + +TEST_1D(CodedStreamTest, VarintSize64, kVarintSizeCases) { + EXPECT_EQ(kVarintSizeCases_case.size, + CodedOutputStream::VarintSize64(kVarintSizeCases_case.value)); +} + +// ------------------------------------------------------------------- +// Fixed-size int tests + +struct Fixed32Case { + uint8 bytes[sizeof(uint32)]; // Encoded bytes. + uint32 value; // Parsed value. +}; + +struct Fixed64Case { + uint8 bytes[sizeof(uint64)]; // Encoded bytes. + uint64 value; // Parsed value. +}; + +inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) { + return os << "0x" << hex << c.value << dec; +} + +inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) { + return os << "0x" << hex << c.value << dec; +} + +Fixed32Case kFixed32Cases[] = { + {{0xef, 0xcd, 0xab, 0x90}, 0x90abcdefu}, + {{0x12, 0x34, 0x56, 0x78}, 0x78563412u}, +}; + +Fixed64Case kFixed64Cases[] = { + {{0xef, 0xcd, 0xab, 0x90, 0x12, 0x34, 0x56, 0x78}, ULL(0x7856341290abcdef)}, + {{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, ULL(0x8877665544332211)}, +}; + +TEST_2D(CodedStreamTest, ReadLittleEndian32, kFixed32Cases, kBlockSizes) { + memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint32 value; + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(kFixed32Cases_case.value, value); + } + + EXPECT_EQ(sizeof(uint32), input.ByteCount()); +} + +TEST_2D(CodedStreamTest, ReadLittleEndian64, kFixed64Cases, kBlockSizes) { + memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + uint64 value; + EXPECT_TRUE(coded_input.ReadLittleEndian64(&value)); + EXPECT_EQ(kFixed64Cases_case.value, value); + } + + EXPECT_EQ(sizeof(uint64), input.ByteCount()); +} + +TEST_2D(CodedStreamTest, WriteLittleEndian32, kFixed32Cases, kBlockSizes) { + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteLittleEndian32(kFixed32Cases_case.value); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(sizeof(uint32), coded_output.ByteCount()); + } + + EXPECT_EQ(sizeof(uint32), output.ByteCount()); + EXPECT_EQ(0, memcmp(buffer_, kFixed32Cases_case.bytes, sizeof(uint32))); +} + +TEST_2D(CodedStreamTest, WriteLittleEndian64, kFixed64Cases, kBlockSizes) { + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteLittleEndian64(kFixed64Cases_case.value); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(sizeof(uint64), coded_output.ByteCount()); + } + + EXPECT_EQ(sizeof(uint64), output.ByteCount()); + EXPECT_EQ(0, memcmp(buffer_, kFixed64Cases_case.bytes, sizeof(uint64))); +} + +// Tests using the static methods to read fixed-size values from raw arrays. + +TEST_1D(CodedStreamTest, ReadLittleEndian32FromArray, kFixed32Cases) { + memcpy(buffer_, kFixed32Cases_case.bytes, sizeof(kFixed32Cases_case.bytes)); + + uint32 value; + const uint8* end = CodedInputStream::ReadLittleEndian32FromArray( + buffer_, &value); + EXPECT_EQ(kFixed32Cases_case.value, value); + EXPECT_TRUE(end == buffer_ + sizeof(value)); +} + +TEST_1D(CodedStreamTest, ReadLittleEndian64FromArray, kFixed64Cases) { + memcpy(buffer_, kFixed64Cases_case.bytes, sizeof(kFixed64Cases_case.bytes)); + + uint64 value; + const uint8* end = CodedInputStream::ReadLittleEndian64FromArray( + buffer_, &value); + EXPECT_EQ(kFixed64Cases_case.value, value); + EXPECT_TRUE(end == buffer_ + sizeof(value)); +} + +// ------------------------------------------------------------------- +// Raw reads and writes + +const char kRawBytes[] = "Some bytes which will be written and read raw."; + +TEST_1D(CodedStreamTest, ReadRaw, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + char read_buffer[sizeof(kRawBytes)]; + + { + CodedInputStream coded_input(&input); + + EXPECT_TRUE(coded_input.ReadRaw(read_buffer, sizeof(kRawBytes))); + EXPECT_EQ(0, memcmp(kRawBytes, read_buffer, sizeof(kRawBytes))); + } + + EXPECT_EQ(sizeof(kRawBytes), input.ByteCount()); +} + +TEST_1D(CodedStreamTest, WriteRaw, kBlockSizes) { + ArrayOutputStream output(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedOutputStream coded_output(&output); + + coded_output.WriteRaw(kRawBytes, sizeof(kRawBytes)); + EXPECT_FALSE(coded_output.HadError()); + + EXPECT_EQ(sizeof(kRawBytes), coded_output.ByteCount()); + } + + EXPECT_EQ(sizeof(kRawBytes), output.ByteCount()); + EXPECT_EQ(0, memcmp(buffer_, kRawBytes, sizeof(kRawBytes))); +} + +TEST_1D(CodedStreamTest, ReadString, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(kRawBytes, str); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +// Check to make sure ReadString doesn't crash on impossibly large strings. +TEST_1D(CodedStreamTest, ReadStringImpossiblyLarge, kBlockSizes) { + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + string str; + // Try to read a gigabyte. + EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); + } +} + +TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) { + // Same test as above, except directly use a buffer. This used to cause + // crashes while the above did not. + uint8 buffer[8]; + CodedInputStream coded_input(buffer, 8); + string str; + EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); +} + +TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) { + scoped_array buffer(new uint8[8]); + CodedInputStream coded_input(buffer.get(), 8); + string str; + EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); +} + + +// ------------------------------------------------------------------- +// Skip + +const char kSkipTestBytes[] = + ""; +const char kSkipOutputTestBytes[] = + "---------------------------------"; + +TEST_1D(CodedStreamTest, SkipInput, kBlockSizes) { + memcpy(buffer_, kSkipTestBytes, sizeof(kSkipTestBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(""))); + EXPECT_EQ("", str); + EXPECT_TRUE(coded_input.Skip(strlen(""))); + EXPECT_TRUE(coded_input.ReadString(&str, strlen(""))); + EXPECT_EQ("", str); + } + + EXPECT_EQ(strlen(kSkipTestBytes), input.ByteCount()); +} + +// ------------------------------------------------------------------- +// GetDirectBufferPointer + +TEST_F(CodedStreamTest, GetDirectBufferPointerInput) { + ArrayInputStream input(buffer_, sizeof(buffer_), 8); + CodedInputStream coded_input(&input); + + const void* ptr; + int size; + + EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Peeking again should return the same pointer. + EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Skip forward in the same buffer then peek again. + EXPECT_TRUE(coded_input.Skip(3)); + EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_ + 3, ptr); + EXPECT_EQ(5, size); + + // Skip to end of buffer and peek -- should get next buffer. + EXPECT_TRUE(coded_input.Skip(5)); + EXPECT_TRUE(coded_input.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_ + 8, ptr); + EXPECT_EQ(8, size); +} + +TEST_F(CodedStreamTest, GetDirectBufferPointerInlineInput) { + ArrayInputStream input(buffer_, sizeof(buffer_), 8); + CodedInputStream coded_input(&input); + + const void* ptr; + int size; + + coded_input.GetDirectBufferPointerInline(&ptr, &size); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Peeking again should return the same pointer. + coded_input.GetDirectBufferPointerInline(&ptr, &size); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Skip forward in the same buffer then peek again. + EXPECT_TRUE(coded_input.Skip(3)); + coded_input.GetDirectBufferPointerInline(&ptr, &size); + EXPECT_EQ(buffer_ + 3, ptr); + EXPECT_EQ(5, size); + + // Skip to end of buffer and peek -- should return false and provide an empty + // buffer. It does not try to Refresh(). + EXPECT_TRUE(coded_input.Skip(5)); + coded_input.GetDirectBufferPointerInline(&ptr, &size); + EXPECT_EQ(buffer_ + 8, ptr); + EXPECT_EQ(0, size); +} + +TEST_F(CodedStreamTest, GetDirectBufferPointerOutput) { + ArrayOutputStream output(buffer_, sizeof(buffer_), 8); + CodedOutputStream coded_output(&output); + + void* ptr; + int size; + + EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Peeking again should return the same pointer. + EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_, ptr); + EXPECT_EQ(8, size); + + // Skip forward in the same buffer then peek again. + EXPECT_TRUE(coded_output.Skip(3)); + EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_ + 3, ptr); + EXPECT_EQ(5, size); + + // Skip to end of buffer and peek -- should get next buffer. + EXPECT_TRUE(coded_output.Skip(5)); + EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_ + 8, ptr); + EXPECT_EQ(8, size); + + // Skip over multiple buffers. + EXPECT_TRUE(coded_output.Skip(22)); + EXPECT_TRUE(coded_output.GetDirectBufferPointer(&ptr, &size)); + EXPECT_EQ(buffer_ + 30, ptr); + EXPECT_EQ(2, size); +} + +// ------------------------------------------------------------------- +// Limits + +TEST_1D(CodedStreamTest, BasicLimit, kBlockSizes) { + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + CodedInputStream::Limit limit = coded_input.PushLimit(8); + + // Read until we hit the limit. + uint32 value; + EXPECT_EQ(8, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(4, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + EXPECT_FALSE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + + coded_input.PopLimit(limit); + + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + } + + EXPECT_EQ(12, input.ByteCount()); +} + +// Test what happens when we push two limits where the second (top) one is +// shorter. +TEST_1D(CodedStreamTest, SmallLimitOnTopOfBigLimit, kBlockSizes) { + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + CodedInputStream::Limit limit1 = coded_input.PushLimit(8); + EXPECT_EQ(8, coded_input.BytesUntilLimit()); + CodedInputStream::Limit limit2 = coded_input.PushLimit(4); + + uint32 value; + + // Read until we hit limit2, the top and shortest limit. + EXPECT_EQ(4, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + EXPECT_FALSE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + + coded_input.PopLimit(limit2); + + // Read until we hit limit1. + EXPECT_EQ(4, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + EXPECT_FALSE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + + coded_input.PopLimit(limit1); + + // No more limits. + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + } + + EXPECT_EQ(12, input.ByteCount()); +} + +// Test what happens when we push two limits where the second (top) one is +// longer. In this case, the top limit is shortened to match the previous +// limit. +TEST_1D(CodedStreamTest, BigLimitOnTopOfSmallLimit, kBlockSizes) { + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + CodedInputStream::Limit limit1 = coded_input.PushLimit(4); + EXPECT_EQ(4, coded_input.BytesUntilLimit()); + CodedInputStream::Limit limit2 = coded_input.PushLimit(8); + + uint32 value; + + // Read until we hit limit2. Except, wait! limit1 is shorter, so + // we end up hitting that first, despite having 4 bytes to go on + // limit2. + EXPECT_EQ(4, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + EXPECT_FALSE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + + coded_input.PopLimit(limit2); + + // OK, popped limit2, now limit1 is on top, which we've already hit. + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + EXPECT_FALSE(coded_input.ReadLittleEndian32(&value)); + EXPECT_EQ(0, coded_input.BytesUntilLimit()); + + coded_input.PopLimit(limit1); + + // No more limits. + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + } + + EXPECT_EQ(8, input.ByteCount()); +} + +TEST_F(CodedStreamTest, ExpectAtEnd) { + // Test ExpectAtEnd(), which is based on limits. + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + + EXPECT_FALSE(coded_input.ExpectAtEnd()); + + CodedInputStream::Limit limit = coded_input.PushLimit(4); + + uint32 value; + EXPECT_TRUE(coded_input.ReadLittleEndian32(&value)); + EXPECT_TRUE(coded_input.ExpectAtEnd()); + + coded_input.PopLimit(limit); + EXPECT_FALSE(coded_input.ExpectAtEnd()); +} + +TEST_F(CodedStreamTest, NegativeLimit) { + // Check what happens when we push a negative limit. + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + + CodedInputStream::Limit limit = coded_input.PushLimit(-1234); + // BytesUntilLimit() returns -1 to mean "no limit", which actually means + // "the limit is INT_MAX relative to the beginning of the stream". + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + coded_input.PopLimit(limit); +} + +TEST_F(CodedStreamTest, NegativeLimitAfterReading) { + // Check what happens when we push a negative limit. + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + ASSERT_TRUE(coded_input.Skip(128)); + + CodedInputStream::Limit limit = coded_input.PushLimit(-64); + // BytesUntilLimit() returns -1 to mean "no limit", which actually means + // "the limit is INT_MAX relative to the beginning of the stream". + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + coded_input.PopLimit(limit); +} + +TEST_F(CodedStreamTest, OverflowLimit) { + // Check what happens when we push a limit large enough that its absolute + // position is more than 2GB into the stream. + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + ASSERT_TRUE(coded_input.Skip(128)); + + CodedInputStream::Limit limit = coded_input.PushLimit(INT_MAX); + // BytesUntilLimit() returns -1 to mean "no limit", which actually means + // "the limit is INT_MAX relative to the beginning of the stream". + EXPECT_EQ(-1, coded_input.BytesUntilLimit()); + coded_input.PopLimit(limit); +} + +TEST_F(CodedStreamTest, TotalBytesLimit) { + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + coded_input.SetTotalBytesLimit(16, -1); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, 16)); + + vector errors; + + { + ScopedMemoryLog error_log; + EXPECT_FALSE(coded_input.ReadString(&str, 1)); + errors = error_log.GetMessages(ERROR); + } + + ASSERT_EQ(1, errors.size()); + EXPECT_PRED_FORMAT2(testing::IsSubstring, + "A protocol message was rejected because it was too big", errors[0]); + + coded_input.SetTotalBytesLimit(32, -1); + EXPECT_TRUE(coded_input.ReadString(&str, 16)); +} + +TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { + // total_bytes_limit_ is not a valid place for a message to end. + + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + + // Set both total_bytes_limit and a regular limit at 16 bytes. + coded_input.SetTotalBytesLimit(16, -1); + CodedInputStream::Limit limit = coded_input.PushLimit(16); + + // Read 16 bytes. + string str; + EXPECT_TRUE(coded_input.ReadString(&str, 16)); + + // Read a tag. Should fail, but report being a valid endpoint since it's + // a regular limit. + EXPECT_EQ(0, coded_input.ReadTag()); + EXPECT_TRUE(coded_input.ConsumedEntireMessage()); + + // Pop the limit. + coded_input.PopLimit(limit); + + // Read a tag. Should fail, and report *not* being a valid endpoint, since + // this time we're hitting the total bytes limit. + EXPECT_EQ(0, coded_input.ReadTag()); + EXPECT_FALSE(coded_input.ConsumedEntireMessage()); +} + +// This method is used by the tests below. +// It constructs a CodedInputStream with the given limits and tries to read 2KiB +// of data from it. Then it returns the logged errors and warnings in the given +// vectors. +void CodedStreamTest::SetupTotalBytesLimitWarningTest( + int total_bytes_limit, int warning_threshold, + vector* out_errors, vector* out_warnings) { + ArrayInputStream raw_input(buffer_, sizeof(buffer_), 128); + + ScopedMemoryLog scoped_log; + { + CodedInputStream input(&raw_input); + input.SetTotalBytesLimit(total_bytes_limit, warning_threshold); + string str; + EXPECT_TRUE(input.ReadString(&str, 2048)); + } + + *out_errors = scoped_log.GetMessages(ERROR); + *out_warnings = scoped_log.GetMessages(WARNING); +} + +TEST_F(CodedStreamTest, TotalBytesLimitWarning) { + vector errors; + vector warnings; + SetupTotalBytesLimitWarningTest(10240, 1024, &errors, &warnings); + + EXPECT_EQ(0, errors.size()); + + ASSERT_EQ(2, warnings.size()); + EXPECT_PRED_FORMAT2(testing::IsSubstring, + "Reading dangerously large protocol message. If the message turns out to " + "be larger than 10240 bytes, parsing will be halted for security reasons.", + warnings[0]); + EXPECT_PRED_FORMAT2(testing::IsSubstring, + "The total number of bytes read was 2048", + warnings[1]); +} + +TEST_F(CodedStreamTest, TotalBytesLimitWarningDisabled) { + vector errors; + vector warnings; + + // Test with -1 + SetupTotalBytesLimitWarningTest(10240, -1, &errors, &warnings); + EXPECT_EQ(0, errors.size()); + EXPECT_EQ(0, warnings.size()); + + // Test again with -2, expecting the same result + SetupTotalBytesLimitWarningTest(10240, -2, &errors, &warnings); + EXPECT_EQ(0, errors.size()); + EXPECT_EQ(0, warnings.size()); +} + + +TEST_F(CodedStreamTest, RecursionLimit) { + ArrayInputStream input(buffer_, sizeof(buffer_)); + CodedInputStream coded_input(&input); + coded_input.SetRecursionLimit(4); + + // This is way too much testing for a counter. + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 + coded_input.DecrementRecursionDepth(); // 5 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 6 + coded_input.DecrementRecursionDepth(); // 5 + coded_input.DecrementRecursionDepth(); // 4 + coded_input.DecrementRecursionDepth(); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + coded_input.DecrementRecursionDepth(); // 4 + coded_input.DecrementRecursionDepth(); // 3 + coded_input.DecrementRecursionDepth(); // 2 + coded_input.DecrementRecursionDepth(); // 1 + coded_input.DecrementRecursionDepth(); // 0 + coded_input.DecrementRecursionDepth(); // 0 + coded_input.DecrementRecursionDepth(); // 0 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 1 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 2 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 3 + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 4 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 5 + + coded_input.SetRecursionLimit(6); + EXPECT_TRUE(coded_input.IncrementRecursionDepth()); // 6 + EXPECT_FALSE(coded_input.IncrementRecursionDepth()); // 7 +} + + +class ReallyBigInputStream : public ZeroCopyInputStream { + public: + ReallyBigInputStream() : backup_amount_(0), buffer_count_(0) {} + ~ReallyBigInputStream() {} + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) { + // We only expect BackUp() to be called at the end. + EXPECT_EQ(0, backup_amount_); + + switch (buffer_count_++) { + case 0: + *data = buffer_; + *size = sizeof(buffer_); + return true; + case 1: + // Return an enormously large buffer that, when combined with the 1k + // returned already, should overflow the total_bytes_read_ counter in + // CodedInputStream. Note that we'll only read the first 1024 bytes + // of this buffer so it's OK that we have it point at buffer_. + *data = buffer_; + *size = INT_MAX; + return true; + default: + return false; + } + } + + void BackUp(int count) { + backup_amount_ = count; + } + + bool Skip(int count) { GOOGLE_LOG(FATAL) << "Not implemented."; return false; } + int64 ByteCount() const { GOOGLE_LOG(FATAL) << "Not implemented."; return 0; } + + int backup_amount_; + + private: + char buffer_[1024]; + int64 buffer_count_; +}; + +TEST_F(CodedStreamTest, InputOver2G) { + // CodedInputStream should gracefully handle input over 2G and call + // input.BackUp() with the correct number of bytes on destruction. + ReallyBigInputStream input; + + vector errors; + + { + ScopedMemoryLog error_log; + CodedInputStream coded_input(&input); + string str; + EXPECT_TRUE(coded_input.ReadString(&str, 512)); + EXPECT_TRUE(coded_input.ReadString(&str, 1024)); + errors = error_log.GetMessages(ERROR); + } + + EXPECT_EQ(INT_MAX - 512, input.backup_amount_); + EXPECT_EQ(0, errors.size()); +} + +// =================================================================== + + +} // namespace +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.cc new file mode 100644 index 000000000..fe1f3319d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.cc @@ -0,0 +1,326 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: brianolson@google.com (Brian Olson) +// +// This file contains the implementation of classes GzipInputStream and +// GzipOutputStream. + +#include "config.h" + +#if HAVE_ZLIB +#include + +#include + +namespace google { +namespace protobuf { +namespace io { + +static const int kDefaultBufferSize = 65536; + +GzipInputStream::GzipInputStream( + ZeroCopyInputStream* sub_stream, Format format, int buffer_size) + : format_(format), sub_stream_(sub_stream), zerror_(Z_OK) { + zcontext_.zalloc = Z_NULL; + zcontext_.zfree = Z_NULL; + zcontext_.opaque = Z_NULL; + zcontext_.total_out = 0; + zcontext_.next_in = NULL; + zcontext_.avail_in = 0; + zcontext_.total_in = 0; + zcontext_.msg = NULL; + if (buffer_size == -1) { + output_buffer_length_ = kDefaultBufferSize; + } else { + output_buffer_length_ = buffer_size; + } + output_buffer_ = operator new(output_buffer_length_); + GOOGLE_CHECK(output_buffer_ != NULL); + zcontext_.next_out = static_cast(output_buffer_); + zcontext_.avail_out = output_buffer_length_; + output_position_ = output_buffer_; +} +GzipInputStream::~GzipInputStream() { + operator delete(output_buffer_); + zerror_ = inflateEnd(&zcontext_); +} + +static inline int internalInflateInit2( + z_stream* zcontext, GzipInputStream::Format format) { + int windowBitsFormat = 0; + switch (format) { + case GzipInputStream::GZIP: windowBitsFormat = 16; break; + case GzipInputStream::AUTO: windowBitsFormat = 32; break; + case GzipInputStream::ZLIB: windowBitsFormat = 0; break; + } + return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat); +} + +int GzipInputStream::Inflate(int flush) { + if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) { + // previous inflate filled output buffer. don't change input params yet. + } else if (zcontext_.avail_in == 0) { + const void* in; + int in_size; + bool first = zcontext_.next_in == NULL; + bool ok = sub_stream_->Next(&in, &in_size); + if (!ok) { + zcontext_.next_out = NULL; + zcontext_.avail_out = 0; + return Z_STREAM_END; + } + zcontext_.next_in = static_cast(const_cast(in)); + zcontext_.avail_in = in_size; + if (first) { + int error = internalInflateInit2(&zcontext_, format_); + if (error != Z_OK) { + return error; + } + } + } + zcontext_.next_out = static_cast(output_buffer_); + zcontext_.avail_out = output_buffer_length_; + output_position_ = output_buffer_; + int error = inflate(&zcontext_, flush); + return error; +} + +void GzipInputStream::DoNextOutput(const void** data, int* size) { + *data = output_position_; + *size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_); + output_position_ = zcontext_.next_out; +} + +// implements ZeroCopyInputStream ---------------------------------- +bool GzipInputStream::Next(const void** data, int* size) { + bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) + || (zerror_ == Z_BUF_ERROR); + if ((!ok) || (zcontext_.next_out == NULL)) { + return false; + } + if (zcontext_.next_out != output_position_) { + DoNextOutput(data, size); + return true; + } + if (zerror_ == Z_STREAM_END) { + if (zcontext_.next_out != NULL) { + // sub_stream_ may have concatenated streams to follow + zerror_ = inflateEnd(&zcontext_); + if (zerror_ != Z_OK) { + return false; + } + zerror_ = internalInflateInit2(&zcontext_, format_); + if (zerror_ != Z_OK) { + return false; + } + } else { + *data = NULL; + *size = 0; + return false; + } + } + zerror_ = Inflate(Z_NO_FLUSH); + if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) { + // The underlying stream's Next returned false inside Inflate. + return false; + } + ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) + || (zerror_ == Z_BUF_ERROR); + if (!ok) { + return false; + } + DoNextOutput(data, size); + return true; +} +void GzipInputStream::BackUp(int count) { + output_position_ = reinterpret_cast( + reinterpret_cast(output_position_) - count); +} +bool GzipInputStream::Skip(int count) { + const void* data; + int size; + bool ok = Next(&data, &size); + while (ok && (size < count)) { + count -= size; + ok = Next(&data, &size); + } + if (size > count) { + BackUp(size - count); + } + return ok; +} +int64 GzipInputStream::ByteCount() const { + return zcontext_.total_out + + (((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_)); +} + +// ========================================================================= + +GzipOutputStream::Options::Options() + : format(GZIP), + buffer_size(kDefaultBufferSize), + compression_level(Z_DEFAULT_COMPRESSION), + compression_strategy(Z_DEFAULT_STRATEGY) {} + +GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream) { + Init(sub_stream, Options()); +} + +GzipOutputStream::GzipOutputStream(ZeroCopyOutputStream* sub_stream, + const Options& options) { + Init(sub_stream, options); +} + +void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, + const Options& options) { + sub_stream_ = sub_stream; + sub_data_ = NULL; + sub_data_size_ = 0; + + input_buffer_length_ = options.buffer_size; + input_buffer_ = operator new(input_buffer_length_); + GOOGLE_CHECK(input_buffer_ != NULL); + + zcontext_.zalloc = Z_NULL; + zcontext_.zfree = Z_NULL; + zcontext_.opaque = Z_NULL; + zcontext_.next_out = NULL; + zcontext_.avail_out = 0; + zcontext_.total_out = 0; + zcontext_.next_in = NULL; + zcontext_.avail_in = 0; + zcontext_.total_in = 0; + zcontext_.msg = NULL; + // default to GZIP format + int windowBitsFormat = 16; + if (options.format == ZLIB) { + windowBitsFormat = 0; + } + zerror_ = deflateInit2( + &zcontext_, + options.compression_level, + Z_DEFLATED, + /* windowBits */15 | windowBitsFormat, + /* memLevel (default) */8, + options.compression_strategy); +} + +GzipOutputStream::~GzipOutputStream() { + Close(); + if (input_buffer_ != NULL) { + operator delete(input_buffer_); + } +} + +// private +int GzipOutputStream::Deflate(int flush) { + int error = Z_OK; + do { + if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) { + bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_); + if (!ok) { + sub_data_ = NULL; + sub_data_size_ = 0; + return Z_BUF_ERROR; + } + GOOGLE_CHECK_GT(sub_data_size_, 0); + zcontext_.next_out = static_cast(sub_data_); + zcontext_.avail_out = sub_data_size_; + } + error = deflate(&zcontext_, flush); + } while (error == Z_OK && zcontext_.avail_out == 0); + if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { + // Notify lower layer of data. + sub_stream_->BackUp(zcontext_.avail_out); + // We don't own the buffer anymore. + sub_data_ = NULL; + sub_data_size_ = 0; + } + return error; +} + +// implements ZeroCopyOutputStream --------------------------------- +bool GzipOutputStream::Next(void** data, int* size) { + if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) { + return false; + } + if (zcontext_.avail_in != 0) { + zerror_ = Deflate(Z_NO_FLUSH); + if (zerror_ != Z_OK) { + return false; + } + } + if (zcontext_.avail_in == 0) { + // all input was consumed. reset the buffer. + zcontext_.next_in = static_cast(input_buffer_); + zcontext_.avail_in = input_buffer_length_; + *data = input_buffer_; + *size = input_buffer_length_; + } else { + // The loop in Deflate should consume all avail_in + GOOGLE_LOG(DFATAL) << "Deflate left bytes unconsumed"; + } + return true; +} +void GzipOutputStream::BackUp(int count) { + GOOGLE_CHECK_GE(zcontext_.avail_in, count); + zcontext_.avail_in -= count; +} +int64 GzipOutputStream::ByteCount() const { + return zcontext_.total_in + zcontext_.avail_in; +} + +bool GzipOutputStream::Flush() { + zerror_ = Deflate(Z_FULL_FLUSH); + // Return true if the flush succeeded or if it was a no-op. + return (zerror_ == Z_OK) || + (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && + zcontext_.avail_out != 0); +} + +bool GzipOutputStream::Close() { + if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) { + return false; + } + do { + zerror_ = Deflate(Z_FINISH); + } while (zerror_ == Z_OK); + zerror_ = deflateEnd(&zcontext_); + bool ok = zerror_ == Z_OK; + zerror_ = Z_STREAM_END; + return ok; +} + +} // namespace io +} // namespace protobuf +} // namespace google + +#endif // HAVE_ZLIB diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.h new file mode 100644 index 000000000..365e9ea5f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream.h @@ -0,0 +1,209 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: brianolson@google.com (Brian Olson) +// +// This file contains the definition for classes GzipInputStream and +// GzipOutputStream. +// +// GzipInputStream decompresses data from an underlying +// ZeroCopyInputStream and provides the decompressed data as a +// ZeroCopyInputStream. +// +// GzipOutputStream is an ZeroCopyOutputStream that compresses data to +// an underlying ZeroCopyOutputStream. + +#ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace io { + +// A ZeroCopyInputStream that reads compressed data through zlib +class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream { + public: + // Format key for constructor + enum Format { + // zlib will autodetect gzip header or deflate stream + AUTO = 0, + + // GZIP streams have some extra header data for file attributes. + GZIP = 1, + + // Simpler zlib stream format. + ZLIB = 2, + }; + + // buffer_size and format may be -1 for default of 64kB and GZIP format + explicit GzipInputStream( + ZeroCopyInputStream* sub_stream, + Format format = AUTO, + int buffer_size = -1); + virtual ~GzipInputStream(); + + // Return last error message or NULL if no error. + inline const char* ZlibErrorMessage() const { + return zcontext_.msg; + } + inline int ZlibErrorCode() const { + return zerror_; + } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + private: + Format format_; + + ZeroCopyInputStream* sub_stream_; + + z_stream zcontext_; + int zerror_; + + void* output_buffer_; + void* output_position_; + size_t output_buffer_length_; + + int Inflate(int flush); + void DoNextOutput(const void** data, int* size); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream); +}; + + +class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { + public: + // Format key for constructor + enum Format { + // GZIP streams have some extra header data for file attributes. + GZIP = 1, + + // Simpler zlib stream format. + ZLIB = 2, + }; + + struct LIBPROTOBUF_EXPORT Options { + // Defaults to GZIP. + Format format; + + // What size buffer to use internally. Defaults to 64kB. + int buffer_size; + + // A number between 0 and 9, where 0 is no compression and 9 is best + // compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h). + int compression_level; + + // Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED, + // Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in + // zlib.h for definitions of these constants. + int compression_strategy; + + Options(); // Initializes with default values. + }; + + // Create a GzipOutputStream with default options. + explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream); + + // Create a GzipOutputStream with the given options. + GzipOutputStream( + ZeroCopyOutputStream* sub_stream, + const Options& options); + + virtual ~GzipOutputStream(); + + // Return last error message or NULL if no error. + inline const char* ZlibErrorMessage() const { + return zcontext_.msg; + } + inline int ZlibErrorCode() const { + return zerror_; + } + + // Flushes data written so far to zipped data in the underlying stream. + // It is the caller's responsibility to flush the underlying stream if + // necessary. + // Compression may be less efficient stopping and starting around flushes. + // Returns true if no error. + // + // Please ensure that block size is > 6. Here is an excerpt from the zlib + // doc that explains why: + // + // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out + // is greater than six to avoid repeated flush markers due to + // avail_out == 0 on return. + bool Flush(); + + // Writes out all data and closes the gzip stream. + // It is the caller's responsibility to close the underlying stream if + // necessary. + // Returns true if no error. + bool Close(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + ZeroCopyOutputStream* sub_stream_; + // Result from calling Next() on sub_stream_ + void* sub_data_; + int sub_data_size_; + + z_stream zcontext_; + int zerror_; + void* input_buffer_; + size_t input_buffer_length_; + + // Shared constructor code. + void Init(ZeroCopyOutputStream* sub_stream, const Options& options); + + // Do some compression. + // Takes zlib flush mode. + // Returns zlib error code. + int Deflate(int flush); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream); +}; + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream_unittest.sh b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream_unittest.sh new file mode 100644 index 000000000..6e8a09437 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/gzip_stream_unittest.sh @@ -0,0 +1,44 @@ +#!/bin/sh -x +# +# Protocol Buffers - Google's data interchange format +# Copyright 2009 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# 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: brianolson@google.com (Brian Olson) +# +# Test compatibility between command line gzip/gunzip binaries and +# ZeroCopyStream versions. + +TESTFILE=Makefile + +(./zcgzip < ${TESTFILE} | gunzip | cmp - ${TESTFILE}) && \ +(gzip < ${TESTFILE} | ./zcgunzip | cmp - ${TESTFILE}) + +# Result of "(cmd) && (cmd)" implicitly becomes result of this script +# and thus the test. diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/package_info.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/package_info.h new file mode 100644 index 000000000..7a7a4e773 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/package_info.h @@ -0,0 +1,54 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 exists solely to document the google::protobuf::io namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +namespace google { + +namespace protobuf { + +// Auxiliary classes used for I/O. +// +// The Protocol Buffer library uses the classes in this package to deal with +// I/O and encoding/decoding raw bytes. Most users will not need to +// deal with this package. However, users who want to adapt the system to +// work with their own I/O abstractions -- e.g., to allow Protocol Buffers +// to be read from a different kind of input stream without the need for a +// temporary buffer -- should take a closer look. +namespace io {} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.cc new file mode 100644 index 000000000..d2bf3f549 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.cc @@ -0,0 +1,198 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +namespace google { +namespace protobuf { +namespace io { + +Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter) + : variable_delimiter_(variable_delimiter), + output_(output), + buffer_(NULL), + buffer_size_(0), + at_start_of_line_(true), + failed_(false) { +} + +Printer::~Printer() { + // Only BackUp() if we have called Next() at least once and never failed. + if (buffer_size_ > 0 && !failed_) { + output_->BackUp(buffer_size_); + } +} + +void Printer::Print(const map& variables, const char* text) { + int size = strlen(text); + 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'. + WriteRaw(text + pos, i - pos + 1); + pos = i + 1; + + // Setting this true will cause the next WriteRaw() to insert an indent + // first. + at_start_of_line_ = true; + + } else if (text[i] == variable_delimiter_) { + // Saw the start of a variable name. + + // Write what we have so far. + WriteRaw(text + pos, i - pos); + pos = i + 1; + + // Find closing delimiter. + const char* end = strchr(text + pos, variable_delimiter_); + if (end == NULL) { + GOOGLE_LOG(DFATAL) << " Unclosed variable name."; + end = text + pos; + } + int endpos = end - text; + + string varname(text + pos, endpos - pos); + if (varname.empty()) { + // Two delimiters in a row reduce to a literal delimiter character. + WriteRaw(&variable_delimiter_, 1); + } else { + // Replace with the variable's value. + map::const_iterator iter = variables.find(varname); + if (iter == variables.end()) { + GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname; + } else { + WriteRaw(iter->second.data(), iter->second.size()); + } + } + + // Advance past this variable. + i = endpos; + pos = endpos + 1; + } + } + + // Write the rest. + WriteRaw(text + pos, size - pos); +} + +void Printer::Print(const char* text) { + static map empty; + Print(empty, text); +} + +void Printer::Print(const char* text, + const char* variable, const string& value) { + map vars; + vars[variable] = value; + Print(vars, text); +} + +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + Print(vars, text); +} + +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + Print(vars, text); +} + +void Printer::Indent() { + indent_ += " "; +} + +void Printer::Outdent() { + if (indent_.empty()) { + GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; + return; + } + + indent_.resize(indent_.size() - 2); +} + +void Printer::PrintRaw(const string& data) { + WriteRaw(data.data(), data.size()); +} + +void Printer::PrintRaw(const char* data) { + if (failed_) return; + WriteRaw(data, strlen(data)); +} + +void Printer::WriteRaw(const char* data, int size) { + if (failed_) return; + if (size == 0) return; + + if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) { + // Insert an indent. + at_start_of_line_ = false; + WriteRaw(indent_.data(), indent_.size()); + if (failed_) return; + } + + while (size > buffer_size_) { + // Data exceeds space in the buffer. Copy what we can and request a + // new buffer. + memcpy(buffer_, data, buffer_size_); + data += buffer_size_; + size -= buffer_size_; + void* void_buffer; + 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; +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.h new file mode 100644 index 000000000..5be48543a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer.h @@ -0,0 +1,136 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Utility class for writing text to a ZeroCopyOutputStream. + +#ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__ +#define GOOGLE_PROTOBUF_IO_PRINTER_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { + +class ZeroCopyOutputStream; // zero_copy_stream.h + +// This simple utility class assists in code generation. It basically +// allows the caller to define a set of variables and then output some +// text with variable substitutions. Example usage: +// +// Printer printer(output, '$'); +// map vars; +// vars["name"] = "Bob"; +// printer.Print(vars, "My name is $name$."); +// +// The above writes "My name is Bob." to the output stream. +// +// Printer aggressively enforces correct usage, crashing (with assert failures) +// in the case of undefined variables in debug builds. This helps greatly in +// debugging code which uses it. +class LIBPROTOBUF_EXPORT Printer { + public: + // Create a printer that writes text to the given output stream. Use the + // given character as the delimiter for variables. + Printer(ZeroCopyOutputStream* output, char variable_delimiter); + ~Printer(); + + // Print some text after applying variable substitutions. If a particular + // variable in the text is not defined, this will crash. Variables to be + // substituted are identified by their names surrounded by delimiter + // characters (as given to the constructor). The variable bindings are + // defined by the given map. + void Print(const map& variables, const char* text); + + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable, const string& value); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3); + // TODO(kenton): Overloaded versions with more variables? Three seems + // to be enough. + + // 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(); + + // Reduces the current indent level by two spaces, or crashes if the indent + // level is zero. + void Outdent(); + + // Write a string to the output buffer. + // This method does not look for newlines to add indentation. + void PrintRaw(const string& data); + + // Write a zero-delimited string to output buffer. + // This method does not look for newlines to add indentation. + void PrintRaw(const char* data); + + // Write some bytes to the output buffer. + // This method does not look for newlines to add indentation. + void WriteRaw(const char* data, int size); + + // True if any write to the underlying stream failed. (We don't just + // crash in this case because this is an I/O failure, not a programming + // error.) + bool failed() const { return failed_; } + + private: + const char variable_delimiter_; + + ZeroCopyOutputStream* const output_; + char* buffer_; + int buffer_size_; + + string indent_; + bool at_start_of_line_; + bool failed_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer); +}; + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_PRINTER_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer_unittest.cc new file mode 100644 index 000000000..c9b303596 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/printer_unittest.cc @@ -0,0 +1,285 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace io { +namespace { + +// Each test repeats over several block sizes in order to test both cases +// where particular writes cross a buffer boundary and cases where they do +// not. + +TEST(Printer, EmptyPrinter) { + char buffer[8192]; + const int block_size = 100; + ArrayOutputStream output(buffer, GOOGLE_ARRAYSIZE(buffer), block_size); + Printer printer(&output, '\0'); + EXPECT_TRUE(!printer.failed()); +} + +TEST(Printer, BasicPrinting) { + char buffer[8192]; + + for (int block_size = 1; block_size < 512; block_size *= 2) { + ArrayOutputStream output(buffer, sizeof(buffer), block_size); + + { + Printer printer(&output, '\0'); + + printer.Print("Hello World!"); + printer.Print(" This is the same line.\n"); + printer.Print("But this is a new one.\nAnd this is another one."); + + EXPECT_FALSE(printer.failed()); + } + + buffer[output.ByteCount()] = '\0'; + + EXPECT_STREQ("Hello World! This is the same line.\n" + "But this is a new one.\n" + "And this is another one.", + buffer); + } +} + +TEST(Printer, WriteRaw) { + char buffer[8192]; + + for (int block_size = 1; block_size < 512; block_size *= 2) { + ArrayOutputStream output(buffer, sizeof(buffer), block_size); + + { + string string_obj = "From an object\n"; + Printer printer(&output, '$'); + printer.WriteRaw("Hello World!", 12); + printer.PrintRaw(" This is the same line.\n"); + printer.PrintRaw("But this is a new one.\nAnd this is another one."); + printer.WriteRaw("\n", 1); + printer.PrintRaw(string_obj); + EXPECT_FALSE(printer.failed()); + } + + buffer[output.ByteCount()] = '\0'; + + EXPECT_STREQ("Hello World! This is the same line.\n" + "But this is a new one.\n" + "And this is another one." + "\n" + "From an object\n", + buffer); + } +} + +TEST(Printer, VariableSubstitution) { + char buffer[8192]; + + for (int block_size = 1; block_size < 512; block_size *= 2) { + ArrayOutputStream output(buffer, sizeof(buffer), block_size); + + { + Printer printer(&output, '$'); + map vars; + + vars["foo"] = "World"; + vars["bar"] = "$foo$"; + vars["abcdefg"] = "1234"; + + printer.Print(vars, "Hello $foo$!\nbar = $bar$\n"); + printer.PrintRaw("RawBit\n"); + printer.Print(vars, "$abcdefg$\nA literal dollar sign: $$"); + + vars["foo"] = "blah"; + printer.Print(vars, "\nNow foo = $foo$."); + + EXPECT_FALSE(printer.failed()); + } + + buffer[output.ByteCount()] = '\0'; + + EXPECT_STREQ("Hello World!\n" + "bar = $foo$\n" + "RawBit\n" + "1234\n" + "A literal dollar sign: $\n" + "Now foo = blah.", + buffer); + } +} + +TEST(Printer, InlineVariableSubstitution) { + char buffer[8192]; + + ArrayOutputStream output(buffer, sizeof(buffer)); + + { + Printer printer(&output, '$'); + printer.Print("Hello $foo$!\n", "foo", "World"); + printer.PrintRaw("RawBit\n"); + printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two"); + EXPECT_FALSE(printer.failed()); + } + + buffer[output.ByteCount()] = '\0'; + + EXPECT_STREQ("Hello World!\n" + "RawBit\n" + "one two\n", + buffer); +} + +TEST(Printer, Indenting) { + char buffer[8192]; + + for (int block_size = 1; block_size < 512; block_size *= 2) { + ArrayOutputStream output(buffer, sizeof(buffer), block_size); + + { + Printer printer(&output, '$'); + map vars; + + vars["newline"] = "\n"; + + printer.Print("This is not indented.\n"); + printer.Indent(); + printer.Print("This is indented\nAnd so is this\n"); + printer.Outdent(); + printer.Print("But this is not."); + printer.Indent(); + printer.Print(" And this is still the same line.\n" + "But this is indented.\n"); + printer.PrintRaw("RawBit has indent at start\n"); + printer.PrintRaw("but not after a raw newline\n"); + printer.Print(vars, "Note that a newline in a variable will break " + "indenting, as we see$newline$here.\n"); + printer.Indent(); + printer.Print("And this"); + printer.Outdent(); + printer.Outdent(); + printer.Print(" is double-indented\nBack to normal."); + + EXPECT_FALSE(printer.failed()); + } + + buffer[output.ByteCount()] = '\0'; + + EXPECT_STREQ( + "This is not indented.\n" + " This is indented\n" + " And so is this\n" + "But this is not. And this is still the same line.\n" + " But this is indented.\n" + " RawBit has indent at start\n" + "but not after a raw newline\n" + "Note that a newline in a variable will break indenting, as we see\n" + "here.\n" + " And this is double-indented\n" + "Back to normal.", + buffer); + } +} + +// Death tests do not work on Windows as of yet. +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(Printer, Death) { + char buffer[8192]; + + ArrayOutputStream output(buffer, sizeof(buffer)); + Printer printer(&output, '$'); + + EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "Undefined variable"); + EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name"); + EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent"); +} +#endif // PROTOBUF__HAS_DEATH_TEST + +TEST(Printer, WriteFailurePartial) { + char buffer[17]; + + ArrayOutputStream output(buffer, sizeof(buffer)); + Printer printer(&output, '$'); + + // Print 16 bytes to almost fill the buffer (should not fail). + printer.Print("0123456789abcdef"); + EXPECT_FALSE(printer.failed()); + + // Try to print 2 chars. Only one fits. + printer.Print("<>"); + EXPECT_TRUE(printer.failed()); + + // Anything else should fail too. + printer.Print(" "); + EXPECT_TRUE(printer.failed()); + printer.Print("blah"); + EXPECT_TRUE(printer.failed()); + + // Buffer should contain the first 17 bytes written. + EXPECT_EQ("0123456789abcdef<", string(buffer, sizeof(buffer))); +} + +TEST(Printer, WriteFailureExact) { + char buffer[16]; + + ArrayOutputStream output(buffer, sizeof(buffer)); + Printer printer(&output, '$'); + + // Print 16 bytes to fill the buffer exactly (should not fail). + printer.Print("0123456789abcdef"); + EXPECT_FALSE(printer.failed()); + + // Try to print one more byte (should fail). + printer.Print(" "); + EXPECT_TRUE(printer.failed()); + + // Should not crash + printer.Print("blah"); + EXPECT_TRUE(printer.failed()); + + // Buffer should contain the first 16 bytes written. + EXPECT_EQ("0123456789abcdef", string(buffer, sizeof(buffer))); +} + +} // namespace +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.cc new file mode 100644 index 000000000..a022b71db --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.cc @@ -0,0 +1,1091 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Here we have a hand-written lexer. At first you might ask yourself, +// "Hand-written text processing? Is Kenton crazy?!" Well, first of all, +// yes I am crazy, but that's beside the point. There are actually reasons +// why I ended up writing this this way. +// +// The traditional approach to lexing is to use lex to generate a lexer for +// you. Unfortunately, lex's output is ridiculously ugly and difficult to +// integrate cleanly with C++ code, especially abstract code or code meant +// as a library. Better parser-generators exist but would add dependencies +// which most users won't already have, which we'd like to avoid. (GNU flex +// has a C++ output option, but it's still ridiculously ugly, non-abstract, +// and not library-friendly.) +// +// The next approach that any good software engineer should look at is to +// use regular expressions. And, indeed, I did. I have code which +// implements this same class using regular expressions. It's about 200 +// lines shorter. However: +// - Rather than error messages telling you "This string has an invalid +// escape sequence at line 5, column 45", you get error messages like +// "Parse error on line 5". Giving more precise errors requires adding +// a lot of code that ends up basically as complex as the hand-coded +// version anyway. +// - The regular expression to match a string literal looks like this: +// kString = new RE("(\"([^\"\\\\]|" // non-escaped +// "\\\\[abfnrtv?\"'\\\\0-7]|" // normal escape +// "\\\\x[0-9a-fA-F])*\"|" // hex escape +// "\'([^\'\\\\]|" // Also support single-quotes. +// "\\\\[abfnrtv?\"'\\\\0-7]|" +// "\\\\x[0-9a-fA-F])*\')"); +// Verifying the correctness of this line noise is actually harder than +// verifying the correctness of ConsumeString(), defined below. I'm not +// even confident that the above is correct, after staring at it for some +// time. +// - PCRE is fast, but there's still more overhead involved than the code +// below. +// - Sadly, regular expressions are not part of the C standard library, so +// using them would require depending on some other library. For the +// open source release, this could be really annoying. Nobody likes +// downloading one piece of software just to find that they need to +// download something else to make it work, and in all likelihood +// people downloading Protocol Buffers will already be doing so just +// to make something else work. We could include a copy of PCRE with +// our code, but that obligates us to keep it up-to-date and just seems +// like a big waste just to save 200 lines of code. +// +// On a similar but unrelated note, I'm even scared to use ctype.h. +// Apparently functions like isalpha() are locale-dependent. So, if we used +// that, then if this code is being called from some program that doesn't +// have its locale set to "C", it would behave strangely. We can't just set +// the locale to "C" ourselves since we might break the calling program that +// way, particularly if it is multi-threaded. WTF? Someone please let me +// (Kenton) know if I'm missing something here... +// +// I'd love to hear about other alternatives, though, as this code isn't +// exactly pretty. + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { +namespace { + +// As mentioned above, I don't trust ctype.h due to the presence of "locales". +// So, I have written replacement functions here. Someone please smack me if +// this is a bad idea or if there is some way around this. +// +// These "character classes" are designed to be used in template methods. +// For instance, Tokenizer::ConsumeZeroOrMore() will eat +// whitespace. + +// Note: No class is allowed to contain '\0', since this is used to mark end- +// of-input and is handled specially. + +#define CHARACTER_CLASS(NAME, EXPRESSION) \ + class NAME { \ + public: \ + static inline bool InClass(char c) { \ + return EXPRESSION; \ + } \ + } + +CHARACTER_CLASS(Whitespace, c == ' ' || c == '\n' || c == '\t' || + c == '\r' || c == '\v' || c == '\f'); +CHARACTER_CLASS(WhitespaceNoNewline, c == ' ' || c == '\t' || + c == '\r' || c == '\v' || c == '\f'); + +CHARACTER_CLASS(Unprintable, c < ' ' && c > '\0'); + +CHARACTER_CLASS(Digit, '0' <= c && c <= '9'); +CHARACTER_CLASS(OctalDigit, '0' <= c && c <= '7'); +CHARACTER_CLASS(HexDigit, ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F')); + +CHARACTER_CLASS(Letter, ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + (c == '_')); + +CHARACTER_CLASS(Alphanumeric, ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9') || + (c == '_')); + +CHARACTER_CLASS(Escape, c == 'a' || c == 'b' || c == 'f' || c == 'n' || + c == 'r' || c == 't' || c == 'v' || c == '\\' || + c == '?' || c == '\'' || c == '\"'); + +#undef CHARACTER_CLASS + +// Given a char, interpret it as a numeric digit and return its value. +// This supports any number base up to 36. +inline int DigitValue(char digit) { + if ('0' <= digit && digit <= '9') return digit - '0'; + if ('a' <= digit && digit <= 'z') return digit - 'a' + 10; + if ('A' <= digit && digit <= 'Z') return digit - 'A' + 10; + return -1; +} + +// Inline because it's only used in one place. +inline char TranslateEscape(char c) { + switch (c) { + case 'a': return '\a'; + case 'b': return '\b'; + case 'f': return '\f'; + case 'n': return '\n'; + case 'r': return '\r'; + case 't': return '\t'; + case 'v': return '\v'; + case '\\': return '\\'; + case '?': return '\?'; // Trigraphs = :( + case '\'': return '\''; + case '"': return '\"'; + + // We expect escape sequences to have been validated separately. + default: return '?'; + } +} + +} // anonymous namespace + +ErrorCollector::~ErrorCollector() {} + +// =================================================================== + +Tokenizer::Tokenizer(ZeroCopyInputStream* input, + ErrorCollector* error_collector) + : input_(input), + error_collector_(error_collector), + buffer_(NULL), + buffer_size_(0), + buffer_pos_(0), + read_error_(false), + line_(0), + column_(0), + record_target_(NULL), + record_start_(-1), + allow_f_after_float_(false), + comment_style_(CPP_COMMENT_STYLE) { + + current_.line = 0; + current_.column = 0; + current_.end_column = 0; + current_.type = TYPE_START; + + Refresh(); +} + +Tokenizer::~Tokenizer() { + // If we had any buffer left unread, return it to the underlying stream + // so that someone else can read it. + if (buffer_size_ > buffer_pos_) { + input_->BackUp(buffer_size_ - buffer_pos_); + } +} + +// ------------------------------------------------------------------- +// Internal helpers. + +void Tokenizer::NextChar() { + // Update our line and column counters based on the character being + // consumed. + if (current_char_ == '\n') { + ++line_; + column_ = 0; + } else if (current_char_ == '\t') { + column_ += kTabWidth - column_ % kTabWidth; + } else { + ++column_; + } + + // Advance to the next character. + ++buffer_pos_; + if (buffer_pos_ < buffer_size_) { + current_char_ = buffer_[buffer_pos_]; + } else { + Refresh(); + } +} + +void Tokenizer::Refresh() { + if (read_error_) { + current_char_ = '\0'; + return; + } + + // If we're in a token, append the rest of the buffer to it. + if (record_target_ != NULL && record_start_ < buffer_size_) { + record_target_->append(buffer_ + record_start_, buffer_size_ - record_start_); + record_start_ = 0; + } + + const void* data = NULL; + buffer_ = NULL; + buffer_pos_ = 0; + do { + if (!input_->Next(&data, &buffer_size_)) { + // end of stream (or read error) + buffer_size_ = 0; + read_error_ = true; + current_char_ = '\0'; + return; + } + } while (buffer_size_ == 0); + + buffer_ = static_cast(data); + + current_char_ = buffer_[0]; +} + +inline void Tokenizer::RecordTo(string* target) { + record_target_ = target; + record_start_ = buffer_pos_; +} + +inline void Tokenizer::StopRecording() { + // Note: The if() is necessary because some STL implementations crash when + // you call string::append(NULL, 0), presumably because they are trying to + // be helpful by detecting the NULL pointer, even though there's nothing + // wrong with reading zero bytes from NULL. + if (buffer_pos_ != record_start_) { + record_target_->append(buffer_ + record_start_, buffer_pos_ - record_start_); + } + record_target_ = NULL; + record_start_ = -1; +} + +inline void Tokenizer::StartToken() { + current_.type = TYPE_START; // Just for the sake of initializing it. + current_.text.clear(); + current_.line = line_; + current_.column = column_; + RecordTo(¤t_.text); +} + +inline void Tokenizer::EndToken() { + StopRecording(); + current_.end_column = column_; +} + +// ------------------------------------------------------------------- +// Helper methods that consume characters. + +template +inline bool Tokenizer::LookingAt() { + return CharacterClass::InClass(current_char_); +} + +template +inline bool Tokenizer::TryConsumeOne() { + if (CharacterClass::InClass(current_char_)) { + NextChar(); + return true; + } else { + return false; + } +} + +inline bool Tokenizer::TryConsume(char c) { + if (current_char_ == c) { + NextChar(); + return true; + } else { + return false; + } +} + +template +inline void Tokenizer::ConsumeZeroOrMore() { + while (CharacterClass::InClass(current_char_)) { + NextChar(); + } +} + +template +inline void Tokenizer::ConsumeOneOrMore(const char* error) { + if (!CharacterClass::InClass(current_char_)) { + AddError(error); + } else { + do { + NextChar(); + } while (CharacterClass::InClass(current_char_)); + } +} + +// ------------------------------------------------------------------- +// Methods that read whole patterns matching certain kinds of tokens +// or comments. + +void Tokenizer::ConsumeString(char delimiter) { + while (true) { + switch (current_char_) { + case '\0': + case '\n': { + AddError("String literals cannot cross line boundaries."); + return; + } + + case '\\': { + // An escape sequence. + NextChar(); + if (TryConsumeOne()) { + // Valid escape sequence. + } else if (TryConsumeOne()) { + // Possibly followed by two more octal digits, but these will + // just be consumed by the main loop anyway so we don't need + // to do so explicitly here. + } else if (TryConsume('x') || TryConsume('X')) { + if (!TryConsumeOne()) { + AddError("Expected hex digits for escape sequence."); + } + // Possibly followed by another hex digit, but again we don't care. + } else if (TryConsume('u')) { + if (!TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne()) { + AddError("Expected four hex digits for \\u escape sequence."); + } + } else if (TryConsume('U')) { + // We expect 8 hex digits; but only the range up to 0x10ffff is + // legal. + if (!TryConsume('0') || + !TryConsume('0') || + !(TryConsume('0') || TryConsume('1')) || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne() || + !TryConsumeOne()) { + AddError("Expected eight hex digits up to 10ffff for \\U escape " + "sequence"); + } + } else { + AddError("Invalid escape sequence in string literal."); + } + break; + } + + default: { + if (current_char_ == delimiter) { + NextChar(); + return; + } + NextChar(); + break; + } + } + } +} + +Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, + bool started_with_dot) { + bool is_float = false; + + if (started_with_zero && (TryConsume('x') || TryConsume('X'))) { + // A hex number (started with "0x"). + ConsumeOneOrMore("\"0x\" must be followed by hex digits."); + + } else if (started_with_zero && LookingAt()) { + // An octal number (had a leading zero). + ConsumeZeroOrMore(); + if (LookingAt()) { + AddError("Numbers starting with leading zero must be in octal."); + ConsumeZeroOrMore(); + } + + } else { + // A decimal number. + if (started_with_dot) { + is_float = true; + ConsumeZeroOrMore(); + } else { + ConsumeZeroOrMore(); + + if (TryConsume('.')) { + is_float = true; + ConsumeZeroOrMore(); + } + } + + if (TryConsume('e') || TryConsume('E')) { + is_float = true; + TryConsume('-') || TryConsume('+'); + ConsumeOneOrMore("\"e\" must be followed by exponent."); + } + + if (allow_f_after_float_ && (TryConsume('f') || TryConsume('F'))) { + is_float = true; + } + } + + if (LookingAt()) { + AddError("Need space between number and identifier."); + } else if (current_char_ == '.') { + if (is_float) { + AddError( + "Already saw decimal point or exponent; can't have another one."); + } else { + AddError("Hex and octal numbers must be integers."); + } + } + + return is_float ? TYPE_FLOAT : TYPE_INTEGER; +} + +void Tokenizer::ConsumeLineComment(string* content) { + if (content != NULL) RecordTo(content); + + while (current_char_ != '\0' && current_char_ != '\n') { + NextChar(); + } + TryConsume('\n'); + + if (content != NULL) StopRecording(); +} + +void Tokenizer::ConsumeBlockComment(string* content) { + int start_line = line_; + int start_column = column_ - 2; + + if (content != NULL) RecordTo(content); + + while (true) { + while (current_char_ != '\0' && + current_char_ != '*' && + current_char_ != '/' && + current_char_ != '\n') { + NextChar(); + } + + if (TryConsume('\n')) { + if (content != NULL) StopRecording(); + + // Consume leading whitespace and asterisk; + ConsumeZeroOrMore(); + if (TryConsume('*')) { + if (TryConsume('/')) { + // End of comment. + break; + } + } + + if (content != NULL) RecordTo(content); + } else if (TryConsume('*') && TryConsume('/')) { + // End of comment. + if (content != NULL) { + StopRecording(); + // Strip trailing "*/". + content->erase(content->size() - 2); + } + break; + } else if (TryConsume('/') && current_char_ == '*') { + // Note: We didn't consume the '*' because if there is a '/' after it + // we want to interpret that as the end of the comment. + AddError( + "\"/*\" inside block comment. Block comments cannot be nested."); + } else if (current_char_ == '\0') { + AddError("End-of-file inside block comment."); + error_collector_->AddError( + start_line, start_column, " Comment started here."); + if (content != NULL) StopRecording(); + break; + } + } +} + +Tokenizer::NextCommentStatus Tokenizer::TryConsumeCommentStart() { + if (comment_style_ == CPP_COMMENT_STYLE && TryConsume('/')) { + if (TryConsume('/')) { + return LINE_COMMENT; + } else if (TryConsume('*')) { + return BLOCK_COMMENT; + } else { + // Oops, it was just a slash. Return it. + current_.type = TYPE_SYMBOL; + current_.text = "/"; + current_.line = line_; + current_.column = column_ - 1; + current_.end_column = column_; + return SLASH_NOT_COMMENT; + } + } else if (comment_style_ == SH_COMMENT_STYLE && TryConsume('#')) { + return LINE_COMMENT; + } else { + return NO_COMMENT; + } +} + +// ------------------------------------------------------------------- + +bool Tokenizer::Next() { + previous_ = current_; + + while (!read_error_) { + ConsumeZeroOrMore(); + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(NULL); + continue; + case BLOCK_COMMENT: + ConsumeBlockComment(NULL); + continue; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + break; + } + + // Check for EOF before continuing. + if (read_error_) break; + + if (LookingAt() || current_char_ == '\0') { + AddError("Invalid control characters encountered in text."); + NextChar(); + // Skip more unprintable characters, too. But, remember that '\0' is + // also what current_char_ is set to after EOF / read error. We have + // to be careful not to go into an infinite loop of trying to consume + // it, so make sure to check read_error_ explicitly before consuming + // '\0'. + while (TryConsumeOne() || + (!read_error_ && TryConsume('\0'))) { + // Ignore. + } + + } else { + // Reading some sort of token. + StartToken(); + + if (TryConsumeOne()) { + ConsumeZeroOrMore(); + current_.type = TYPE_IDENTIFIER; + } else if (TryConsume('0')) { + current_.type = ConsumeNumber(true, false); + } else if (TryConsume('.')) { + // This could be the beginning of a floating-point number, or it could + // just be a '.' symbol. + + if (TryConsumeOne()) { + // It's a floating-point number. + if (previous_.type == TYPE_IDENTIFIER && + current_.line == previous_.line && + current_.column == previous_.end_column) { + // We don't accept syntax like "blah.123". + error_collector_->AddError(line_, column_ - 2, + "Need space between identifier and decimal point."); + } + current_.type = ConsumeNumber(false, true); + } else { + current_.type = TYPE_SYMBOL; + } + } else if (TryConsumeOne()) { + current_.type = ConsumeNumber(false, false); + } else if (TryConsume('\"')) { + ConsumeString('\"'); + current_.type = TYPE_STRING; + } else if (TryConsume('\'')) { + ConsumeString('\''); + current_.type = TYPE_STRING; + } else { + NextChar(); + current_.type = TYPE_SYMBOL; + } + + EndToken(); + return true; + } + } + + // EOF + current_.type = TYPE_END; + current_.text.clear(); + current_.line = line_; + current_.column = column_; + current_.end_column = column_; + return false; +} + +namespace { + +// Helper class for collecting comments and putting them in the right places. +// +// This basically just buffers the most recent comment until it can be decided +// exactly where that comment should be placed. When Flush() is called, the +// current comment goes into either prev_trailing_comments or detached_comments. +// When the CommentCollector is destroyed, the last buffered comment goes into +// next_leading_comments. +class CommentCollector { + public: + CommentCollector(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments) + : prev_trailing_comments_(prev_trailing_comments), + detached_comments_(detached_comments), + next_leading_comments_(next_leading_comments), + has_comment_(false), + is_line_comment_(false), + can_attach_to_prev_(true) { + if (prev_trailing_comments != NULL) prev_trailing_comments->clear(); + if (detached_comments != NULL) detached_comments->clear(); + if (next_leading_comments != NULL) next_leading_comments->clear(); + } + + ~CommentCollector() { + // Whatever is in the buffer is a leading comment. + if (next_leading_comments_ != NULL && has_comment_) { + comment_buffer_.swap(*next_leading_comments_); + } + } + + // About to read a line comment. Get the comment buffer pointer in order to + // read into it. + string* GetBufferForLineComment() { + // We want to combine with previous line comments, but not block comments. + if (has_comment_ && !is_line_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = true; + return &comment_buffer_; + } + + // About to read a block comment. Get the comment buffer pointer in order to + // read into it. + string* GetBufferForBlockComment() { + if (has_comment_) { + Flush(); + } + has_comment_ = true; + is_line_comment_ = false; + return &comment_buffer_; + } + + void ClearBuffer() { + comment_buffer_.clear(); + has_comment_ = false; + } + + // Called once we know that the comment buffer is complete and is *not* + // connected to the next token. + void Flush() { + if (has_comment_) { + if (can_attach_to_prev_) { + if (prev_trailing_comments_ != NULL) { + prev_trailing_comments_->append(comment_buffer_); + } + can_attach_to_prev_ = false; + } else { + if (detached_comments_ != NULL) { + detached_comments_->push_back(comment_buffer_); + } + } + ClearBuffer(); + } + } + + void DetachFromPrev() { + can_attach_to_prev_ = false; + } + + private: + string* prev_trailing_comments_; + vector* detached_comments_; + string* next_leading_comments_; + + string comment_buffer_; + + // True if any comments were read into comment_buffer_. This can be true even + // if comment_buffer_ is empty, namely if the comment was "/**/". + bool has_comment_; + + // Is the comment in the comment buffer a line comment? + bool is_line_comment_; + + // Is it still possible that we could be reading a comment attached to the + // previous token? + bool can_attach_to_prev_; +}; + +} // namespace + +bool Tokenizer::NextWithComments(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments) { + CommentCollector collector(prev_trailing_comments, detached_comments, + next_leading_comments); + + if (current_.type == TYPE_START) { + collector.DetachFromPrev(); + } else { + // A comment appearing on the same line must be attached to the previous + // declaration. + ConsumeZeroOrMore(); + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + ConsumeZeroOrMore(); + if (!TryConsume('\n')) { + // Oops, the next token is on the same line. If we recorded a comment + // we really have no idea which token it should be attached to. + collector.ClearBuffer(); + return Next(); + } + + // Don't allow comments on subsequent lines to be attached to a trailing + // comment. + collector.Flush(); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (!TryConsume('\n')) { + // The next token is on the same line. There are no comments. + return Next(); + } + break; + } + } + + // OK, we are now on the line *after* the previous token. + while (true) { + ConsumeZeroOrMore(); + + switch (TryConsumeCommentStart()) { + case LINE_COMMENT: + ConsumeLineComment(collector.GetBufferForLineComment()); + break; + case BLOCK_COMMENT: + ConsumeBlockComment(collector.GetBufferForBlockComment()); + + // Consume the rest of the line so that we don't interpret it as a + // blank line the next time around the loop. + ConsumeZeroOrMore(); + TryConsume('\n'); + break; + case SLASH_NOT_COMMENT: + return true; + case NO_COMMENT: + if (TryConsume('\n')) { + // Completely blank line. + collector.Flush(); + collector.DetachFromPrev(); + } else { + bool result = Next(); + if (!result || + current_.text == "}" || + current_.text == "]" || + current_.text == ")") { + // It looks like we're at the end of a scope. In this case it + // makes no sense to attach a comment to the following token. + collector.Flush(); + } + return result; + } + break; + } + } +} + +// ------------------------------------------------------------------- +// Token-parsing helpers. Remember that these don't need to report +// errors since any errors should already have been reported while +// tokenizing. Also, these can assume that whatever text they +// are given is text that the tokenizer actually parsed as a token +// of the given type. + +bool Tokenizer::ParseInteger(const string& text, uint64 max_value, + uint64* output) { + // Sadly, we can't just use strtoul() since it is only 32-bit and strtoull() + // is non-standard. I hate the C standard library. :( + +// return strtoull(text.c_str(), NULL, 0); + + const char* ptr = text.c_str(); + int base = 10; + if (ptr[0] == '0') { + if (ptr[1] == 'x' || ptr[1] == 'X') { + // This is hex. + base = 16; + ptr += 2; + } else { + // This is octal. + base = 8; + } + } + + uint64 result = 0; + for (; *ptr != '\0'; ptr++) { + int digit = DigitValue(*ptr); + GOOGLE_LOG_IF(DFATAL, digit < 0 || digit >= base) + << " Tokenizer::ParseInteger() passed text that could not have been" + " tokenized as an integer: " << CEscape(text); + if (digit > max_value || result > (max_value - digit) / base) { + // Overflow. + return false; + } + result = result * base + digit; + } + + *output = result; + return true; +} + +double Tokenizer::ParseFloat(const string& text) { + const char* start = text.c_str(); + char* end; + double result = NoLocaleStrtod(start, &end); + + // "1e" is not a valid float, but if the tokenizer reads it, it will + // report an error but still return it as a valid token. We need to + // accept anything the tokenizer could possibly return, error or not. + if (*end == 'e' || *end == 'E') { + ++end; + if (*end == '-' || *end == '+') ++end; + } + + // If the Tokenizer had allow_f_after_float_ enabled, the float may be + // suffixed with the letter 'f'. + if (*end == 'f' || *end == 'F') { + ++end; + } + + GOOGLE_LOG_IF(DFATAL, end - start != text.size() || *start == '-') + << " Tokenizer::ParseFloat() passed text that could not have been" + " tokenized as a float: " << CEscape(text); + return result; +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +static void AppendUTF8(uint32 code_point, string* 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 if (code_point <= 0x1fffff) { + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + StringAppendF(output, "\\U%08x", code_point); + return; + } + tmp = ghtonl(tmp); + output->append(reinterpret_cast(&tmp) + sizeof(tmp) - len, len); +} + +// Try to read hex digits from ptr, and stuff the numeric result into +// *result. Returns true if that many digits were successfully consumed. +static bool ReadHexDigits(const char* ptr, int len, uint32* result) { + *result = 0; + if (len == 0) return false; + for (const char* end = ptr + len; ptr < end; ++ptr) { + if (*ptr == '\0') return false; + *result = (*result << 4) + DigitValue(*ptr); + } + return true; +} + +// Handling UTF-16 surrogate pairs. UTF-16 encodes code points in the range +// 0x10000...0x10ffff as a pair of numbers, a head surrogate followed by a trail +// surrogate. These numbers are in a reserved range of Unicode code points, so +// if we encounter such a pair we know how to parse it and convert it into a +// single code point. +static const uint32 kMinHeadSurrogate = 0xd800; +static const uint32 kMaxHeadSurrogate = 0xdc00; +static const uint32 kMinTrailSurrogate = 0xdc00; +static const uint32 kMaxTrailSurrogate = 0xe000; + +static inline bool IsHeadSurrogate(uint32 code_point) { + return (code_point >= kMinHeadSurrogate) && (code_point < kMaxHeadSurrogate); +} + +static inline bool IsTrailSurrogate(uint32 code_point) { + return (code_point >= kMinTrailSurrogate) && + (code_point < kMaxTrailSurrogate); +} + +// Combine a head and trail surrogate into a single Unicode code point. +static uint32 AssembleUTF16(uint32 head_surrogate, uint32 trail_surrogate) { + GOOGLE_DCHECK(IsHeadSurrogate(head_surrogate)); + GOOGLE_DCHECK(IsTrailSurrogate(trail_surrogate)); + return 0x10000 + (((head_surrogate - kMinHeadSurrogate) << 10) | + (trail_surrogate - kMinTrailSurrogate)); +} + +// Convert the escape sequence parameter to a number of expected hex digits. +static inline int UnicodeLength(char key) { + if (key == 'u') return 4; + if (key == 'U') return 8; + return 0; +} + +// Given a pointer to the 'u' or 'U' starting a Unicode escape sequence, attempt +// to parse that sequence. On success, returns a pointer to the first char +// beyond that sequence, and fills in *code_point. On failure, returns ptr +// itself. +static const char* FetchUnicodePoint(const char* ptr, uint32* code_point) { + const char* p = ptr; + // Fetch the code point. + const int len = UnicodeLength(*p++); + if (!ReadHexDigits(p, len, code_point)) + return ptr; + p += len; + + // Check if the code point we read is a "head surrogate." If so, then we + // expect it to be immediately followed by another code point which is a valid + // "trail surrogate," and together they form a UTF-16 pair which decodes into + // a single Unicode point. Trail surrogates may only use \u, not \U. + if (IsHeadSurrogate(*code_point) && *p == '\\' && *(p + 1) == 'u') { + uint32 trail_surrogate; + if (ReadHexDigits(p + 2, 4, &trail_surrogate) && + IsTrailSurrogate(trail_surrogate)) { + *code_point = AssembleUTF16(*code_point, trail_surrogate); + p += 6; + } + // If this failed, then we just emit the head surrogate as a code point. + // It's bogus, but so is the string. + } + + return p; +} + +// The text string must begin and end with single or double quote +// characters. +void Tokenizer::ParseStringAppend(const string& text, string* output) { + // Reminder: text[0] is always a quote character. (If text is + // empty, it's invalid, so we'll just return). + const size_t text_size = text.size(); + if (text_size == 0) { + GOOGLE_LOG(DFATAL) + << " Tokenizer::ParseStringAppend() passed text that could not" + " have been tokenized as a string: " << CEscape(text); + return; + } + + // Reserve room for new string. The branch is necessary because if + // there is already space available the reserve() call might + // downsize the output. + const size_t new_len = text_size + output->size(); + if (new_len > output->capacity()) { + output->reserve(new_len); + } + + // Loop through the string copying characters to "output" and + // interpreting escape sequences. Note that any invalid escape + // sequences or other errors were already reported while tokenizing. + // In this case we do not need to produce valid results. + for (const char* ptr = text.c_str() + 1; *ptr != '\0'; ptr++) { + if (*ptr == '\\' && ptr[1] != '\0') { + // An escape sequence. + ++ptr; + + if (OctalDigit::InClass(*ptr)) { + // An octal escape. May one, two, or three digits. + int code = DigitValue(*ptr); + if (OctalDigit::InClass(ptr[1])) { + ++ptr; + code = code * 8 + DigitValue(*ptr); + } + if (OctalDigit::InClass(ptr[1])) { + ++ptr; + code = code * 8 + DigitValue(*ptr); + } + output->push_back(static_cast(code)); + + } else if (*ptr == 'x') { + // A hex escape. May zero, one, or two digits. (The zero case + // will have been caught as an error earlier.) + int code = 0; + if (HexDigit::InClass(ptr[1])) { + ++ptr; + code = DigitValue(*ptr); + } + if (HexDigit::InClass(ptr[1])) { + ++ptr; + code = code * 16 + DigitValue(*ptr); + } + output->push_back(static_cast(code)); + + } else if (*ptr == 'u' || *ptr == 'U') { + uint32 unicode; + const char* end = FetchUnicodePoint(ptr, &unicode); + if (end == ptr) { + // Failure: Just dump out what we saw, don't try to parse it. + output->push_back(*ptr); + } else { + AppendUTF8(unicode, output); + ptr = end - 1; // Because we're about to ++ptr. + } + } else { + // Some other escape code. + output->push_back(TranslateEscape(*ptr)); + } + + } else if (*ptr == text[0] && ptr[1] == '\0') { + // Ignore final quote matching the starting quote. + } else { + output->push_back(*ptr); + } + } +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.h new file mode 100644 index 000000000..d85b82f9d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer.h @@ -0,0 +1,384 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Class for parsing tokenized text from a ZeroCopyInputStream. + +#ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__ +#define GOOGLE_PROTOBUF_IO_TOKENIZER_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { + +class ZeroCopyInputStream; // zero_copy_stream.h + +// Defined in this file. +class ErrorCollector; +class Tokenizer; + +// Abstract interface for an object which collects the errors that occur +// during parsing. A typical implementation might simply print the errors +// to stdout. +class LIBPROTOBUF_EXPORT ErrorCollector { + public: + inline ErrorCollector() {} + virtual ~ErrorCollector(); + + // Indicates that there was an error in the input at the given line and + // column numbers. The numbers are zero-based, so you may want to add + // 1 to each before printing them. + virtual void AddError(int line, int column, const string& message) = 0; + + // Indicates that there was a warning in the input at the given line and + // column numbers. The numbers are zero-based, so you may want to add + // 1 to each before printing them. + virtual void AddWarning(int line, int column, const string& message) { } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); +}; + +// This class converts a stream of raw text into a stream of tokens for +// the protocol definition parser to parse. The tokens recognized are +// similar to those that make up the C language; see the TokenType enum for +// precise descriptions. Whitespace and comments are skipped. By default, +// C- and C++-style comments are recognized, but other styles can be used by +// calling set_comment_style(). +class LIBPROTOBUF_EXPORT Tokenizer { + public: + // Construct a Tokenizer that reads and tokenizes text from the given + // input stream and writes errors to the given error_collector. + // The caller keeps ownership of input and error_collector. + Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector); + ~Tokenizer(); + + enum TokenType { + TYPE_START, // Next() has not yet been called. + TYPE_END, // End of input reached. "text" is empty. + + TYPE_IDENTIFIER, // A sequence of letters, digits, and underscores, not + // starting with a digit. It is an error for a number + // to be followed by an identifier with no space in + // between. + TYPE_INTEGER, // A sequence of digits representing an integer. Normally + // the digits are decimal, but a prefix of "0x" indicates + // a hex number and a leading zero indicates octal, just + // like with C numeric literals. A leading negative sign + // is NOT included in the token; it's up to the parser to + // interpret the unary minus operator on its own. + TYPE_FLOAT, // A floating point literal, with a fractional part and/or + // an exponent. Always in decimal. Again, never + // negative. + TYPE_STRING, // A quoted sequence of escaped characters. Either single + // or double quotes can be used, but they must match. + // A string literal cannot cross a line break. + TYPE_SYMBOL, // Any other printable character, like '!' or '+'. + // Symbols are always a single character, so "!+$%" is + // four tokens. + }; + + // Structure representing a token read from the token stream. + struct Token { + TokenType type; + string text; // The exact text of the token as it appeared in + // the input. e.g. tokens of TYPE_STRING will still + // be escaped and in quotes. + + // "line" and "column" specify the position of the first character of + // the token within the input stream. They are zero-based. + int line; + int column; + int end_column; + }; + + // Get the current token. This is updated when Next() is called. Before + // the first call to Next(), current() has type TYPE_START and no contents. + const Token& current(); + + // Return the previous token -- i.e. what current() returned before the + // previous call to Next(). + const Token& previous(); + + // Advance to the next token. Returns false if the end of the input is + // reached. + bool Next(); + + // Like Next(), but also collects comments which appear between the previous + // and next tokens. + // + // Comments which appear to be attached to the previous token are stored + // in *prev_tailing_comments. Comments which appear to be attached to the + // next token are stored in *next_leading_comments. Comments appearing in + // between which do not appear to be attached to either will be added to + // detached_comments. Any of these parameters can be NULL to simply discard + // the comments. + // + // A series of line comments appearing on consecutive lines, with no other + // tokens appearing on those lines, will be treated as a single comment. + // + // Only the comment content is returned; comment markers (e.g. //) are + // stripped out. For block comments, leading whitespace and an asterisk will + // be stripped from the beginning of each line other than the first. Newlines + // are included in the output. + // + // Examples: + // + // optional int32 foo = 1; // Comment attached to foo. + // // Comment attached to bar. + // optional int32 bar = 2; + // + // optional string baz = 3; + // // Comment attached to baz. + // // Another line attached to baz. + // + // // Comment attached to qux. + // // + // // Another line attached to qux. + // optional double qux = 4; + // + // // Detached comment. This is not attached to qux or corge + // // because there are blank lines separating it from both. + // + // optional string corge = 5; + // /* Block comment attached + // * to corge. Leading asterisks + // * will be removed. */ + // /* Block comment attached to + // * grault. */ + // optional int32 grault = 6; + bool NextWithComments(string* prev_trailing_comments, + vector* detached_comments, + string* next_leading_comments); + + // Parse helpers --------------------------------------------------- + + // Parses a TYPE_FLOAT token. This never fails, so long as the text actually + // comes from a TYPE_FLOAT token parsed by Tokenizer. If it doesn't, the + // result is undefined (possibly an assert failure). + static double ParseFloat(const string& text); + + // Parses a TYPE_STRING token. This never fails, so long as the text actually + // comes from a TYPE_STRING token parsed by Tokenizer. If it doesn't, the + // result is undefined (possibly an assert failure). + static void ParseString(const string& text, string* output); + + // Identical to ParseString, but appends to output. + static void ParseStringAppend(const string& text, string* output); + + // Parses a TYPE_INTEGER token. Returns false if the result would be + // greater than max_value. Otherwise, returns true and sets *output to the + // result. If the text is not from a Token of type TYPE_INTEGER originally + // parsed by a Tokenizer, the result is undefined (possibly an assert + // failure). + static bool ParseInteger(const string& text, uint64 max_value, + uint64* output); + + // Options --------------------------------------------------------- + + // Set true to allow floats to be suffixed with the letter 'f'. Tokens + // which would otherwise be integers but which have the 'f' suffix will be + // forced to be interpreted as floats. For all other purposes, the 'f' is + // ignored. + void set_allow_f_after_float(bool value) { allow_f_after_float_ = value; } + + // Valid values for set_comment_style(). + enum CommentStyle { + // Line comments begin with "//", block comments are delimited by "/*" and + // "*/". + CPP_COMMENT_STYLE, + // Line comments begin with "#". No way to write block comments. + SH_COMMENT_STYLE + }; + + // Sets the comment style. + void set_comment_style(CommentStyle style) { comment_style_ = style; } + + // ----------------------------------------------------------------- + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); + + Token current_; // Returned by current(). + Token previous_; // Returned by previous(). + + ZeroCopyInputStream* input_; + ErrorCollector* error_collector_; + + char current_char_; // == buffer_[buffer_pos_], updated by NextChar(). + const char* buffer_; // Current buffer returned from input_. + int buffer_size_; // Size of buffer_. + int buffer_pos_; // Current position within the buffer. + bool read_error_; // Did we previously encounter a read error? + + // Line and column number of current_char_ within the whole input stream. + int line_; + int column_; + + // String to which text should be appended as we advance through it. + // Call RecordTo(&str) to start recording and StopRecording() to stop. + // E.g. StartToken() calls RecordTo(¤t_.text). record_start_ is the + // position within the current buffer where recording started. + string* record_target_; + int record_start_; + + // Options. + bool allow_f_after_float_; + CommentStyle comment_style_; + + // Since we count columns we need to interpret tabs somehow. We'll take + // the standard 8-character definition for lack of any way to do better. + static const int kTabWidth = 8; + + // ----------------------------------------------------------------- + // Helper methods. + + // Consume this character and advance to the next one. + void NextChar(); + + // Read a new buffer from the input. + void Refresh(); + + inline void RecordTo(string* target); + inline void StopRecording(); + + // Called when the current character is the first character of a new + // token (not including whitespace or comments). + inline void StartToken(); + // Called when the current character is the first character after the + // end of the last token. After this returns, current_.text will + // contain all text consumed since StartToken() was called. + inline void EndToken(); + + // Convenience method to add an error at the current line and column. + void AddError(const string& message) { + error_collector_->AddError(line_, column_, message); + } + + // ----------------------------------------------------------------- + // The following four methods are used to consume tokens of specific + // types. They are actually used to consume all characters *after* + // the first, since the calling function consumes the first character + // in order to decide what kind of token is being read. + + // Read and consume a string, ending when the given delimiter is + // consumed. + void ConsumeString(char delimiter); + + // Read and consume a number, returning TYPE_FLOAT or TYPE_INTEGER + // depending on what was read. This needs to know if the first + // character was a zero in order to correctly recognize hex and octal + // numbers. + // It also needs to know if the first characted was a . to parse floating + // point correctly. + TokenType ConsumeNumber(bool started_with_zero, bool started_with_dot); + + // Consume the rest of a line. + void ConsumeLineComment(string* content); + // Consume until "*/". + void ConsumeBlockComment(string* content); + + enum NextCommentStatus { + // Started a line comment. + LINE_COMMENT, + + // Started a block comment. + BLOCK_COMMENT, + + // Consumed a slash, then realized it wasn't a comment. current_ has + // been filled in with a slash token. The caller should return it. + SLASH_NOT_COMMENT, + + // We do not appear to be starting a comment here. + NO_COMMENT + }; + + // If we're at the start of a new comment, consume it and return what kind + // of comment it is. + NextCommentStatus TryConsumeCommentStart(); + + // ----------------------------------------------------------------- + // These helper methods make the parsing code more readable. The + // "character classes" refered to are defined at the top of the .cc file. + // Basically it is a C++ class with one method: + // static bool InClass(char c); + // The method returns true if c is a member of this "class", like "Letter" + // or "Digit". + + // Returns true if the current character is of the given character + // class, but does not consume anything. + template + inline bool LookingAt(); + + // If the current character is in the given class, consume it and return + // true. Otherwise return false. + // e.g. TryConsumeOne() + template + inline bool TryConsumeOne(); + + // Like above, but try to consume the specific character indicated. + inline bool TryConsume(char c); + + // Consume zero or more of the given character class. + template + inline void ConsumeZeroOrMore(); + + // Consume one or more of the given character class or log the given + // error message. + // e.g. ConsumeOneOrMore("Expected digits."); + template + inline void ConsumeOneOrMore(const char* error); +}; + +// inline methods ==================================================== +inline const Tokenizer::Token& Tokenizer::current() { + return current_; +} + +inline const Tokenizer::Token& Tokenizer::previous() { + return previous_; +} + +inline void Tokenizer::ParseString(const string& text, string* output) { + output->clear(); + ParseStringAppend(text, output); +} + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_TOKENIZER_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer_unittest.cc new file mode 100644 index 000000000..dbb5be4f6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/tokenizer_unittest.cc @@ -0,0 +1,1001 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { +namespace { + +// =================================================================== +// Data-Driven Test Infrastructure + +// TODO(kenton): This is copied from coded_stream_unittest. This is +// temporary until these fetaures are integrated into gTest itself. + +// TEST_1D and TEST_2D are macros I'd eventually like to see added to +// gTest. These macros can be used to declare tests which should be +// run multiple times, once for each item in some input array. TEST_1D +// tests all cases in a single input array. TEST_2D tests all +// combinations of cases from two arrays. The arrays must be statically +// defined such that the GOOGLE_ARRAYSIZE() macro works on them. Example: +// +// int kCases[] = {1, 2, 3, 4} +// TEST_1D(MyFixture, MyTest, kCases) { +// EXPECT_GT(kCases_case, 0); +// } +// +// This test iterates through the numbers 1, 2, 3, and 4 and tests that +// they are all grater than zero. In case of failure, the exact case +// which failed will be printed. The case type must be printable using +// ostream::operator<<. + +#define TEST_1D(FIXTURE, NAME, CASES) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType& CASES##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES " case #" << i << ": " << CASES[i]); \ + DoSingleCase(CASES[i]); \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType& CASES##_case) + +#define TEST_2D(FIXTURE, NAME, CASES1, CASES2) \ + class FIXTURE##_##NAME##_DD : public FIXTURE { \ + protected: \ + template \ + void DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case); \ + }; \ + \ + TEST_F(FIXTURE##_##NAME##_DD, NAME) { \ + for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) { \ + for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) { \ + SCOPED_TRACE(testing::Message() \ + << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \ + << #CASES2 " case #" << j << ": " << CASES2[j]); \ + DoSingleCase(CASES1[i], CASES2[j]); \ + } \ + } \ + } \ + \ + template \ + void FIXTURE##_##NAME##_DD::DoSingleCase(const CaseType1& CASES1##_case, \ + const CaseType2& CASES2##_case) + +// ------------------------------------------------------------------- + +// An input stream that is basically like an ArrayInputStream but sometimes +// returns empty buffers, just to throw us off. +class TestInputStream : public ZeroCopyInputStream { + public: + TestInputStream(const void* data, int size, int block_size) + : array_stream_(data, size, block_size), counter_(0) {} + ~TestInputStream() {} + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size) { + // We'll return empty buffers starting with the first buffer, and every + // 3 and 5 buffers after that. + if (counter_ % 3 == 0 || counter_ % 5 == 0) { + *data = NULL; + *size = 0; + ++counter_; + return true; + } else { + ++counter_; + return array_stream_.Next(data, size); + } + } + + void BackUp(int count) { return array_stream_.BackUp(count); } + bool Skip(int count) { return array_stream_.Skip(count); } + int64 ByteCount() const { return array_stream_.ByteCount(); } + + private: + ArrayInputStream array_stream_; + int counter_; +}; + +// ------------------------------------------------------------------- + +// An error collector which simply concatenates all its errors into a big +// block of text which can be checked. +class TestErrorCollector : public ErrorCollector { + public: + TestErrorCollector() {} + ~TestErrorCollector() {} + + string text_; + + // implements ErrorCollector --------------------------------------- + void AddError(int line, int column, const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", + line, column, message); + } +}; + +// ------------------------------------------------------------------- + +// We test each operation over a variety of block sizes to insure that +// we test cases where reads cross buffer boundaries as well as cases +// where they don't. This is sort of a brute-force approach to this, +// but it's easy to write and easy to understand. +const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024}; + +class TokenizerTest : public testing::Test { + protected: + // For easy testing. + uint64 ParseInteger(const string& text) { + uint64 result; + EXPECT_TRUE(Tokenizer::ParseInteger(text, kuint64max, &result)); + return result; + } +}; + +// =================================================================== + +// These tests causes gcc 3.3.5 (and earlier?) to give the cryptic error: +// "sorry, unimplemented: `method_call_expr' not supported by dump_expr" +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) + +// In each test case, the entire input text should parse as a single token +// of the given type. +struct SimpleTokenCase { + string input; + Tokenizer::TokenType type; +}; + +inline ostream& operator<<(ostream& out, + const SimpleTokenCase& test_case) { + return out << CEscape(test_case.input); +} + +SimpleTokenCase kSimpleTokenCases[] = { + // Test identifiers. + { "hello", Tokenizer::TYPE_IDENTIFIER }, + + // Test integers. + { "123", Tokenizer::TYPE_INTEGER }, + { "0xab6", Tokenizer::TYPE_INTEGER }, + { "0XAB6", Tokenizer::TYPE_INTEGER }, + { "0X1234567", Tokenizer::TYPE_INTEGER }, + { "0x89abcdef", Tokenizer::TYPE_INTEGER }, + { "0x89ABCDEF", Tokenizer::TYPE_INTEGER }, + { "01234567", Tokenizer::TYPE_INTEGER }, + + // Test floats. + { "123.45", Tokenizer::TYPE_FLOAT }, + { "1.", Tokenizer::TYPE_FLOAT }, + { "1e3", Tokenizer::TYPE_FLOAT }, + { "1E3", Tokenizer::TYPE_FLOAT }, + { "1e-3", Tokenizer::TYPE_FLOAT }, + { "1e+3", Tokenizer::TYPE_FLOAT }, + { "1.e3", Tokenizer::TYPE_FLOAT }, + { "1.2e3", Tokenizer::TYPE_FLOAT }, + { ".1", Tokenizer::TYPE_FLOAT }, + { ".1e3", Tokenizer::TYPE_FLOAT }, + { ".1e-3", Tokenizer::TYPE_FLOAT }, + { ".1e+3", Tokenizer::TYPE_FLOAT }, + + // Test strings. + { "'hello'", Tokenizer::TYPE_STRING }, + { "\"foo\"", Tokenizer::TYPE_STRING }, + { "'a\"b'", Tokenizer::TYPE_STRING }, + { "\"a'b\"", Tokenizer::TYPE_STRING }, + { "'a\\'b'", Tokenizer::TYPE_STRING }, + { "\"a\\\"b\"", Tokenizer::TYPE_STRING }, + { "'\\xf'", Tokenizer::TYPE_STRING }, + { "'\\0'", Tokenizer::TYPE_STRING }, + + // Test symbols. + { "+", Tokenizer::TYPE_SYMBOL }, + { ".", Tokenizer::TYPE_SYMBOL }, +}; + +TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { + // Set up the tokenizer. + TestInputStream input(kSimpleTokenCases_case.input.data(), + kSimpleTokenCases_case.input.size(), + kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + // Before Next() is called, the initial token should always be TYPE_START. + EXPECT_EQ(Tokenizer::TYPE_START, tokenizer.current().type); + EXPECT_EQ("", tokenizer.current().text); + EXPECT_EQ(0, tokenizer.current().line); + EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); + + // Parse the token. + ASSERT_TRUE(tokenizer.Next()); + + // Check that it has the right type. + EXPECT_EQ(kSimpleTokenCases_case.type, tokenizer.current().type); + // Check that it contains the complete input text. + EXPECT_EQ(kSimpleTokenCases_case.input, tokenizer.current().text); + // Check that it is located at the beginning of the input + EXPECT_EQ(0, tokenizer.current().line); + EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); + + // There should be no more input. + EXPECT_FALSE(tokenizer.Next()); + + // After Next() returns false, the token should have type TYPE_END. + EXPECT_EQ(Tokenizer::TYPE_END, tokenizer.current().type); + EXPECT_EQ("", tokenizer.current().text); + EXPECT_EQ(0, tokenizer.current().line); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); + + // There should be no errors. + EXPECT_TRUE(error_collector.text_.empty()); +} + +TEST_1D(TokenizerTest, FloatSuffix, kBlockSizes) { + // Test the "allow_f_after_float" option. + + // Set up the tokenizer. + const char* text = "1f 2.5f 6e3f 7F"; + TestInputStream input(text, strlen(text), kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + tokenizer.set_allow_f_after_float(true); + + // Advance through tokens and check that they are parsed as expected. + ASSERT_TRUE(tokenizer.Next()); + EXPECT_EQ(tokenizer.current().text, "1f"); + EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT); + ASSERT_TRUE(tokenizer.Next()); + EXPECT_EQ(tokenizer.current().text, "2.5f"); + EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT); + ASSERT_TRUE(tokenizer.Next()); + EXPECT_EQ(tokenizer.current().text, "6e3f"); + EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT); + ASSERT_TRUE(tokenizer.Next()); + EXPECT_EQ(tokenizer.current().text, "7F"); + EXPECT_EQ(tokenizer.current().type, Tokenizer::TYPE_FLOAT); + + // There should be no more input. + EXPECT_FALSE(tokenizer.Next()); + // There should be no errors. + EXPECT_TRUE(error_collector.text_.empty()); +} + +#endif + +// ------------------------------------------------------------------- + +// In each case, the input is parsed to produce a list of tokens. The +// last token in "output" must have type TYPE_END. +struct MultiTokenCase { + string input; + Tokenizer::Token output[10]; // The compiler wants a constant array + // size for initialization to work. There + // is no reason this can't be increased if + // needed. +}; + +inline ostream& operator<<(ostream& out, + const MultiTokenCase& test_case) { + return out << CEscape(test_case.input); +} + +MultiTokenCase kMultiTokenCases[] = { + // Test empty input. + { "", { + { Tokenizer::TYPE_END , "" , 0, 0 }, + }}, + + // Test all token types at the same time. + { "foo 1 1.2 + 'bar'", { + { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0, 3 }, + { Tokenizer::TYPE_INTEGER , "1" , 0, 4, 5 }, + { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6, 9 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 10, 11 }, + { Tokenizer::TYPE_STRING , "'bar'", 0, 12, 17 }, + { Tokenizer::TYPE_END , "" , 0, 17, 17 }, + }}, + + // Test that consecutive symbols are parsed as separate tokens. + { "!@+%", { + { Tokenizer::TYPE_SYMBOL , "!" , 0, 0, 1 }, + { Tokenizer::TYPE_SYMBOL , "@" , 0, 1, 2 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 2, 3 }, + { Tokenizer::TYPE_SYMBOL , "%" , 0, 3, 4 }, + { Tokenizer::TYPE_END , "" , 0, 4, 4 }, + }}, + + // Test that newlines affect line numbers correctly. + { "foo bar\nrab oof", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4, 7 }, + { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4, 7 }, + { Tokenizer::TYPE_END , "" , 1, 7, 7 }, + }}, + + // Test that tabs affect column numbers correctly. + { "foo\tbar \tbaz", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8, 11 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 }, + { Tokenizer::TYPE_END , "" , 0, 19, 19 }, + }}, + + // Test that tabs in string literals affect column numbers correctly. + { "\"foo\tbar\" baz", { + { Tokenizer::TYPE_STRING , "\"foo\tbar\"", 0, 0, 12 }, + { Tokenizer::TYPE_IDENTIFIER, "baz" , 0, 13, 16 }, + { Tokenizer::TYPE_END , "" , 0, 16, 16 }, + }}, + + // Test that line comments are ignored. + { "foo // This is a comment\n" + "bar // This is another comment", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0, 3 }, + { Tokenizer::TYPE_END , "" , 1, 30, 30 }, + }}, + + // Test that block comments are ignored. + { "foo /* This is a block comment */ bar", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 }, + { Tokenizer::TYPE_END , "" , 0, 37, 37 }, + }}, + + // Test that sh-style comments are not ignored by default. + { "foo # bar\n" + "baz", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_SYMBOL , "#" , 0, 4, 5 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 }, + { Tokenizer::TYPE_END , "" , 1, 3, 3 }, + }}, + + // Bytes with the high-order bit set should not be seen as control characters. + { "\300", { + { Tokenizer::TYPE_SYMBOL, "\300", 0, 0, 1 }, + { Tokenizer::TYPE_END , "" , 0, 1, 1 }, + }}, + + // Test all whitespace chars + { "foo\n\t\r\v\fbar", { + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 }, + { Tokenizer::TYPE_END , "" , 1, 14, 14 }, + }}, +}; + +TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { + // Set up the tokenizer. + TestInputStream input(kMultiTokenCases_case.input.data(), + kMultiTokenCases_case.input.size(), + kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + // Before Next() is called, the initial token should always be TYPE_START. + EXPECT_EQ(Tokenizer::TYPE_START, tokenizer.current().type); + EXPECT_EQ("", tokenizer.current().text); + EXPECT_EQ(0, tokenizer.current().line); + EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); + + // Loop through all expected tokens. + int i = 0; + Tokenizer::Token token; + do { + token = kMultiTokenCases_case.output[i++]; + + SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text); + + Tokenizer::Token previous = tokenizer.current(); + + // Next() should only return false when it hits the end token. + if (token.type != Tokenizer::TYPE_END) { + ASSERT_TRUE(tokenizer.Next()); + } else { + ASSERT_FALSE(tokenizer.Next()); + } + + // Check that the previous token is set correctly. + EXPECT_EQ(previous.type, tokenizer.previous().type); + EXPECT_EQ(previous.text, tokenizer.previous().text); + EXPECT_EQ(previous.line, tokenizer.previous().line); + EXPECT_EQ(previous.column, tokenizer.previous().column); + EXPECT_EQ(previous.end_column, tokenizer.previous().end_column); + + // Check that the token matches the expected one. + EXPECT_EQ(token.type, tokenizer.current().type); + EXPECT_EQ(token.text, tokenizer.current().text); + EXPECT_EQ(token.line, tokenizer.current().line); + EXPECT_EQ(token.column, tokenizer.current().column); + EXPECT_EQ(token.end_column, tokenizer.current().end_column); + + } while (token.type != Tokenizer::TYPE_END); + + // There should be no errors. + EXPECT_TRUE(error_collector.text_.empty()); +} + +// This test causes gcc 3.3.5 (and earlier?) to give the cryptic error: +// "sorry, unimplemented: `method_call_expr' not supported by dump_expr" +#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) + +TEST_1D(TokenizerTest, ShCommentStyle, kBlockSizes) { + // Test the "comment_style" option. + + const char* text = "foo # bar\n" + "baz // qux\n" + "corge /* grault */\n" + "garply"; + const char* const kTokens[] = {"foo", // "# bar" is ignored + "baz", "/", "/", "qux", + "corge", "/", "*", "grault", "*", "/", + "garply"}; + + // Set up the tokenizer. + TestInputStream input(text, strlen(text), kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + tokenizer.set_comment_style(Tokenizer::SH_COMMENT_STYLE); + + // Advance through tokens and check that they are parsed as expected. + for (int i = 0; i < GOOGLE_ARRAYSIZE(kTokens); i++) { + EXPECT_TRUE(tokenizer.Next()); + EXPECT_EQ(tokenizer.current().text, kTokens[i]); + } + + // There should be no more input. + EXPECT_FALSE(tokenizer.Next()); + // There should be no errors. + EXPECT_TRUE(error_collector.text_.empty()); +} + +#endif + +// ------------------------------------------------------------------- + +// In each case, the input is expected to have two tokens named "prev" and +// "next" with comments in between. +struct DocCommentCase { + string input; + + const char* prev_trailing_comments; + const char* detached_comments[10]; + const char* next_leading_comments; +}; + +inline ostream& operator<<(ostream& out, + const DocCommentCase& test_case) { + return out << CEscape(test_case.input); +} + +DocCommentCase kDocCommentCases[] = { + { + "prev next", + + "", + {}, + "" + }, + + { + "prev /* ignored */ next", + + "", + {}, + "" + }, + + { + "prev // trailing comment\n" + "next", + + " trailing comment\n", + {}, + "" + }, + + { + "prev\n" + "// leading comment\n" + "// line 2\n" + "next", + + "", + {}, + " leading comment\n" + " line 2\n" + }, + + { + "prev\n" + "// trailing comment\n" + "// line 2\n" + "\n" + "next", + + " trailing comment\n" + " line 2\n", + {}, + "" + }, + + { + "prev // trailing comment\n" + "// leading comment\n" + "// line 2\n" + "next", + + " trailing comment\n", + {}, + " leading comment\n" + " line 2\n" + }, + + { + "prev /* trailing block comment */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment ", + {}, + " leading block comment\n" + " line 2\n" + " line 3 " + }, + + { + "prev\n" + "/* trailing block comment\n" + " * line 2\n" + " * line 3\n" + " */\n" + "/* leading block comment\n" + " * line 2\n" + " * line 3 */" + "next", + + " trailing block comment\n" + " line 2\n" + " line 3\n", + {}, + " leading block comment\n" + " line 2\n" + " line 3 " + }, + + { + "prev\n" + "// trailing comment\n" + "\n" + "// detached comment\n" + "// line 2\n" + "\n" + "// second detached comment\n" + "/* third detached comment\n" + " * line 2 */\n" + "// leading comment\n" + "next", + + " trailing comment\n", + { + " detached comment\n" + " line 2\n", + " second detached comment\n", + " third detached comment\n" + " line 2 " + }, + " leading comment\n" + }, + + { + "prev /**/\n" + "\n" + "// detached comment\n" + "\n" + "// leading comment\n" + "next", + + "", + { + " detached comment\n" + }, + " leading comment\n" + }, + + { + "prev /**/\n" + "// leading comment\n" + "next", + + "", + {}, + " leading comment\n" + }, + }; + +TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) { + // Set up the tokenizer. + TestInputStream input(kDocCommentCases_case.input.data(), + kDocCommentCases_case.input.size(), + kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + // Set up a second tokenizer where we'll pass all NULLs to NextWithComments(). + TestInputStream input2(kDocCommentCases_case.input.data(), + kDocCommentCases_case.input.size(), + kBlockSizes_case); + Tokenizer tokenizer2(&input2, &error_collector); + + tokenizer.Next(); + tokenizer2.Next(); + + EXPECT_EQ("prev", tokenizer.current().text); + EXPECT_EQ("prev", tokenizer2.current().text); + + string prev_trailing_comments; + vector detached_comments; + string next_leading_comments; + tokenizer.NextWithComments(&prev_trailing_comments, &detached_comments, + &next_leading_comments); + tokenizer2.NextWithComments(NULL, NULL, NULL); + EXPECT_EQ("next", tokenizer.current().text); + EXPECT_EQ("next", tokenizer2.current().text); + + EXPECT_EQ(kDocCommentCases_case.prev_trailing_comments, + prev_trailing_comments); + + for (int i = 0; i < detached_comments.size(); i++) { + ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases)); + ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL); + EXPECT_EQ(kDocCommentCases_case.detached_comments[i], + detached_comments[i]); + } + + // Verify that we matched all the detached comments. + EXPECT_EQ(NULL, + kDocCommentCases_case.detached_comments[detached_comments.size()]); + + EXPECT_EQ(kDocCommentCases_case.next_leading_comments, + next_leading_comments); +} + +// ------------------------------------------------------------------- + +// Test parse helpers. It's not really worth setting up a full data-driven +// test here. +TEST_F(TokenizerTest, ParseInteger) { + EXPECT_EQ(0, ParseInteger("0")); + EXPECT_EQ(123, ParseInteger("123")); + EXPECT_EQ(0xabcdef12u, ParseInteger("0xabcdef12")); + EXPECT_EQ(0xabcdef12u, ParseInteger("0xABCDEF12")); + EXPECT_EQ(kuint64max, ParseInteger("0xFFFFFFFFFFFFFFFF")); + EXPECT_EQ(01234567, ParseInteger("01234567")); + EXPECT_EQ(0X123, ParseInteger("0X123")); + + // Test invalid integers that may still be tokenized as integers. + EXPECT_EQ(0, ParseInteger("0x")); + + uint64 i; +#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet + // Test invalid integers that will never be tokenized as integers. + EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("zxy", kuint64max, &i), + "passed text that could not have been tokenized as an integer"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("1.2", kuint64max, &i), + "passed text that could not have been tokenized as an integer"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("08", kuint64max, &i), + "passed text that could not have been tokenized as an integer"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("0xg", kuint64max, &i), + "passed text that could not have been tokenized as an integer"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i), + "passed text that could not have been tokenized as an integer"); +#endif // PROTOBUF_HASDEATH_TEST + + // Test overflows. + EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i)); + EXPECT_FALSE(Tokenizer::ParseInteger("1", 0, &i)); + EXPECT_TRUE (Tokenizer::ParseInteger("1", 1, &i)); + EXPECT_TRUE (Tokenizer::ParseInteger("12345", 12345, &i)); + EXPECT_FALSE(Tokenizer::ParseInteger("12346", 12345, &i)); + EXPECT_TRUE (Tokenizer::ParseInteger("0xFFFFFFFFFFFFFFFF" , kuint64max, &i)); + EXPECT_FALSE(Tokenizer::ParseInteger("0x10000000000000000", kuint64max, &i)); +} + +TEST_F(TokenizerTest, ParseFloat) { + EXPECT_DOUBLE_EQ(1 , Tokenizer::ParseFloat("1.")); + EXPECT_DOUBLE_EQ(1e3 , Tokenizer::ParseFloat("1e3")); + EXPECT_DOUBLE_EQ(1e3 , Tokenizer::ParseFloat("1E3")); + EXPECT_DOUBLE_EQ(1.5e3, Tokenizer::ParseFloat("1.5e3")); + EXPECT_DOUBLE_EQ(.1 , Tokenizer::ParseFloat(".1")); + EXPECT_DOUBLE_EQ(.25 , Tokenizer::ParseFloat(".25")); + EXPECT_DOUBLE_EQ(.1e3 , Tokenizer::ParseFloat(".1e3")); + EXPECT_DOUBLE_EQ(.25e3, Tokenizer::ParseFloat(".25e3")); + EXPECT_DOUBLE_EQ(.1e+3, Tokenizer::ParseFloat(".1e+3")); + EXPECT_DOUBLE_EQ(.1e-3, Tokenizer::ParseFloat(".1e-3")); + EXPECT_DOUBLE_EQ(5 , Tokenizer::ParseFloat("5")); + EXPECT_DOUBLE_EQ(6e-12, Tokenizer::ParseFloat("6e-12")); + EXPECT_DOUBLE_EQ(1.2 , Tokenizer::ParseFloat("1.2")); + EXPECT_DOUBLE_EQ(1.e2 , Tokenizer::ParseFloat("1.e2")); + + // Test invalid integers that may still be tokenized as integers. + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1e")); + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1e-")); + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1.e")); + + // Test 'f' suffix. + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1f")); + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1.0f")); + EXPECT_DOUBLE_EQ(1, Tokenizer::ParseFloat("1F")); + + // These should parse successfully even though they are out of range. + // Overflows become infinity and underflows become zero. + EXPECT_EQ( 0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999")); + EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999")); + +#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet + // Test invalid integers that will never be tokenized as integers. + EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("zxy"), + "passed text that could not have been tokenized as a float"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("1-e0"), + "passed text that could not have been tokenized as a float"); + EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("-1.0"), + "passed text that could not have been tokenized as a float"); +#endif // PROTOBUF_HASDEATH_TEST +} + +TEST_F(TokenizerTest, ParseString) { + string output; + Tokenizer::ParseString("'hello'", &output); + EXPECT_EQ("hello", output); + Tokenizer::ParseString("\"blah\\nblah2\"", &output); + EXPECT_EQ("blah\nblah2", output); + Tokenizer::ParseString("'\\1x\\1\\123\\739\\52\\334n\\3'", &output); + EXPECT_EQ("\1x\1\123\739\52\334n\3", output); + Tokenizer::ParseString("'\\x20\\x4'", &output); + EXPECT_EQ("\x20\x4", output); + + // Test invalid strings that may still be tokenized as strings. + Tokenizer::ParseString("\"\\a\\l\\v\\t", &output); // \l is invalid + EXPECT_EQ("\a?\v\t", output); + Tokenizer::ParseString("'", &output); + EXPECT_EQ("", output); + Tokenizer::ParseString("'\\", &output); + EXPECT_EQ("\\", output); + + // Experiment with Unicode escapes. Here are one-, two- and three-byte Unicode + // characters. + Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\U00024b62XX'", &output); + EXPECT_EQ("$¢€𤭢XX", output); + // Same thing encoded using UTF16. + Tokenizer::ParseString("'\\u0024\\u00a2\\u20ac\\ud852\\udf62XX'", &output); + EXPECT_EQ("$¢€𤭢XX", output); + // Here's some broken UTF16; there's a head surrogate with no tail surrogate. + // We just output this as if it were UTF8; it's not a defined code point, but + // it has a defined encoding. + Tokenizer::ParseString("'\\ud852XX'", &output); + EXPECT_EQ("\xed\xa1\x92XX", output); + // Malformed escape: Demons may fly out of the nose. + Tokenizer::ParseString("\\u0", &output); + EXPECT_EQ("u0", output); + + // Test invalid strings that will never be tokenized as strings. +#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet + EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output), + "passed text that could not have been tokenized as a string"); +#endif // PROTOBUF_HASDEATH_TEST +} + +TEST_F(TokenizerTest, ParseStringAppend) { + // Check that ParseString and ParseStringAppend differ. + string output("stuff+"); + Tokenizer::ParseStringAppend("'hello'", &output); + EXPECT_EQ("stuff+hello", output); + Tokenizer::ParseString("'hello'", &output); + EXPECT_EQ("hello", output); +} + +// ------------------------------------------------------------------- + +// Each case parses some input text, ignoring the tokens produced, and +// checks that the error output matches what is expected. +struct ErrorCase { + string input; + bool recoverable; // True if the tokenizer should be able to recover and + // parse more tokens after seeing this error. Cases + // for which this is true must end with "foo" as + // the last token, which the test will check for. + const char* errors; +}; + +inline ostream& operator<<(ostream& out, + const ErrorCase& test_case) { + return out << CEscape(test_case.input); +} + +ErrorCase kErrorCases[] = { + // String errors. + { "'\\l' foo", true, + "0:2: Invalid escape sequence in string literal.\n" }, + { "'\\x' foo", true, + "0:3: Expected hex digits for escape sequence.\n" }, + { "'foo", false, + "0:4: String literals cannot cross line boundaries.\n" }, + { "'bar\nfoo", true, + "0:4: String literals cannot cross line boundaries.\n" }, + { "'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n" }, + { "'\\u01' foo", true, + "0:5: Expected four hex digits for \\u escape sequence.\n" }, + { "'\\uXYZ' foo", true, + "0:3: Expected four hex digits for \\u escape sequence.\n" }, + + // Integer errors. + { "123foo", true, + "0:3: Need space between number and identifier.\n" }, + + // Hex/octal errors. + { "0x foo", true, + "0:2: \"0x\" must be followed by hex digits.\n" }, + { "0541823 foo", true, + "0:4: Numbers starting with leading zero must be in octal.\n" }, + { "0x123z foo", true, + "0:5: Need space between number and identifier.\n" }, + { "0x123.4 foo", true, + "0:5: Hex and octal numbers must be integers.\n" }, + { "0123.4 foo", true, + "0:4: Hex and octal numbers must be integers.\n" }, + + // Float errors. + { "1e foo", true, + "0:2: \"e\" must be followed by exponent.\n" }, + { "1e- foo", true, + "0:3: \"e\" must be followed by exponent.\n" }, + { "1.2.3 foo", true, + "0:3: Already saw decimal point or exponent; can't have another one.\n" }, + { "1e2.3 foo", true, + "0:3: Already saw decimal point or exponent; can't have another one.\n" }, + { "a.1 foo", true, + "0:1: Need space between identifier and decimal point.\n" }, + // allow_f_after_float not enabled, so this should be an error. + { "1.0f foo", true, + "0:3: Need space between number and identifier.\n" }, + + // Block comment errors. + { "/*", false, + "0:2: End-of-file inside block comment.\n" + "0:0: Comment started here.\n"}, + { "/*/*/ foo", true, + "0:3: \"/*\" inside block comment. Block comments cannot be nested.\n"}, + + // Control characters. Multiple consecutive control characters should only + // produce one error. + { "\b foo", true, + "0:0: Invalid control characters encountered in text.\n" }, + { "\b\b foo", true, + "0:0: Invalid control characters encountered in text.\n" }, + + // Check that control characters at end of input don't result in an + // infinite loop. + { "\b", false, + "0:0: Invalid control characters encountered in text.\n" }, + + // Check recovery from '\0'. We have to explicitly specify the length of + // these strings because otherwise the string constructor will just call + // strlen() which will see the first '\0' and think that is the end of the + // string. + { string("\0foo", 4), true, + "0:0: Invalid control characters encountered in text.\n" }, + { string("\0\0foo", 5), true, + "0:0: Invalid control characters encountered in text.\n" }, +}; + +TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { + // Set up the tokenizer. + TestInputStream input(kErrorCases_case.input.data(), + kErrorCases_case.input.size(), + kBlockSizes_case); + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + // Ignore all input, except remember if the last token was "foo". + bool last_was_foo = false; + while (tokenizer.Next()) { + last_was_foo = tokenizer.current().text == "foo"; + } + + // Check that the errors match what was expected. + EXPECT_EQ(kErrorCases_case.errors, error_collector.text_); + + // If the error was recoverable, make sure we saw "foo" after it. + if (kErrorCases_case.recoverable) { + EXPECT_TRUE(last_was_foo); + } +} + +// ------------------------------------------------------------------- + +TEST_1D(TokenizerTest, BackUpOnDestruction, kBlockSizes) { + string text = "foo bar"; + TestInputStream input(text.data(), text.size(), kBlockSizes_case); + + // Create a tokenizer, read one token, then destroy it. + { + TestErrorCollector error_collector; + Tokenizer tokenizer(&input, &error_collector); + + tokenizer.Next(); + } + + // Only "foo" should have been read. + EXPECT_EQ(strlen("foo"), input.ByteCount()); +} + + +} // namespace +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.cc new file mode 100644 index 000000000..dad6ff144 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.cc @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + + +namespace google { +namespace protobuf { +namespace io { + +ZeroCopyInputStream::~ZeroCopyInputStream() {} +ZeroCopyOutputStream::~ZeroCopyOutputStream() {} + + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.h new file mode 100644 index 000000000..db5326f70 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream.h @@ -0,0 +1,238 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains the ZeroCopyInputStream and ZeroCopyOutputStream +// interfaces, which represent abstract I/O streams to and from which +// protocol buffers can be read and written. For a few simple +// implementations of these interfaces, see zero_copy_stream_impl.h. +// +// These interfaces are different from classic I/O streams in that they +// try to minimize the amount of data copying that needs to be done. +// To accomplish this, responsibility for allocating buffers is moved to +// the stream object, rather than being the responsibility of the caller. +// So, the stream can return a buffer which actually points directly into +// the final data structure where the bytes are to be stored, and the caller +// can interact directly with that buffer, eliminating an intermediate copy +// operation. +// +// As an example, consider the common case in which you are reading bytes +// from an array that is already in memory (or perhaps an mmap()ed file). +// With classic I/O streams, you would do something like: +// char buffer[BUFFER_SIZE]; +// input->Read(buffer, BUFFER_SIZE); +// DoSomething(buffer, BUFFER_SIZE); +// Then, the stream basically just calls memcpy() to copy the data from +// the array into your buffer. With a ZeroCopyInputStream, you would do +// this instead: +// const void* buffer; +// int size; +// input->Next(&buffer, &size); +// DoSomething(buffer, size); +// Here, no copy is performed. The input stream returns a pointer directly +// into the backing array, and the caller ends up reading directly from it. +// +// If you want to be able to read the old-fashion way, you can create +// a CodedInputStream or CodedOutputStream wrapping these objects and use +// their ReadRaw()/WriteRaw() methods. These will, of course, add a copy +// step, but Coded*Stream will handle buffering so at least it will be +// reasonably efficient. +// +// ZeroCopyInputStream example: +// // Read in a file and print its contents to stdout. +// int fd = open("myfile", O_RDONLY); +// ZeroCopyInputStream* input = new FileInputStream(fd); +// +// const void* buffer; +// int size; +// while (input->Next(&buffer, &size)) { +// cout.write(buffer, size); +// } +// +// delete input; +// close(fd); +// +// ZeroCopyOutputStream example: +// // Copy the contents of "infile" to "outfile", using plain read() for +// // "infile" but a ZeroCopyOutputStream for "outfile". +// int infd = open("infile", O_RDONLY); +// int outfd = open("outfile", O_WRONLY); +// ZeroCopyOutputStream* output = new FileOutputStream(outfd); +// +// void* buffer; +// int size; +// while (output->Next(&buffer, &size)) { +// int bytes = read(infd, buffer, size); +// if (bytes < size) { +// // Reached EOF. +// output->BackUp(size - bytes); +// break; +// } +// } +// +// delete output; +// close(infd); +// close(outfd); + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ + +#include +#include + +namespace google { + +namespace protobuf { +namespace io { + +// Defined in this file. +class ZeroCopyInputStream; +class ZeroCopyOutputStream; + +// Abstract interface similar to an input stream but designed to minimize +// copying. +class LIBPROTOBUF_EXPORT ZeroCopyInputStream { + public: + inline ZeroCopyInputStream() {} + virtual ~ZeroCopyInputStream(); + + // Obtains a chunk of data from the stream. + // + // Preconditions: + // * "size" and "data" are not NULL. + // + // Postconditions: + // * If the returned value is false, there is no more data to return or + // an error occurred. All errors are permanent. + // * Otherwise, "size" points to the actual number of bytes read and "data" + // points to a pointer to a buffer containing these bytes. + // * Ownership of this buffer remains with the stream, and the buffer + // remains valid only until some other method of the stream is called + // or the stream is destroyed. + // * It is legal for the returned buffer to have zero size, as long + // as repeatedly calling Next() eventually yields a buffer with non-zero + // size. + virtual bool Next(const void** data, int* size) = 0; + + // Backs up a number of bytes, so that the next call to Next() returns + // data again that was already returned by the last call to Next(). This + // is useful when writing procedures that are only supposed to read up + // to a certain point in the input, then return. If Next() returns a + // buffer that goes beyond what you wanted to read, you can use BackUp() + // to return to the point where you intended to finish. + // + // Preconditions: + // * The last method called must have been Next(). + // * count must be less than or equal to the size of the last buffer + // returned by Next(). + // + // Postconditions: + // * The last "count" bytes of the last buffer returned by Next() will be + // pushed back into the stream. Subsequent calls to Next() will return + // the same data again before producing new data. + virtual void BackUp(int count) = 0; + + // Skips a number of bytes. Returns false if the end of the stream is + // reached or some input error occurred. In the end-of-stream case, the + // stream is advanced to the end of the stream (so ByteCount() will return + // the total size of the stream). + virtual bool Skip(int count) = 0; + + // Returns the total number of bytes read since this object was created. + virtual int64 ByteCount() const = 0; + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream); +}; + +// Abstract interface similar to an output stream but designed to minimize +// copying. +class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { + public: + inline ZeroCopyOutputStream() {} + virtual ~ZeroCopyOutputStream(); + + // Obtains a buffer into which data can be written. Any data written + // into this buffer will eventually (maybe instantly, maybe later on) + // be written to the output. + // + // Preconditions: + // * "size" and "data" are not NULL. + // + // Postconditions: + // * If the returned value is false, an error occurred. All errors are + // permanent. + // * Otherwise, "size" points to the actual number of bytes in the buffer + // and "data" points to the buffer. + // * Ownership of this buffer remains with the stream, and the buffer + // remains valid only until some other method of the stream is called + // or the stream is destroyed. + // * Any data which the caller stores in this buffer will eventually be + // written to the output (unless BackUp() is called). + // * It is legal for the returned buffer to have zero size, as long + // as repeatedly calling Next() eventually yields a buffer with non-zero + // size. + virtual bool Next(void** data, int* size) = 0; + + // Backs up a number of bytes, so that the end of the last buffer returned + // by Next() is not actually written. This is needed when you finish + // writing all the data you want to write, but the last buffer was bigger + // than you needed. You don't want to write a bunch of garbage after the + // end of your data, so you use BackUp() to back up. + // + // Preconditions: + // * The last method called must have been Next(). + // * count must be less than or equal to the size of the last buffer + // returned by Next(). + // * The caller must not have written anything to the last "count" bytes + // of that buffer. + // + // Postconditions: + // * The last "count" bytes of the last buffer returned by Next() will be + // ignored. + virtual void BackUp(int count) = 0; + + // Returns the total number of bytes written since this object was created. + virtual int64 ByteCount() const = 0; + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); +}; + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc new file mode 100644 index 000000000..9fcbb622a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -0,0 +1,471 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 _MSC_VER +#include +#else +#include +#include +#include +#include +#endif +#include +#include +#include + +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace io { + +#ifdef _WIN32 +// Win32 lseek is broken: If invoked on a non-seekable file descriptor, its +// return value is undefined. We re-define it to always produce an error. +#define lseek(fd, offset, origin) ((off_t)-1) +#endif + +namespace { + +// EINTR sucks. +int close_no_eintr(int fd) { + int result; + do { + result = close(fd); + } while (result < 0 && errno == EINTR); + return result; +} + +} // namespace + + +// =================================================================== + +FileInputStream::FileInputStream(int file_descriptor, int block_size) + : copying_input_(file_descriptor), + impl_(©ing_input_, block_size) { +} + +FileInputStream::~FileInputStream() {} + +bool FileInputStream::Close() { + return copying_input_.Close(); +} + +bool FileInputStream::Next(const void** data, int* size) { + return impl_.Next(data, size); +} + +void FileInputStream::BackUp(int count) { + impl_.BackUp(count); +} + +bool FileInputStream::Skip(int count) { + return impl_.Skip(count); +} + +int64 FileInputStream::ByteCount() const { + return impl_.ByteCount(); +} + +FileInputStream::CopyingFileInputStream::CopyingFileInputStream( + int file_descriptor) + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0), + previous_seek_failed_(false) { +} + +FileInputStream::CopyingFileInputStream::~CopyingFileInputStream() { + if (close_on_delete_) { + if (!Close()) { + GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_); + } + } +} + +bool FileInputStream::CopyingFileInputStream::Close() { + GOOGLE_CHECK(!is_closed_); + + is_closed_ = true; + if (close_no_eintr(file_) != 0) { + // The docs on close() do not specify whether a file descriptor is still + // open after close() fails with EIO. However, the glibc source code + // seems to indicate that it is not. + errno_ = errno; + return false; + } + + return true; +} + +int FileInputStream::CopyingFileInputStream::Read(void* buffer, int size) { + GOOGLE_CHECK(!is_closed_); + + int result; + do { + result = read(file_, buffer, size); + } while (result < 0 && errno == EINTR); + + if (result < 0) { + // Read error (not EOF). + errno_ = errno; + } + + return result; +} + +int FileInputStream::CopyingFileInputStream::Skip(int count) { + GOOGLE_CHECK(!is_closed_); + + if (!previous_seek_failed_ && + lseek(file_, count, SEEK_CUR) != (off_t)-1) { + // Seek succeeded. + return count; + } else { + // Failed to seek. + + // Note to self: Don't seek again. This file descriptor doesn't + // support it. + previous_seek_failed_ = true; + + // Use the default implementation. + return CopyingInputStream::Skip(count); + } +} + +// =================================================================== + +FileOutputStream::FileOutputStream(int file_descriptor, int block_size) + : copying_output_(file_descriptor), + impl_(©ing_output_, block_size) { +} + +FileOutputStream::~FileOutputStream() { + impl_.Flush(); +} + +bool FileOutputStream::Close() { + bool flush_succeeded = impl_.Flush(); + return copying_output_.Close() && flush_succeeded; +} + +bool FileOutputStream::Flush() { + return impl_.Flush(); +} + +bool FileOutputStream::Next(void** data, int* size) { + return impl_.Next(data, size); +} + +void FileOutputStream::BackUp(int count) { + impl_.BackUp(count); +} + +int64 FileOutputStream::ByteCount() const { + return impl_.ByteCount(); +} + +FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream( + int file_descriptor) + : file_(file_descriptor), + close_on_delete_(false), + is_closed_(false), + errno_(0) { +} + +FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() { + if (close_on_delete_) { + if (!Close()) { + GOOGLE_LOG(ERROR) << "close() failed: " << strerror(errno_); + } + } +} + +bool FileOutputStream::CopyingFileOutputStream::Close() { + GOOGLE_CHECK(!is_closed_); + + is_closed_ = true; + if (close_no_eintr(file_) != 0) { + // The docs on close() do not specify whether a file descriptor is still + // open after close() fails with EIO. However, the glibc source code + // seems to indicate that it is not. + errno_ = errno; + return false; + } + + return true; +} + +bool FileOutputStream::CopyingFileOutputStream::Write( + const void* buffer, int size) { + GOOGLE_CHECK(!is_closed_); + int total_written = 0; + + const uint8* buffer_base = reinterpret_cast(buffer); + + while (total_written < size) { + int bytes; + do { + bytes = write(file_, buffer_base + total_written, size - total_written); + } while (bytes < 0 && errno == EINTR); + + if (bytes <= 0) { + // Write error. + + // FIXME(kenton): According to the man page, if write() returns zero, + // there was no error; write() simply did not write anything. It's + // unclear under what circumstances this might happen, but presumably + // errno won't be set in this case. I am confused as to how such an + // event should be handled. For now I'm treating it as an error, since + // retrying seems like it could lead to an infinite loop. I suspect + // this never actually happens anyway. + + if (bytes < 0) { + errno_ = errno; + } + return false; + } + total_written += bytes; + } + + return true; +} + +// =================================================================== + +IstreamInputStream::IstreamInputStream(istream* input, int block_size) + : copying_input_(input), + impl_(©ing_input_, block_size) { +} + +IstreamInputStream::~IstreamInputStream() {} + +bool IstreamInputStream::Next(const void** data, int* size) { + return impl_.Next(data, size); +} + +void IstreamInputStream::BackUp(int count) { + impl_.BackUp(count); +} + +bool IstreamInputStream::Skip(int count) { + return impl_.Skip(count); +} + +int64 IstreamInputStream::ByteCount() const { + return impl_.ByteCount(); +} + +IstreamInputStream::CopyingIstreamInputStream::CopyingIstreamInputStream( + istream* input) + : input_(input) { +} + +IstreamInputStream::CopyingIstreamInputStream::~CopyingIstreamInputStream() {} + +int IstreamInputStream::CopyingIstreamInputStream::Read( + void* buffer, int size) { + input_->read(reinterpret_cast(buffer), size); + int result = input_->gcount(); + if (result == 0 && input_->fail() && !input_->eof()) { + return -1; + } + return result; +} + +// =================================================================== + +OstreamOutputStream::OstreamOutputStream(ostream* output, int block_size) + : copying_output_(output), + impl_(©ing_output_, block_size) { +} + +OstreamOutputStream::~OstreamOutputStream() { + impl_.Flush(); +} + +bool OstreamOutputStream::Next(void** data, int* size) { + return impl_.Next(data, size); +} + +void OstreamOutputStream::BackUp(int count) { + impl_.BackUp(count); +} + +int64 OstreamOutputStream::ByteCount() const { + return impl_.ByteCount(); +} + +OstreamOutputStream::CopyingOstreamOutputStream::CopyingOstreamOutputStream( + ostream* output) + : output_(output) { +} + +OstreamOutputStream::CopyingOstreamOutputStream::~CopyingOstreamOutputStream() { +} + +bool OstreamOutputStream::CopyingOstreamOutputStream::Write( + const void* buffer, int size) { + output_->write(reinterpret_cast(buffer), size); + return output_->good(); +} + +// =================================================================== + +ConcatenatingInputStream::ConcatenatingInputStream( + ZeroCopyInputStream* const streams[], int count) + : streams_(streams), stream_count_(count), bytes_retired_(0) { +} + +ConcatenatingInputStream::~ConcatenatingInputStream() { +} + +bool ConcatenatingInputStream::Next(const void** data, int* size) { + while (stream_count_ > 0) { + if (streams_[0]->Next(data, size)) return true; + + // That stream is done. Advance to the next one. + bytes_retired_ += streams_[0]->ByteCount(); + ++streams_; + --stream_count_; + } + + // No more streams. + return false; +} + +void ConcatenatingInputStream::BackUp(int count) { + if (stream_count_ > 0) { + streams_[0]->BackUp(count); + } else { + GOOGLE_LOG(DFATAL) << "Can't BackUp() after failed Next()."; + } +} + +bool ConcatenatingInputStream::Skip(int count) { + while (stream_count_ > 0) { + // Assume that ByteCount() can be used to find out how much we actually + // skipped when Skip() fails. + int64 target_byte_count = streams_[0]->ByteCount() + count; + if (streams_[0]->Skip(count)) return true; + + // Hit the end of the stream. Figure out how many more bytes we still have + // to skip. + int64 final_byte_count = streams_[0]->ByteCount(); + GOOGLE_DCHECK_LT(final_byte_count, target_byte_count); + count = target_byte_count - final_byte_count; + + // That stream is done. Advance to the next one. + bytes_retired_ += final_byte_count; + ++streams_; + --stream_count_; + } + + return false; +} + +int64 ConcatenatingInputStream::ByteCount() const { + if (stream_count_ == 0) { + return bytes_retired_; + } else { + return bytes_retired_ + streams_[0]->ByteCount(); + } +} + + +// =================================================================== + +LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, + int64 limit) + : input_(input), limit_(limit) {} + +LimitingInputStream::~LimitingInputStream() { + // If we overshot the limit, back up. + if (limit_ < 0) input_->BackUp(-limit_); +} + +bool LimitingInputStream::Next(const void** data, int* size) { + if (limit_ <= 0) return false; + if (!input_->Next(data, size)) return false; + + limit_ -= *size; + if (limit_ < 0) { + // We overshot the limit. Reduce *size to hide the rest of the buffer. + *size += limit_; + } + return true; +} + +void LimitingInputStream::BackUp(int count) { + if (limit_ < 0) { + input_->BackUp(count - limit_); + limit_ = count; + } else { + input_->BackUp(count); + limit_ += count; + } +} + +bool LimitingInputStream::Skip(int count) { + if (count > limit_) { + if (limit_ < 0) return false; + input_->Skip(limit_); + limit_ = 0; + return false; + } else { + if (!input_->Skip(count)) return false; + limit_ -= count; + return true; + } +} + +int64 LimitingInputStream::ByteCount() const { + if (limit_ < 0) { + return input_->ByteCount() + limit_; + } else { + return input_->ByteCount(); + } +} + + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h new file mode 100644 index 000000000..9fedb0057 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h @@ -0,0 +1,357 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains common implementations of the interfaces defined in +// zero_copy_stream.h which are only included in the full (non-lite) +// protobuf library. These implementations include Unix file descriptors +// and C++ iostreams. See also: zero_copy_stream_impl_lite.h + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ + +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace io { + + +// =================================================================== + +// A ZeroCopyInputStream which reads from a file descriptor. +// +// FileInputStream is preferred over using an ifstream with IstreamInputStream. +// The latter will introduce an extra layer of buffering, harming performance. +// Also, it's conceivable that FileInputStream could someday be enhanced +// to use zero-copy file descriptors on OSs which support them. +class LIBPROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given Unix file descriptor. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. + explicit FileInputStream(int file_descriptor, int block_size = -1); + ~FileInputStream(); + + // Flushes any buffers and closes the underlying file. Returns false if + // an error occurs during the process; use GetErrno() to examine the error. + // Even if an error occurs, the file descriptor is closed when this returns. + bool Close(); + + // By default, the file descriptor is not closed when the stream is + // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: + // This leaves no way for the caller to detect if close() fails. If + // detecting close() errors is important to you, you should arrange + // to close the descriptor yourself. + void SetCloseOnDelete(bool value) { copying_input_.SetCloseOnDelete(value); } + + // If an I/O error has occurred on this file descriptor, this is the + // errno from that error. Otherwise, this is zero. Once an error + // occurs, the stream is broken and all subsequent operations will + // fail. + int GetErrno() { return copying_input_.GetErrno(); } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + private: + class LIBPROTOBUF_EXPORT CopyingFileInputStream : public CopyingInputStream { + public: + CopyingFileInputStream(int file_descriptor); + ~CopyingFileInputStream(); + + bool Close(); + void SetCloseOnDelete(bool value) { close_on_delete_ = value; } + int GetErrno() { return errno_; } + + // implements CopyingInputStream --------------------------------- + int Read(void* buffer, int size); + int Skip(int count); + + private: + // The file descriptor. + const int file_; + bool close_on_delete_; + bool is_closed_; + + // The errno of the I/O error, if one has occurred. Otherwise, zero. + int errno_; + + // Did we try to seek once and fail? If so, we assume this file descriptor + // doesn't support seeking and won't try again. + bool previous_seek_failed_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream); + }; + + CopyingFileInputStream copying_input_; + CopyingInputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which writes to a file descriptor. +// +// FileOutputStream is preferred over using an ofstream with +// OstreamOutputStream. The latter will introduce an extra layer of buffering, +// harming performance. Also, it's conceivable that FileOutputStream could +// someday be enhanced to use zero-copy file descriptors on OSs which +// support them. +class LIBPROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given Unix file descriptor. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit FileOutputStream(int file_descriptor, int block_size = -1); + ~FileOutputStream(); + + // Flushes any buffers and closes the underlying file. Returns false if + // an error occurs during the process; use GetErrno() to examine the error. + // Even if an error occurs, the file descriptor is closed when this returns. + bool Close(); + + // Flushes FileOutputStream's buffers but does not close the + // underlying file. No special measures are taken to ensure that + // underlying operating system file object is synchronized to disk. + bool Flush(); + + // By default, the file descriptor is not closed when the stream is + // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: + // This leaves no way for the caller to detect if close() fails. If + // detecting close() errors is important to you, you should arrange + // to close the descriptor yourself. + void SetCloseOnDelete(bool value) { copying_output_.SetCloseOnDelete(value); } + + // If an I/O error has occurred on this file descriptor, this is the + // errno from that error. Otherwise, this is zero. Once an error + // occurs, the stream is broken and all subsequent operations will + // fail. + int GetErrno() { return copying_output_.GetErrno(); } + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + class LIBPROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { + public: + CopyingFileOutputStream(int file_descriptor); + ~CopyingFileOutputStream(); + + bool Close(); + void SetCloseOnDelete(bool value) { close_on_delete_ = value; } + int GetErrno() { return errno_; } + + // implements CopyingOutputStream -------------------------------- + bool Write(const void* buffer, int size); + + private: + // The file descriptor. + const int file_; + bool close_on_delete_; + bool is_closed_; + + // The errno of the I/O error, if one has occurred. Otherwise, zero. + int errno_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream); + }; + + CopyingFileOutputStream copying_output_; + CopyingOutputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream); +}; + +// =================================================================== + +// A ZeroCopyInputStream which reads from a C++ istream. +// +// Note that for reading files (or anything represented by a file descriptor), +// FileInputStream is more efficient. +class LIBPROTOBUF_EXPORT IstreamInputStream : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given C++ istream. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. + explicit IstreamInputStream(istream* stream, int block_size = -1); + ~IstreamInputStream(); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + private: + class LIBPROTOBUF_EXPORT CopyingIstreamInputStream : public CopyingInputStream { + public: + CopyingIstreamInputStream(istream* input); + ~CopyingIstreamInputStream(); + + // implements CopyingInputStream --------------------------------- + int Read(void* buffer, int size); + // (We use the default implementation of Skip().) + + private: + // The stream. + istream* input_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream); + }; + + CopyingIstreamInputStream copying_input_; + CopyingInputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which writes to a C++ ostream. +// +// Note that for writing files (or anything represented by a file descriptor), +// FileOutputStream is more efficient. +class LIBPROTOBUF_EXPORT OstreamOutputStream : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given C++ ostream. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit OstreamOutputStream(ostream* stream, int block_size = -1); + ~OstreamOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + class LIBPROTOBUF_EXPORT CopyingOstreamOutputStream : public CopyingOutputStream { + public: + CopyingOstreamOutputStream(ostream* output); + ~CopyingOstreamOutputStream(); + + // implements CopyingOutputStream -------------------------------- + bool Write(const void* buffer, int size); + + private: + // The stream. + ostream* output_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream); + }; + + CopyingOstreamOutputStream copying_output_; + CopyingOutputStreamAdaptor impl_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream); +}; + +// =================================================================== + +// A ZeroCopyInputStream which reads from several other streams in sequence. +// ConcatenatingInputStream is unable to distinguish between end-of-stream +// and read errors in the underlying streams, so it assumes any errors mean +// end-of-stream. So, if the underlying streams fail for any other reason, +// ConcatenatingInputStream may do odd things. It is suggested that you do +// not use ConcatenatingInputStream on streams that might produce read errors +// other than end-of-stream. +class LIBPROTOBUF_EXPORT ConcatenatingInputStream : public ZeroCopyInputStream { + public: + // All streams passed in as well as the array itself must remain valid + // until the ConcatenatingInputStream is destroyed. + ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count); + ~ConcatenatingInputStream(); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + + private: + // As streams are retired, streams_ is incremented and count_ is + // decremented. + ZeroCopyInputStream* const* streams_; + int stream_count_; + int64 bytes_retired_; // Bytes read from previous streams. + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream); +}; + +// =================================================================== + +// A ZeroCopyInputStream which wraps some other stream and limits it to +// a particular byte count. +class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { + public: + LimitingInputStream(ZeroCopyInputStream* input, int64 limit); + ~LimitingInputStream(); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + + private: + ZeroCopyInputStream* input_; + int64 limit_; // Decreases as we go, becomes negative if we overshoot. + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); +}; + +// =================================================================== + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc new file mode 100644 index 000000000..07b2b2bfc --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -0,0 +1,394 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 io { + +namespace { + +// Default block size for Copying{In,Out}putStreamAdaptor. +static const int kDefaultBlockSize = 8192; + +} // namespace + +// =================================================================== + +ArrayInputStream::ArrayInputStream(const void* data, int size, + int block_size) + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) { +} + +ArrayInputStream::~ArrayInputStream() { +} + +bool ArrayInputStream::Next(const void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = std::min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayInputStream::BackUp(int count) { + GOOGLE_CHECK_GT(last_returned_size_, 0) + << "BackUp() can only be called after a successful Next()."; + GOOGLE_CHECK_LE(count, last_returned_size_); + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ = 0; // Don't let caller back up further. +} + +bool ArrayInputStream::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + last_returned_size_ = 0; // Don't let caller back up. + if (count > size_ - position_) { + position_ = size_; + return false; + } else { + position_ += count; + return true; + } +} + +int64 ArrayInputStream::ByteCount() const { + return position_; +} + + +// =================================================================== + +ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size) + : data_(reinterpret_cast(data)), + size_(size), + block_size_(block_size > 0 ? block_size : size), + position_(0), + last_returned_size_(0) { +} + +ArrayOutputStream::~ArrayOutputStream() { +} + +bool ArrayOutputStream::Next(void** data, int* size) { + if (position_ < size_) { + last_returned_size_ = std::min(block_size_, size_ - position_); + *data = data_ + position_; + *size = last_returned_size_; + position_ += last_returned_size_; + return true; + } else { + // We're at the end of the array. + last_returned_size_ = 0; // Don't let caller back up. + return false; + } +} + +void ArrayOutputStream::BackUp(int count) { + GOOGLE_CHECK_GT(last_returned_size_, 0) + << "BackUp() can only be called after a successful Next()."; + GOOGLE_CHECK_LE(count, last_returned_size_); + GOOGLE_CHECK_GE(count, 0); + position_ -= count; + last_returned_size_ = 0; // Don't let caller back up further. +} + +int64 ArrayOutputStream::ByteCount() const { + return position_; +} + +// =================================================================== + +StringOutputStream::StringOutputStream(string* target) + : target_(target) { +} + +StringOutputStream::~StringOutputStream() { +} + +bool StringOutputStream::Next(void** data, int* size) { + int old_size = target_->size(); + + // Grow the string. + if (old_size < target_->capacity()) { + // Resize the string to match its capacity, since we can get away + // without a memory allocation this way. + STLStringResizeUninitialized(target_, target_->capacity()); + } else { + // Size has reached capacity, so double the size. Also make sure + // that the new size is at least kMinimumSize. + STLStringResizeUninitialized( + target_, + std::max(old_size * 2, + kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. + } + + *data = string_as_array(target_) + old_size; + *size = target_->size() - old_size; + return true; +} + +void StringOutputStream::BackUp(int count) { + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK_LE(count, target_->size()); + target_->resize(target_->size() - count); +} + +int64 StringOutputStream::ByteCount() const { + return target_->size(); +} + +// =================================================================== + +CopyingInputStream::~CopyingInputStream() {} + +int CopyingInputStream::Skip(int count) { + char junk[4096]; + int skipped = 0; + while (skipped < count) { + int bytes = Read(junk, std::min(count - skipped, + implicit_cast(sizeof(junk)))); + if (bytes <= 0) { + // EOF or read error. + return skipped; + } + skipped += bytes; + } + return skipped; +} + +CopyingInputStreamAdaptor::CopyingInputStreamAdaptor( + CopyingInputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0), + backup_bytes_(0) { +} + +CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() { + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingInputStreamAdaptor::Next(const void** data, int* size) { + if (failed_) { + // Already failed on a previous read. + return false; + } + + AllocateBufferIfNeeded(); + + if (backup_bytes_ > 0) { + // We have data left over from a previous BackUp(), so just return that. + *data = buffer_.get() + buffer_used_ - backup_bytes_; + *size = backup_bytes_; + backup_bytes_ = 0; + return true; + } + + // Read new data into the buffer. + buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_); + if (buffer_used_ <= 0) { + // EOF or read error. We don't need the buffer anymore. + if (buffer_used_ < 0) { + // Read error (not EOF). + failed_ = true; + } + FreeBuffer(); + return false; + } + position_ += buffer_used_; + + *size = buffer_used_; + *data = buffer_.get(); + return true; +} + +void CopyingInputStreamAdaptor::BackUp(int count) { + GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + GOOGLE_CHECK_GE(count, 0) + << " Parameter to BackUp() can't be negative."; + + backup_bytes_ = count; +} + +bool CopyingInputStreamAdaptor::Skip(int count) { + GOOGLE_CHECK_GE(count, 0); + + if (failed_) { + // Already failed on a previous read. + return false; + } + + // First skip any bytes left over from a previous BackUp(). + if (backup_bytes_ >= count) { + // We have more data left over than we're trying to skip. Just chop it. + backup_bytes_ -= count; + return true; + } + + count -= backup_bytes_; + backup_bytes_ = 0; + + int skipped = copying_stream_->Skip(count); + position_ += skipped; + return skipped == count; +} + +int64 CopyingInputStreamAdaptor::ByteCount() const { + return position_ - backup_bytes_; +} + +void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_.get() == NULL) { + buffer_.reset(new uint8[buffer_size_]); + } +} + +void CopyingInputStreamAdaptor::FreeBuffer() { + GOOGLE_CHECK_EQ(backup_bytes_, 0); + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +CopyingOutputStream::~CopyingOutputStream() {} + +CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor( + CopyingOutputStream* copying_stream, int block_size) + : copying_stream_(copying_stream), + owns_copying_stream_(false), + failed_(false), + position_(0), + buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize), + buffer_used_(0) { +} + +CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() { + WriteBuffer(); + if (owns_copying_stream_) { + delete copying_stream_; + } +} + +bool CopyingOutputStreamAdaptor::Flush() { + return WriteBuffer(); +} + +bool CopyingOutputStreamAdaptor::Next(void** data, int* size) { + if (buffer_used_ == buffer_size_) { + if (!WriteBuffer()) return false; + } + + AllocateBufferIfNeeded(); + + *data = buffer_.get() + buffer_used_; + *size = buffer_size_ - buffer_used_; + buffer_used_ = buffer_size_; + return true; +} + +void CopyingOutputStreamAdaptor::BackUp(int count) { + GOOGLE_CHECK_GE(count, 0); + GOOGLE_CHECK_EQ(buffer_used_, buffer_size_) + << " BackUp() can only be called after Next()."; + GOOGLE_CHECK_LE(count, buffer_used_) + << " Can't back up over more bytes than were returned by the last call" + " to Next()."; + + buffer_used_ -= count; +} + +int64 CopyingOutputStreamAdaptor::ByteCount() const { + return position_ + buffer_used_; +} + +bool CopyingOutputStreamAdaptor::WriteBuffer() { + if (failed_) { + // Already failed on a previous write. + return false; + } + + if (buffer_used_ == 0) return true; + + if (copying_stream_->Write(buffer_.get(), buffer_used_)) { + position_ += buffer_used_; + buffer_used_ = 0; + return true; + } else { + failed_ = true; + FreeBuffer(); + return false; + } +} + +void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() { + if (buffer_ == NULL) { + buffer_.reset(new uint8[buffer_size_]); + } +} + +void CopyingOutputStreamAdaptor::FreeBuffer() { + buffer_used_ = 0; + buffer_.reset(); +} + +// =================================================================== + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h new file mode 100644 index 000000000..153f543ee --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -0,0 +1,340 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 contains common implementations of the interfaces defined in +// zero_copy_stream.h which are included in the "lite" protobuf library. +// These implementations cover I/O on raw arrays and strings, as well as +// adaptors which make it easy to implement streams based on traditional +// streams. Of course, many users will probably want to write their own +// implementations of these interfaces specific to the particular I/O +// abstractions they prefer to use, but these should cover the most common +// cases. + +#ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ +#define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ + +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace io { + +// =================================================================== + +// A ZeroCopyInputStream backed by an in-memory array of bytes. +class LIBPROTOBUF_EXPORT ArrayInputStream : public ZeroCopyInputStream { + public: + // Create an InputStream that returns the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayInputStream(const void* data, int size, int block_size = -1); + ~ArrayInputStream(); + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + + private: + const uint8* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream backed by an in-memory array of bytes. +class LIBPROTOBUF_EXPORT ArrayOutputStream : public ZeroCopyOutputStream { + public: + // Create an OutputStream that writes to the bytes pointed to by "data". + // "data" remains the property of the caller but must remain valid until + // the stream is destroyed. If a block_size is given, calls to Next() + // will return data blocks no larger than the given size. Otherwise, the + // first call to Next() returns the entire array. block_size is mainly + // useful for testing; in production you would probably never want to set + // it. + ArrayOutputStream(void* data, int size, int block_size = -1); + ~ArrayOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + uint8* const data_; // The byte array. + const int size_; // Total size of the array. + const int block_size_; // How many bytes to return at a time. + + int position_; + int last_returned_size_; // How many bytes we returned last time Next() + // was called (used for error checking only). + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream); +}; + +// =================================================================== + +// A ZeroCopyOutputStream which appends bytes to a string. +class LIBPROTOBUF_EXPORT StringOutputStream : public ZeroCopyOutputStream { + public: + // Create a StringOutputStream which appends bytes to the given string. + // The string remains property of the caller, but it MUST NOT be accessed + // in any way until the stream is destroyed. + // + // Hint: If you call target->reserve(n) before creating the stream, + // the first call to Next() will return at least n bytes of buffer + // space. + explicit StringOutputStream(string* target); + ~StringOutputStream(); + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + static const int kMinimumSize = 16; + + string* target_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream); +}; + +// Note: There is no StringInputStream. Instead, just create an +// ArrayInputStream as follows: +// ArrayInputStream input(str.data(), str.size()); + +// =================================================================== + +// A generic traditional input stream interface. +// +// Lots of traditional input streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every read +// involves copying bytes into a buffer. If you want to take such an +// interface and make a ZeroCopyInputStream based on it, simply implement +// CopyingInputStream and then use CopyingInputStreamAdaptor. +// +// CopyingInputStream implementations should avoid buffering if possible. +// CopyingInputStreamAdaptor does its own buffering and will read data +// in large blocks. +class LIBPROTOBUF_EXPORT CopyingInputStream { + public: + virtual ~CopyingInputStream(); + + // Reads up to "size" bytes into the given buffer. Returns the number of + // bytes read. Read() waits until at least one byte is available, or + // returns zero if no bytes will ever become available (EOF), or -1 if a + // permanent read error occurred. + virtual int Read(void* buffer, int size) = 0; + + // Skips the next "count" bytes of input. Returns the number of bytes + // actually skipped. This will always be exactly equal to "count" unless + // EOF was reached or a permanent read error occurred. + // + // The default implementation just repeatedly calls Read() into a scratch + // buffer. + virtual int Skip(int count); +}; + +// A ZeroCopyInputStream which reads from a CopyingInputStream. This is +// useful for implementing ZeroCopyInputStreams that read from traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to read from file descriptors or C++ istreams, this is +// already implemented for you: use FileInputStream or IstreamInputStream +// respectively. +class LIBPROTOBUF_EXPORT CopyingInputStreamAdaptor : public ZeroCopyInputStream { + public: + // Creates a stream that reads from the given CopyingInputStream. + // If a block_size is given, it specifies the number of bytes that + // should be read and returned with each call to Next(). Otherwise, + // a reasonable default is used. The caller retains ownership of + // copying_stream unless SetOwnsCopyingStream(true) is called. + explicit CopyingInputStreamAdaptor(CopyingInputStream* copying_stream, + int block_size = -1); + ~CopyingInputStreamAdaptor(); + + // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to + // delete the underlying CopyingInputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyInputStream ---------------------------------- + bool Next(const void** data, int* size); + void BackUp(int count); + bool Skip(int count); + int64 ByteCount() const; + + private: + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer and resets buffer_used_. + void FreeBuffer(); + + // The underlying copying stream. + CopyingInputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permenant error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started reading. + int64 position_; + + // Data is read into this buffer. It may be NULL if no buffer is currently + // in use. Otherwise, it points to an array of size buffer_size_. + scoped_array buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + // Number of bytes in the buffer which were backed up over by a call to + // BackUp(). These need to be returned again. + // 0 <= backup_bytes_ <= buffer_used_ + int backup_bytes_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor); +}; + +// =================================================================== + +// A generic traditional output stream interface. +// +// Lots of traditional output streams (e.g. file descriptors, C stdio +// streams, and C++ iostreams) expose an interface where every write +// involves copying bytes from a buffer. If you want to take such an +// interface and make a ZeroCopyOutputStream based on it, simply implement +// CopyingOutputStream and then use CopyingOutputStreamAdaptor. +// +// CopyingOutputStream implementations should avoid buffering if possible. +// CopyingOutputStreamAdaptor does its own buffering and will write data +// in large blocks. +class LIBPROTOBUF_EXPORT CopyingOutputStream { + public: + virtual ~CopyingOutputStream(); + + // Writes "size" bytes from the given buffer to the output. Returns true + // if successful, false on a write error. + virtual bool Write(const void* buffer, int size) = 0; +}; + +// A ZeroCopyOutputStream which writes to a CopyingOutputStream. This is +// useful for implementing ZeroCopyOutputStreams that write to traditional +// streams. Note that this class is not really zero-copy. +// +// If you want to write to file descriptors or C++ ostreams, this is +// already implemented for you: use FileOutputStream or OstreamOutputStream +// respectively. +class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { + public: + // Creates a stream that writes to the given Unix file descriptor. + // If a block_size is given, it specifies the size of the buffers + // that should be returned by Next(). Otherwise, a reasonable default + // is used. + explicit CopyingOutputStreamAdaptor(CopyingOutputStream* copying_stream, + int block_size = -1); + ~CopyingOutputStreamAdaptor(); + + // Writes all pending data to the underlying stream. Returns false if a + // write error occurred on the underlying stream. (The underlying + // stream itself is not necessarily flushed.) + bool Flush(); + + // Call SetOwnsCopyingStream(true) to tell the CopyingOutputStreamAdaptor to + // delete the underlying CopyingOutputStream when it is destroyed. + void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; } + + // implements ZeroCopyOutputStream --------------------------------- + bool Next(void** data, int* size); + void BackUp(int count); + int64 ByteCount() const; + + private: + // Write the current buffer, if it is present. + bool WriteBuffer(); + // Insures that buffer_ is not NULL. + void AllocateBufferIfNeeded(); + // Frees the buffer. + void FreeBuffer(); + + // The underlying copying stream. + CopyingOutputStream* copying_stream_; + bool owns_copying_stream_; + + // True if we have seen a permenant error from the underlying stream. + bool failed_; + + // The current position of copying_stream_, relative to the point where + // we started writing. + int64 position_; + + // Data is written from this buffer. It may be NULL if no buffer is + // currently in use. Otherwise, it points to an array of size buffer_size_. + scoped_array buffer_; + const int buffer_size_; + + // Number of valid bytes currently in the buffer (i.e. the size last + // returned by Next()). When BackUp() is called, we just reduce this. + // 0 <= buffer_used_ <= buffer_size_. + int buffer_used_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor); +}; + +// =================================================================== + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc new file mode 100644 index 000000000..6f155df7e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -0,0 +1,944 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Testing strategy: For each type of I/O (array, string, file, etc.) we +// create an output stream and write some data to it, then create a +// corresponding input stream to read the same data back and expect it to +// match. When the data is written, it is written in several small chunks +// of varying sizes, with a BackUp() after each chunk. It is read back +// similarly, but with chunks separated at different points. The whole +// process is run with a variety of block sizes for both the input and +// the output. +// +// TODO(kenton): Rewrite this test to bring it up to the standards of all +// the other proto2 tests. May want to wait for gTest to implement +// "parametized tests" so that one set of tests can be used on all the +// implementations. + +#include "config.h" + +#ifdef _MSC_VER +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#if HAVE_ZLIB +#include +#endif + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { +namespace { + +#ifdef _WIN32 +#define pipe(fds) _pipe(fds, 4096, O_BINARY) +#endif + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#endif +#endif + +class IoTest : public testing::Test { + protected: + // Test helpers. + + // Helper to write an array of data to an output stream. + bool WriteToOutput(ZeroCopyOutputStream* output, const void* data, int size); + // Helper to read a fixed-length array of data from an input stream. + int ReadFromInput(ZeroCopyInputStream* input, void* data, int size); + // Write a string to the output stream. + void WriteString(ZeroCopyOutputStream* output, const string& str); + // Read a number of bytes equal to the size of the given string and checks + // that it matches the string. + void ReadString(ZeroCopyInputStream* input, const string& str); + // Writes some text to the output stream in a particular order. Returns + // the number of bytes written, incase the caller needs that to set up an + // input stream. + int WriteStuff(ZeroCopyOutputStream* output); + // Reads text from an input stream and expects it to match what + // WriteStuff() writes. + void ReadStuff(ZeroCopyInputStream* input); + + // Similar to WriteStuff, but performs more sophisticated testing. + int WriteStuffLarge(ZeroCopyOutputStream* output); + // Reads and tests a stream that should have been written to + // via WriteStuffLarge(). + void ReadStuffLarge(ZeroCopyInputStream* input); + +#if HAVE_ZLIB + string Compress(const string& data, const GzipOutputStream::Options& options); + string Uncompress(const string& data); +#endif + + static const int kBlockSizes[]; + static const int kBlockSizeCount; +}; + +const int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64}; +const int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes); + +bool IoTest::WriteToOutput(ZeroCopyOutputStream* output, + const void* data, int size) { + const uint8* in = reinterpret_cast(data); + int in_size = size; + + void* out; + int out_size; + + while (true) { + if (!output->Next(&out, &out_size)) { + return false; + } + EXPECT_GT(out_size, 0); + + if (in_size <= out_size) { + memcpy(out, in, in_size); + output->BackUp(out_size - in_size); + return true; + } + + memcpy(out, in, out_size); + in += out_size; + in_size -= out_size; + } +} + +#define MAX_REPEATED_ZEROS 100 + +int IoTest::ReadFromInput(ZeroCopyInputStream* input, void* data, int size) { + uint8* out = reinterpret_cast(data); + int out_size = size; + + const void* in; + int in_size = 0; + + int repeated_zeros = 0; + + while (true) { + if (!input->Next(&in, &in_size)) { + return size - out_size; + } + EXPECT_GT(in_size, -1); + if (in_size == 0) { + repeated_zeros++; + } else { + repeated_zeros = 0; + } + EXPECT_LT(repeated_zeros, MAX_REPEATED_ZEROS); + + if (out_size <= in_size) { + memcpy(out, in, out_size); + if (in_size > out_size) { + input->BackUp(in_size - out_size); + } + return size; // Copied all of it. + } + + memcpy(out, in, in_size); + out += in_size; + out_size -= in_size; + } +} + +void IoTest::WriteString(ZeroCopyOutputStream* output, const string& str) { + EXPECT_TRUE(WriteToOutput(output, str.c_str(), str.size())); +} + +void IoTest::ReadString(ZeroCopyInputStream* input, const string& str) { + scoped_array buffer(new char[str.size() + 1]); + buffer[str.size()] = '\0'; + EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size()); + EXPECT_STREQ(str.c_str(), buffer.get()); +} + +int IoTest::WriteStuff(ZeroCopyOutputStream* output) { + WriteString(output, "Hello world!\n"); + WriteString(output, "Some te"); + WriteString(output, "xt. Blah blah."); + WriteString(output, "abcdefg"); + WriteString(output, "01234567890123456789"); + WriteString(output, "foobar"); + + EXPECT_EQ(output->ByteCount(), 68); + + int result = output->ByteCount(); + return result; +} + +// Reads text from an input stream and expects it to match what WriteStuff() +// writes. +void IoTest::ReadStuff(ZeroCopyInputStream* input) { + ReadString(input, "Hello world!\n"); + ReadString(input, "Some text. "); + ReadString(input, "Blah "); + ReadString(input, "blah."); + ReadString(input, "abcdefg"); + EXPECT_TRUE(input->Skip(20)); + ReadString(input, "foo"); + ReadString(input, "bar"); + + EXPECT_EQ(input->ByteCount(), 68); + + uint8 byte; + EXPECT_EQ(ReadFromInput(input, &byte, 1), 0); +} + +int IoTest::WriteStuffLarge(ZeroCopyOutputStream* output) { + WriteString(output, "Hello world!\n"); + WriteString(output, "Some te"); + WriteString(output, "xt. Blah blah."); + WriteString(output, string(100000, 'x')); // A very long string + WriteString(output, string(100000, 'y')); // A very long string + WriteString(output, "01234567890123456789"); + + EXPECT_EQ(output->ByteCount(), 200055); + + int result = output->ByteCount(); + return result; +} + +// Reads text from an input stream and expects it to match what WriteStuff() +// writes. +void IoTest::ReadStuffLarge(ZeroCopyInputStream* input) { + ReadString(input, "Hello world!\nSome text. "); + EXPECT_TRUE(input->Skip(5)); + ReadString(input, "blah."); + EXPECT_TRUE(input->Skip(100000 - 10)); + ReadString(input, string(10, 'x') + string(100000 - 20000, 'y')); + EXPECT_TRUE(input->Skip(20000 - 10)); + ReadString(input, "yyyyyyyyyy01234567890123456789"); + + EXPECT_EQ(input->ByteCount(), 200055); + + uint8 byte; + EXPECT_EQ(ReadFromInput(input, &byte, 1), 0); +} + +// =================================================================== + +TEST_F(IoTest, ArrayIo) { + const int kBufferSize = 256; + uint8 buffer[kBufferSize]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + int size; + { + ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); + size = WriteStuff(&output); + } + { + ArrayInputStream input(buffer, size, kBlockSizes[j]); + ReadStuff(&input); + } + } + } +} + +TEST_F(IoTest, TwoSessionWrite) { + // Test that two concatenated write sessions read correctly + + static const char* strA = "0123456789"; + static const char* strB = "WhirledPeas"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + CodedOutputStream* coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strA)); + coded_output->WriteRaw(strA, strlen(strA)); + delete coded_output; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strB)); + coded_output->WriteRaw(strB, strlen(strB)); + delete coded_output; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + CodedInputStream* coded_input = new CodedInputStream(input); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)); + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)); + + delete coded_input; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} + +#if HAVE_ZLIB +TEST_F(IoTest, GzipIo) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + for (int z = 0; z < kBlockSizeCount; z++) { + int gzip_buffer_size = kBlockSizes[z]; + int size; + { + ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size, kBlockSizes[j]); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + } + } + } + } + delete [] buffer; +} + +TEST_F(IoTest, GzipIoWithFlush) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + // We start with i = 4 as we want a block size > 6. With block size <= 6 + // Flush() fills up the entire 2K buffer with flush markers and the test + // fails. See documentation for Flush() for more detail. + for (int i = 4; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + for (int z = 0; z < kBlockSizeCount; z++) { + int gzip_buffer_size = kBlockSizes[z]; + int size; + { + ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size, kBlockSizes[j]); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + } + } + } + } + delete [] buffer; +} + +TEST_F(IoTest, GzipIoContiguousFlushes) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + + int block_size = kBlockSizes[4]; + int gzip_buffer_size = block_size; + int size; + + ArrayOutputStream output(buffer, kBufferSize, block_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); + EXPECT_TRUE(gzout.Flush()); + gzout.Close(); + size = output.ByteCount(); + + ArrayInputStream input(buffer, size, block_size); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + + delete [] buffer; +} + +TEST_F(IoTest, GzipIoReadAfterFlush) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + + int block_size = kBlockSizes[4]; + int gzip_buffer_size = block_size; + int size; + ArrayOutputStream output(buffer, kBufferSize, block_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + EXPECT_TRUE(gzout.Flush()); + size = output.ByteCount(); + + ArrayInputStream input(buffer, size, block_size); + GzipInputStream gzin( + &input, GzipInputStream::GZIP, gzip_buffer_size); + ReadStuff(&gzin); + + gzout.Close(); + + delete [] buffer; +} + +TEST_F(IoTest, ZlibIo) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + for (int z = 0; z < kBlockSizeCount; z++) { + int gzip_buffer_size = kBlockSizes[z]; + int size; + { + ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size, kBlockSizes[j]); + GzipInputStream gzin( + &input, GzipInputStream::ZLIB, gzip_buffer_size); + ReadStuff(&gzin); + } + } + } + } + delete [] buffer; +} + +TEST_F(IoTest, ZlibIoInputAutodetect) { + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + int size; + { + ArrayOutputStream output(buffer, kBufferSize); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size); + GzipInputStream gzin(&input, GzipInputStream::AUTO); + ReadStuff(&gzin); + } + { + ArrayOutputStream output(buffer, kBufferSize); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + GzipOutputStream gzout(&output, options); + WriteStuff(&gzout); + gzout.Close(); + size = output.ByteCount(); + } + { + ArrayInputStream input(buffer, size); + GzipInputStream gzin(&input, GzipInputStream::AUTO); + ReadStuff(&gzin); + } + delete [] buffer; +} + +string IoTest::Compress(const string& data, + const GzipOutputStream::Options& options) { + string result; + { + StringOutputStream output(&result); + GzipOutputStream gzout(&output, options); + WriteToOutput(&gzout, data.data(), data.size()); + } + return result; +} + +string IoTest::Uncompress(const string& data) { + string result; + { + ArrayInputStream input(data.data(), data.size()); + GzipInputStream gzin(&input); + const void* buffer; + int size; + while (gzin.Next(&buffer, &size)) { + result.append(reinterpret_cast(buffer), size); + } + } + return result; +} + +TEST_F(IoTest, CompressionOptions) { + // Some ad-hoc testing of compression options. + + string golden; + File::ReadFileToStringOrDie( + TestSourceDir() + "/google/protobuf/testdata/golden_message", + &golden); + + GzipOutputStream::Options options; + string gzip_compressed = Compress(golden, options); + + options.compression_level = 0; + string not_compressed = Compress(golden, options); + + // Try zlib compression for fun. + options = GzipOutputStream::Options(); + options.format = GzipOutputStream::ZLIB; + string zlib_compressed = Compress(golden, options); + + // Uncompressed should be bigger than the original since it should have some + // sort of header. + EXPECT_GT(not_compressed.size(), golden.size()); + + // Higher compression levels should result in smaller sizes. + EXPECT_LT(zlib_compressed.size(), not_compressed.size()); + + // ZLIB format should differ from GZIP format. + EXPECT_TRUE(zlib_compressed != gzip_compressed); + + // Everything should decompress correctly. + EXPECT_TRUE(Uncompress(not_compressed) == golden); + EXPECT_TRUE(Uncompress(gzip_compressed) == golden); + EXPECT_TRUE(Uncompress(zlib_compressed) == golden); +} + +TEST_F(IoTest, TwoSessionWriteGzip) { + // Test that two concatenated gzip streams can be read correctly + + static const char* strA = "0123456789"; + static const char* strB = "QuickBrownFox"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream* gzout = new GzipOutputStream(output); + CodedOutputStream* coded_output = new CodedOutputStream(gzout); + int32 outlen = strlen(strA) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strA, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + gzout = new GzipOutputStream(output); + coded_output = new CodedOutputStream(gzout); + outlen = strlen(strB) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strB, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + GzipInputStream* gzin = new GzipInputStream(input); + CodedInputStream* coded_input = new CodedInputStream(gzin); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)) + << "strA=" << strA << " in=" << temp_buffer; + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)) + << " out_block_size=" << kBlockSizes[i] + << " in_block_size=" << kBlockSizes[j] + << " pos=" << pos + << " size=" << size + << " strB=" << strB << " in=" << temp_buffer; + + delete coded_input; + delete gzin; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} +#endif + +// There is no string input, only string output. Also, it doesn't support +// explicit block sizes. So, we'll only run one test and we'll use +// ArrayInput to read back the results. +TEST_F(IoTest, StringIo) { + string str; + { + StringOutputStream output(&str); + WriteStuff(&output); + } + { + ArrayInputStream input(str.data(), str.size()); + ReadStuff(&input); + } +} + + +// To test files, we create a temporary file, write, read, truncate, repeat. +TEST_F(IoTest, FileIo) { + string filename = TestTempDir() + "/zero_copy_stream_test_file"; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + // Make a temporary file. + int file = + open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); + ASSERT_GE(file, 0); + + { + FileOutputStream output(file, kBlockSizes[i]); + WriteStuff(&output); + EXPECT_EQ(0, output.GetErrno()); + } + + // Rewind. + ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1); + + { + FileInputStream input(file, kBlockSizes[j]); + ReadStuff(&input); + EXPECT_EQ(0, input.GetErrno()); + } + + close(file); + } + } +} + +#if HAVE_ZLIB +TEST_F(IoTest, GzipFileIo) { + string filename = TestTempDir() + "/zero_copy_stream_test_file"; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + // Make a temporary file. + int file = + open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0777); + ASSERT_GE(file, 0); + { + FileOutputStream output(file, kBlockSizes[i]); + GzipOutputStream gzout(&output); + WriteStuffLarge(&gzout); + gzout.Close(); + output.Flush(); + EXPECT_EQ(0, output.GetErrno()); + } + + // Rewind. + ASSERT_NE(lseek(file, 0, SEEK_SET), (off_t)-1); + + { + FileInputStream input(file, kBlockSizes[j]); + GzipInputStream gzin(&input); + ReadStuffLarge(&gzin); + EXPECT_EQ(0, input.GetErrno()); + } + + close(file); + } + } +} +#endif + +// MSVC raises various debugging exceptions if we try to use a file +// descriptor of -1, defeating our tests below. This class will disable +// these debug assertions while in scope. +class MsvcDebugDisabler { + public: +#if defined(_MSC_VER) && _MSC_VER >= 1400 + MsvcDebugDisabler() { + old_handler_ = _set_invalid_parameter_handler(MyHandler); + old_mode_ = _CrtSetReportMode(_CRT_ASSERT, 0); + } + ~MsvcDebugDisabler() { + old_handler_ = _set_invalid_parameter_handler(old_handler_); + old_mode_ = _CrtSetReportMode(_CRT_ASSERT, old_mode_); + } + + static void MyHandler(const wchar_t *expr, + const wchar_t *func, + const wchar_t *file, + unsigned int line, + uintptr_t pReserved) { + // do nothing + } + + _invalid_parameter_handler old_handler_; + int old_mode_; +#else + // Dummy constructor and destructor to ensure that GCC doesn't complain + // that debug_disabler is an unused variable. + MsvcDebugDisabler() {} + ~MsvcDebugDisabler() {} +#endif +}; + +// Test that FileInputStreams report errors correctly. +TEST_F(IoTest, FileReadError) { + MsvcDebugDisabler debug_disabler; + + // -1 = invalid file descriptor. + FileInputStream input(-1); + + const void* buffer; + int size; + EXPECT_FALSE(input.Next(&buffer, &size)); + EXPECT_EQ(EBADF, input.GetErrno()); +} + +// Test that FileOutputStreams report errors correctly. +TEST_F(IoTest, FileWriteError) { + MsvcDebugDisabler debug_disabler; + + // -1 = invalid file descriptor. + FileOutputStream input(-1); + + void* buffer; + int size; + + // The first call to Next() succeeds because it doesn't have anything to + // write yet. + EXPECT_TRUE(input.Next(&buffer, &size)); + + // Second call fails. + EXPECT_FALSE(input.Next(&buffer, &size)); + + EXPECT_EQ(EBADF, input.GetErrno()); +} + +// Pipes are not seekable, so File{Input,Output}Stream ends up doing some +// different things to handle them. We'll test by writing to a pipe and +// reading back from it. +TEST_F(IoTest, PipeIo) { + int files[2]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + // Need to create a new pipe each time because ReadStuff() expects + // to see EOF at the end. + ASSERT_EQ(pipe(files), 0); + + { + FileOutputStream output(files[1], kBlockSizes[i]); + WriteStuff(&output); + EXPECT_EQ(0, output.GetErrno()); + } + close(files[1]); // Send EOF. + + { + FileInputStream input(files[0], kBlockSizes[j]); + ReadStuff(&input); + EXPECT_EQ(0, input.GetErrno()); + } + close(files[0]); + } + } +} + +// Test using C++ iostreams. +TEST_F(IoTest, IostreamIo) { + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + { + stringstream stream; + + { + OstreamOutputStream output(&stream, kBlockSizes[i]); + WriteStuff(&output); + EXPECT_FALSE(stream.fail()); + } + + { + IstreamInputStream input(&stream, kBlockSizes[j]); + ReadStuff(&input); + EXPECT_TRUE(stream.eof()); + } + } + + { + stringstream stream; + + { + OstreamOutputStream output(&stream, kBlockSizes[i]); + WriteStuffLarge(&output); + EXPECT_FALSE(stream.fail()); + } + + { + IstreamInputStream input(&stream, kBlockSizes[j]); + ReadStuffLarge(&input); + EXPECT_TRUE(stream.eof()); + } + } + } + } +} + +// To test ConcatenatingInputStream, we create several ArrayInputStreams +// covering a buffer and then concatenate them. +TEST_F(IoTest, ConcatenatingInputStream) { + const int kBufferSize = 256; + uint8 buffer[kBufferSize]; + + // Fill the buffer. + ArrayOutputStream output(buffer, kBufferSize); + WriteStuff(&output); + + // Now split it up into multiple streams of varying sizes. + ASSERT_EQ(68, output.ByteCount()); // Test depends on this. + ArrayInputStream input1(buffer , 12); + ArrayInputStream input2(buffer + 12, 7); + ArrayInputStream input3(buffer + 19, 6); + ArrayInputStream input4(buffer + 25, 15); + ArrayInputStream input5(buffer + 40, 0); + // Note: We want to make sure we have a stream boundary somewhere between + // bytes 42 and 62, which is the range that it Skip()ed by ReadStuff(). This + // tests that a bug that existed in the original code for Skip() is fixed. + ArrayInputStream input6(buffer + 40, 10); + ArrayInputStream input7(buffer + 50, 18); // Total = 68 bytes. + + ZeroCopyInputStream* streams[] = + {&input1, &input2, &input3, &input4, &input5, &input6, &input7}; + + // Create the concatenating stream and read. + ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams)); + ReadStuff(&input); +} + +// To test LimitingInputStream, we write our golden text to a buffer, then +// create an ArrayInputStream that contains the whole buffer (not just the +// bytes written), then use a LimitingInputStream to limit it just to the +// bytes written. +TEST_F(IoTest, LimitingInputStream) { + const int kBufferSize = 256; + uint8 buffer[kBufferSize]; + + // Fill the buffer. + ArrayOutputStream output(buffer, kBufferSize); + WriteStuff(&output); + + // Set up input. + ArrayInputStream array_input(buffer, kBufferSize); + LimitingInputStream input(&array_input, output.ByteCount()); + + ReadStuff(&input); +} + +// Check that a zero-size array doesn't confuse the code. +TEST(ZeroSizeArray, Input) { + ArrayInputStream input(NULL, 0); + const void* data; + int size; + EXPECT_FALSE(input.Next(&data, &size)); +} + +TEST(ZeroSizeArray, Output) { + ArrayOutputStream output(NULL, 0); + void* data; + int size; + EXPECT_FALSE(output.Next(&data, &size)); +} + +} // namespace +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/lite_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/lite_unittest.cc new file mode 100644 index 000000000..7a0a57b77 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/lite_unittest.cc @@ -0,0 +1,185 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include + +#include +#include +#include + +using namespace std; + +namespace { +// Helper methods to test parsing merge behavior. +void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) { + GOOGLE_CHECK(message.optional_int32() == 3); + GOOGLE_CHECK(message.optional_int64() == 2); + GOOGLE_CHECK(message.optional_string() == "hello"); +} + +void AssignParsingMergeMessages( + google::protobuf::unittest::TestAllTypesLite* msg1, + google::protobuf::unittest::TestAllTypesLite* msg2, + google::protobuf::unittest::TestAllTypesLite* msg3) { + msg1->set_optional_int32(1); + msg2->set_optional_int64(2); + msg3->set_optional_int32(3); + msg3->set_optional_string("hello"); +} + +} // namespace + +int main(int argc, char* argv[]) { + string data, packed_data; + + { + protobuf_unittest::TestAllTypesLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + message2.CopyFrom(message); + data = message.SerializeAsString(); + message3.ParseFromString(data); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message3); + google::protobuf::TestUtilLite::ModifyRepeatedFields(&message); + google::protobuf::TestUtilLite::ExpectRepeatedFieldsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectClear(message); + } + + { + protobuf_unittest::TestAllExtensionsLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + google::protobuf::TestUtilLite::SetAllExtensions(&message); + message2.CopyFrom(message); + string extensions_data = message.SerializeAsString(); + GOOGLE_CHECK(extensions_data == data); + message3.ParseFromString(extensions_data); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message3); + google::protobuf::TestUtilLite::ModifyRepeatedExtensions(&message); + google::protobuf::TestUtilLite::ExpectRepeatedExtensionsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + } + + { + protobuf_unittest::TestPackedTypesLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectPackedClear(message); + google::protobuf::TestUtilLite::SetPackedFields(&message); + message2.CopyFrom(message); + packed_data = message.SerializeAsString(); + message3.ParseFromString(packed_data); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message3); + google::protobuf::TestUtilLite::ModifyPackedFields(&message); + google::protobuf::TestUtilLite::ExpectPackedFieldsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedClear(message); + } + + { + protobuf_unittest::TestPackedExtensionsLite message, message2, message3; + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + google::protobuf::TestUtilLite::SetPackedExtensions(&message); + message2.CopyFrom(message); + string packed_extensions_data = message.SerializeAsString(); + GOOGLE_CHECK(packed_extensions_data == packed_data); + message3.ParseFromString(packed_extensions_data); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message3); + google::protobuf::TestUtilLite::ModifyPackedExtensions(&message); + google::protobuf::TestUtilLite::ExpectPackedExtensionsModified(message); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + } + + { + // Test that if an optional or required message/group field appears multiple + // times in the input, they need to be merged. + google::protobuf::unittest::TestParsingMergeLite::RepeatedFieldsGenerator generator; + google::protobuf::unittest::TestAllTypesLite* msg1; + google::protobuf::unittest::TestAllTypesLite* msg2; + google::protobuf::unittest::TestAllTypesLite* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_FIELD(field1); + ASSIGN_REPEATED_FIELD(field2); + ASSIGN_REPEATED_FIELD(field3); + ASSIGN_REPEATED_FIELD(ext1); + ASSIGN_REPEATED_FIELD(ext2); + +#undef ASSIGN_REPEATED_FIELD +#define ASSIGN_REPEATED_GROUP(FIELD) \ + msg1 = generator.add_##FIELD()->mutable_field1(); \ + msg2 = generator.add_##FIELD()->mutable_field1(); \ + msg3 = generator.add_##FIELD()->mutable_field1(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_GROUP(group1); + ASSIGN_REPEATED_GROUP(group2); + +#undef ASSIGN_REPEATED_GROUP + + string buffer; + generator.SerializeToString(&buffer); + google::protobuf::unittest::TestParsingMergeLite parsing_merge; + parsing_merge.ParseFromString(buffer); + + // Required and optional fields should be merged. + ExpectMessageMerged(parsing_merge.required_all_types()); + ExpectMessageMerged(parsing_merge.optional_all_types()); + ExpectMessageMerged( + parsing_merge.optionalgroup().optional_group_all_types()); + ExpectMessageMerged(parsing_merge.GetExtension( + google::protobuf::unittest::TestParsingMergeLite::optional_ext)); + + // Repeated fields should not be merged. + GOOGLE_CHECK(parsing_merge.repeated_all_types_size() == 3); + GOOGLE_CHECK(parsing_merge.repeatedgroup_size() == 3); + GOOGLE_CHECK(parsing_merge.ExtensionSize( + google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3); + } + + cout << "PASS" << endl; + return 0; +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.cc new file mode 100644 index 000000000..ab7efa990 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.cc @@ -0,0 +1,358 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using internal::WireFormat; +using internal::ReflectionOps; + +Message::~Message() {} + +void Message::MergeFrom(const Message& from) { + const Descriptor* descriptor = GetDescriptor(); + GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) + << ": Tried to merge from a message with a different type. " + "to: " << descriptor->full_name() << ", " + "from:" << from.GetDescriptor()->full_name(); + ReflectionOps::Merge(from, this); +} + +void Message::CheckTypeAndMergeFrom(const MessageLite& other) { + MergeFrom(*down_cast(&other)); +} + +void Message::CopyFrom(const Message& from) { + const Descriptor* descriptor = GetDescriptor(); + GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) + << ": Tried to copy from a message with a different type." + "to: " << descriptor->full_name() << ", " + "from:" << from.GetDescriptor()->full_name(); + ReflectionOps::Copy(from, this); +} + +string Message::GetTypeName() const { + return GetDescriptor()->full_name(); +} + +void Message::Clear() { + ReflectionOps::Clear(this); +} + +bool Message::IsInitialized() const { + return ReflectionOps::IsInitialized(*this); +} + +void Message::FindInitializationErrors(vector* errors) const { + return ReflectionOps::FindInitializationErrors(*this, "", errors); +} + +string Message::InitializationErrorString() const { + vector errors; + FindInitializationErrors(&errors); + return JoinStrings(errors, ", "); +} + +void Message::CheckInitialized() const { + GOOGLE_CHECK(IsInitialized()) + << "Message of type \"" << GetDescriptor()->full_name() + << "\" is missing required fields: " << InitializationErrorString(); +} + +void Message::DiscardUnknownFields() { + return ReflectionOps::DiscardUnknownFields(this); +} + +bool Message::MergePartialFromCodedStream(io::CodedInputStream* input) { + return WireFormat::ParseAndMergePartial(input, this); +} + +bool Message::ParseFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParseFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool Message::ParsePartialFromFileDescriptor(int file_descriptor) { + io::FileInputStream input(file_descriptor); + return ParsePartialFromZeroCopyStream(&input) && input.GetErrno() == 0; +} + +bool Message::ParseFromIstream(istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParseFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + +bool Message::ParsePartialFromIstream(istream* input) { + io::IstreamInputStream zero_copy_input(input); + return ParsePartialFromZeroCopyStream(&zero_copy_input) && input->eof(); +} + + +void Message::SerializeWithCachedSizes( + io::CodedOutputStream* output) const { + WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output); +} + +int Message::ByteSize() const { + int size = WireFormat::ByteSize(*this); + SetCachedSize(size); + return size; +} + +void Message::SetCachedSize(int size) const { + GOOGLE_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name() + << "\" implements neither SetCachedSize() nor ByteSize(). " + "Must implement one or the other."; +} + +int Message::SpaceUsed() const { + return GetReflection()->SpaceUsed(*this); +} + +bool Message::SerializeToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializeToZeroCopyStream(&output); +} + +bool Message::SerializePartialToFileDescriptor(int file_descriptor) const { + io::FileOutputStream output(file_descriptor); + return SerializePartialToZeroCopyStream(&output); +} + +bool Message::SerializeToOstream(ostream* output) const { + { + io::OstreamOutputStream zero_copy_output(output); + if (!SerializeToZeroCopyStream(&zero_copy_output)) return false; + } + return output->good(); +} + +bool Message::SerializePartialToOstream(ostream* output) const { + io::OstreamOutputStream zero_copy_output(output); + return SerializePartialToZeroCopyStream(&zero_copy_output); +} + + +// ============================================================================= +// Reflection and associated Template Specializations + +Reflection::~Reflection() {} + +#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE) \ +template<> \ +const RepeatedField& Reflection::GetRepeatedField( \ + const Message& message, const FieldDescriptor* field) const { \ + return *static_cast* >( \ + MutableRawRepeatedField(const_cast(&message), \ + field, CPPTYPE, CTYPE, NULL)); \ +} \ + \ +template<> \ +RepeatedField* Reflection::MutableRepeatedField( \ + Message* message, const FieldDescriptor* field) const { \ + return static_cast* >( \ + MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \ +} + +HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1); +HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1); +HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1); +HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1); +HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1); +HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1); +HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); + + +#undef HANDLE_TYPE + +void* Reflection::MutableRawRepeatedString( + Message* message, const FieldDescriptor* field, bool is_string) const { + return MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL); +} + + +// ============================================================================= +// MessageFactory + +MessageFactory::~MessageFactory() {} + +namespace { + +class GeneratedMessageFactory : public MessageFactory { + public: + GeneratedMessageFactory(); + ~GeneratedMessageFactory(); + + static GeneratedMessageFactory* singleton(); + + typedef void RegistrationFunc(const string&); + void RegisterFile(const char* file, RegistrationFunc* registration_func); + void RegisterType(const Descriptor* descriptor, const Message* prototype); + + // implements MessageFactory --------------------------------------- + const Message* GetPrototype(const Descriptor* type); + + private: + // Only written at static init time, so does not require locking. + hash_map, streq> file_map_; + + // Initialized lazily, so requires locking. + Mutex mutex_; + hash_map type_map_; +}; + +GeneratedMessageFactory* generated_message_factory_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(generated_message_factory_once_init_); + +void ShutdownGeneratedMessageFactory() { + delete generated_message_factory_; +} + +void InitGeneratedMessageFactory() { + generated_message_factory_ = new GeneratedMessageFactory; + internal::OnShutdown(&ShutdownGeneratedMessageFactory); +} + +GeneratedMessageFactory::GeneratedMessageFactory() {} +GeneratedMessageFactory::~GeneratedMessageFactory() {} + +GeneratedMessageFactory* GeneratedMessageFactory::singleton() { + ::google::protobuf::GoogleOnceInit(&generated_message_factory_once_init_, + &InitGeneratedMessageFactory); + return generated_message_factory_; +} + +void GeneratedMessageFactory::RegisterFile( + const char* file, RegistrationFunc* registration_func) { + if (!InsertIfNotPresent(&file_map_, file, registration_func)) { + GOOGLE_LOG(FATAL) << "File is already registered: " << file; + } +} + +void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor, + const Message* prototype) { + GOOGLE_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool()) + << "Tried to register a non-generated type with the generated " + "type registry."; + + // This should only be called as a result of calling a file registration + // function during GetPrototype(), in which case we already have locked + // the mutex. + mutex_.AssertHeld(); + if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) { + GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name(); + } +} + + +const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) { + { + ReaderMutexLock lock(&mutex_); + const Message* result = FindPtrOrNull(type_map_, type); + if (result != NULL) return result; + } + + // If the type is not in the generated pool, then we can't possibly handle + // it. + if (type->file()->pool() != DescriptorPool::generated_pool()) return NULL; + + // Apparently the file hasn't been registered yet. Let's do that now. + RegistrationFunc* registration_func = + FindPtrOrNull(file_map_, type->file()->name().c_str()); + if (registration_func == NULL) { + GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't " + "registered: " << type->file()->name(); + return NULL; + } + + WriterMutexLock lock(&mutex_); + + // Check if another thread preempted us. + const Message* result = FindPtrOrNull(type_map_, type); + if (result == NULL) { + // Nope. OK, register everything. + registration_func(type->file()->name()); + // Should be here now. + result = FindPtrOrNull(type_map_, type); + } + + if (result == NULL) { + GOOGLE_LOG(DFATAL) << "Type appears to be in generated pool but wasn't " + << "registered: " << type->full_name(); + } + + return result; +} + +} // namespace + +MessageFactory* MessageFactory::generated_factory() { + return GeneratedMessageFactory::singleton(); +} + +void MessageFactory::InternalRegisterGeneratedFile( + const char* filename, void (*register_messages)(const string&)) { + GeneratedMessageFactory::singleton()->RegisterFile(filename, + register_messages); +} + +void MessageFactory::InternalRegisterGeneratedMessage( + const Descriptor* descriptor, const Message* prototype) { + GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype); +} + + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.h new file mode 100644 index 000000000..0f90bc1a1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message.h @@ -0,0 +1,837 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Defines Message, the abstract interface implemented by non-lite +// protocol message objects. Although it's possible to implement this +// interface manually, most users will use the protocol compiler to +// generate implementations. +// +// Example usage: +// +// Say you have a message defined as: +// +// message Foo { +// optional string text = 1; +// repeated int32 numbers = 2; +// } +// +// Then, if you used the protocol compiler to generate a class from the above +// definition, you could use it like so: +// +// string data; // Will store a serialized version of the message. +// +// { +// // Create a message and serialize it. +// Foo foo; +// foo.set_text("Hello World!"); +// foo.add_numbers(1); +// foo.add_numbers(5); +// foo.add_numbers(42); +// +// foo.SerializeToString(&data); +// } +// +// { +// // Parse the serialized message and check that it contains the +// // correct data. +// Foo foo; +// foo.ParseFromString(data); +// +// assert(foo.text() == "Hello World!"); +// assert(foo.numbers_size() == 3); +// assert(foo.numbers(0) == 1); +// assert(foo.numbers(1) == 5); +// assert(foo.numbers(2) == 42); +// } +// +// { +// // Same as the last block, but do it dynamically via the Message +// // reflection interface. +// Message* foo = new Foo; +// const Descriptor* descriptor = foo->GetDescriptor(); +// +// // Get the descriptors for the fields we're interested in and verify +// // their types. +// const FieldDescriptor* text_field = descriptor->FindFieldByName("text"); +// assert(text_field != NULL); +// assert(text_field->type() == FieldDescriptor::TYPE_STRING); +// assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL); +// const FieldDescriptor* numbers_field = descriptor-> +// FindFieldByName("numbers"); +// assert(numbers_field != NULL); +// assert(numbers_field->type() == FieldDescriptor::TYPE_INT32); +// assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED); +// +// // Parse the message. +// foo->ParseFromString(data); +// +// // Use the reflection interface to examine the contents. +// const Reflection* reflection = foo->GetReflection(); +// assert(reflection->GetString(foo, text_field) == "Hello World!"); +// assert(reflection->FieldSize(foo, numbers_field) == 3); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5); +// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42); +// +// delete foo; +// } + +#ifndef GOOGLE_PROTOBUF_MESSAGE_H__ +#define GOOGLE_PROTOBUF_MESSAGE_H__ + +#include +#include + +#ifdef __DECCXX +// HP C++'s iosfwd doesn't work. +#include +#else +#include +#endif + +#include + +#include +#include + + +namespace google { +namespace protobuf { + +// Defined in this file. +class Message; +class Reflection; +class MessageFactory; + +// Defined in other files. +class UnknownFieldSet; // unknown_field_set.h +namespace io { + class ZeroCopyInputStream; // zero_copy_stream.h + class ZeroCopyOutputStream; // zero_copy_stream.h + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h +} + + +template +class RepeatedField; // repeated_field.h + +template +class RepeatedPtrField; // repeated_field.h + +// A container to hold message metadata. +struct Metadata { + const Descriptor* descriptor; + const Reflection* reflection; +}; + +// Abstract interface for protocol messages. +// +// See also MessageLite, which contains most every-day operations. Message +// adds descriptors and reflection on top of that. +// +// The methods of this class that are virtual but not pure-virtual have +// default implementations based on reflection. Message classes which are +// optimized for speed will want to override these with faster implementations, +// but classes optimized for code size may be happy with keeping them. See +// the optimize_for option in descriptor.proto. +class LIBPROTOBUF_EXPORT Message : public MessageLite { + public: + inline Message() {} + virtual ~Message(); + + // Basic Operations ------------------------------------------------ + + // Construct a new instance of the same type. Ownership is passed to the + // caller. (This is also defined in MessageLite, but is defined again here + // for return-type covariance.) + virtual Message* New() const = 0; + + // Make this message into a copy of the given message. The given message + // must have the same descriptor, but need not necessarily be the same class. + // By default this is just implemented as "Clear(); MergeFrom(from);". + virtual void CopyFrom(const Message& from); + + // Merge the fields from the given message into this message. Singular + // fields will be overwritten, except for embedded messages which will + // be merged. Repeated fields will be concatenated. The given message + // must be of the same type as this message (i.e. the exact same class). + virtual void MergeFrom(const Message& from); + + // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with + // a nice error message. + void CheckInitialized() const; + + // Slowly build a list of all required fields that are not set. + // This is much, much slower than IsInitialized() as it is implemented + // purely via reflection. Generally, you should not call this unless you + // have already determined that an error exists by calling IsInitialized(). + void FindInitializationErrors(vector* errors) const; + + // Like FindInitializationErrors, but joins all the strings, delimited by + // commas, and returns them. + string InitializationErrorString() const; + + // Clears all unknown fields from this message and all embedded messages. + // Normally, if unknown tag numbers are encountered when parsing a message, + // the tag and value are stored in the message's UnknownFieldSet and + // then written back out when the message is serialized. This allows servers + // which simply route messages to other servers to pass through messages + // that have new field definitions which they don't yet know about. However, + // this behavior can have security implications. To avoid it, call this + // method after parsing. + // + // See Reflection::GetUnknownFields() for more on unknown fields. + virtual void DiscardUnknownFields(); + + // Computes (an estimate of) the total number of bytes currently used for + // storing the message in memory. The default implementation calls the + // Reflection object's SpaceUsed() method. + virtual int SpaceUsed() const; + + // Debugging & Testing---------------------------------------------- + + // Generates a human readable form of this message, useful for debugging + // and other purposes. + string DebugString() const; + // Like DebugString(), but with less whitespace. + string ShortDebugString() const; + // Like DebugString(), but do not escape UTF-8 byte sequences. + string Utf8DebugString() const; + // Convenience function useful in GDB. Prints DebugString() to stdout. + void PrintDebugString() const; + + // Heavy I/O ------------------------------------------------------- + // Additional parsing and serialization methods not implemented by + // MessageLite because they are not supported by the lite library. + + // Parse a protocol buffer from a file descriptor. If successful, the entire + // input will be consumed. + bool ParseFromFileDescriptor(int file_descriptor); + // Like ParseFromFileDescriptor(), but accepts messages that are missing + // required fields. + bool ParsePartialFromFileDescriptor(int file_descriptor); + // Parse a protocol buffer from a C++ istream. If successful, the entire + // input will be consumed. + bool ParseFromIstream(istream* input); + // Like ParseFromIstream(), but accepts messages that are missing + // required fields. + bool ParsePartialFromIstream(istream* input); + + // Serialize the message and write it to the given file descriptor. All + // required fields must be set. + bool SerializeToFileDescriptor(int file_descriptor) const; + // Like SerializeToFileDescriptor(), but allows missing required fields. + bool SerializePartialToFileDescriptor(int file_descriptor) const; + // Serialize the message and write it to the given C++ ostream. All + // required fields must be set. + bool SerializeToOstream(ostream* output) const; + // Like SerializeToOstream(), but allows missing required fields. + bool SerializePartialToOstream(ostream* output) const; + + + // Reflection-based methods ---------------------------------------- + // These methods are pure-virtual in MessageLite, but Message provides + // reflection-based default implementations. + + virtual string GetTypeName() const; + virtual void Clear(); + virtual bool IsInitialized() const; + virtual void CheckTypeAndMergeFrom(const MessageLite& other); + virtual bool MergePartialFromCodedStream(io::CodedInputStream* input); + virtual int ByteSize() const; + virtual void SerializeWithCachedSizes(io::CodedOutputStream* output) const; + + private: + // This is called only by the default implementation of ByteSize(), to + // update the cached size. If you override ByteSize(), you do not need + // to override this. If you do not override ByteSize(), you MUST override + // this; the default implementation will crash. + // + // The method is private because subclasses should never call it; only + // override it. Yes, C++ lets you do that. Crazy, huh? + virtual void SetCachedSize(int size) const; + + public: + + // Introspection --------------------------------------------------- + + // Typedef for backwards-compatibility. + typedef google::protobuf::Reflection Reflection; + + // Get a Descriptor for this message's type. This describes what + // fields the message contains, the types of those fields, etc. + const Descriptor* GetDescriptor() const { return GetMetadata().descriptor; } + + // Get the Reflection interface for this Message, which can be used to + // read and modify the fields of the Message dynamically (in other words, + // without knowing the message type at compile time). This object remains + // property of the Message. + // + // This method remains virtual in case a subclass does not implement + // reflection and wants to override the default behavior. + virtual const Reflection* GetReflection() const { + return GetMetadata().reflection; + } + + protected: + // Get a struct containing the metadata for the Message. Most subclasses only + // need to implement this method, rather than the GetDescriptor() and + // GetReflection() wrappers. + virtual Metadata GetMetadata() const = 0; + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); +}; + +// This interface contains methods that can be used to dynamically access +// and modify the fields of a protocol message. Their semantics are +// similar to the accessors the protocol compiler generates. +// +// To get the Reflection for a given Message, call Message::GetReflection(). +// +// This interface is separate from Message only for efficiency reasons; +// the vast majority of implementations of Message will share the same +// implementation of Reflection (GeneratedMessageReflection, +// defined in generated_message.h), and all Messages of a particular class +// should share the same Reflection object (though you should not rely on +// the latter fact). +// +// There are several ways that these methods can be used incorrectly. For +// example, any of the following conditions will lead to undefined +// results (probably assertion failures): +// - The FieldDescriptor is not a field of this message type. +// - The method called is not appropriate for the field's type. For +// each field type in FieldDescriptor::TYPE_*, there is only one +// Get*() method, one Set*() method, and one Add*() method that is +// valid for that type. It should be obvious which (except maybe +// for TYPE_BYTES, which are represented using strings in C++). +// - A Get*() or Set*() method for singular fields is called on a repeated +// field. +// - GetRepeated*(), SetRepeated*(), or Add*() is called on a non-repeated +// field. +// - The Message object passed to any method is not of the right type for +// this Reflection object (i.e. message.GetReflection() != reflection). +// +// You might wonder why there is not any abstract representation for a field +// of arbitrary type. E.g., why isn't there just a "GetField()" method that +// returns "const Field&", where "Field" is some class with accessors like +// "GetInt32Value()". The problem is that someone would have to deal with +// allocating these Field objects. For generated message classes, having to +// allocate space for an additional object to wrap every field would at least +// double the message's memory footprint, probably worse. Allocating the +// objects on-demand, on the other hand, would be expensive and prone to +// memory leaks. So, instead we ended up with this flat interface. +// +// TODO(kenton): Create a utility class which callers can use to read and +// write fields from a Reflection without paying attention to the type. +class LIBPROTOBUF_EXPORT Reflection { + public: + inline Reflection() {} + virtual ~Reflection(); + + // Get the UnknownFieldSet for the message. This contains fields which + // were seen when the Message was parsed but were not recognized according + // to the Message's definition. + virtual const UnknownFieldSet& GetUnknownFields( + const Message& message) const = 0; + // Get a mutable pointer to the UnknownFieldSet for the message. This + // contains fields which were seen when the Message was parsed but were not + // recognized according to the Message's definition. + virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0; + + // Estimate the amount of memory used by the message object. + virtual int SpaceUsed(const Message& message) const = 0; + + // Check if the given non-repeated field is set. + virtual bool HasField(const Message& message, + const FieldDescriptor* field) const = 0; + + // Get the number of elements of a repeated field. + virtual int FieldSize(const Message& message, + const FieldDescriptor* field) const = 0; + + // Clear the value of a field, so that HasField() returns false or + // FieldSize() returns zero. + virtual void ClearField(Message* message, + const FieldDescriptor* field) const = 0; + + // Removes the last element of a repeated field. + // We don't provide a way to remove any element other than the last + // because it invites inefficient use, such as O(n^2) filtering loops + // that should have been O(n). If you want to remove an element other + // than the last, the best way to do it is to re-arrange the elements + // (using Swap()) so that the one you want removed is at the end, then + // call RemoveLast(). + virtual void RemoveLast(Message* message, + const FieldDescriptor* field) const = 0; + // Removes the last element of a repeated message field, and returns the + // pointer to the caller. Caller takes ownership of the returned pointer. + virtual Message* ReleaseLast(Message* message, + const FieldDescriptor* field) const = 0; + + // Swap the complete contents of two messages. + virtual void Swap(Message* message1, Message* message2) const = 0; + + // Swap two elements of a repeated field. + virtual void SwapElements(Message* message, + const FieldDescriptor* field, + int index1, + int index2) const = 0; + + // List all fields of the message which are currently set. This includes + // extensions. Singular fields will only be listed if HasField(field) would + // return true and repeated fields will only be listed if FieldSize(field) + // would return non-zero. Fields (both normal fields and extension fields) + // will be listed ordered by field number. + virtual void ListFields(const Message& message, + vector* output) const = 0; + + // Singular field getters ------------------------------------------ + // These get the value of a non-repeated field. They return the default + // value for fields that aren't set. + + virtual int32 GetInt32 (const Message& message, + const FieldDescriptor* field) const = 0; + virtual int64 GetInt64 (const Message& message, + const FieldDescriptor* field) const = 0; + virtual uint32 GetUInt32(const Message& message, + const FieldDescriptor* field) const = 0; + virtual uint64 GetUInt64(const Message& message, + const FieldDescriptor* field) const = 0; + virtual float GetFloat (const Message& message, + const FieldDescriptor* field) const = 0; + virtual double GetDouble(const Message& message, + const FieldDescriptor* field) const = 0; + virtual bool GetBool (const Message& message, + const FieldDescriptor* field) const = 0; + virtual string GetString(const Message& message, + const FieldDescriptor* field) const = 0; + virtual const EnumValueDescriptor* GetEnum( + const Message& message, const FieldDescriptor* field) const = 0; + // See MutableMessage() for the meaning of the "factory" parameter. + virtual const Message& GetMessage(const Message& message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; + + // Get a string value without copying, if possible. + // + // GetString() necessarily returns a copy of the string. This can be + // inefficient when the string is already stored in a string object in the + // underlying message. GetStringReference() will return a reference to the + // underlying string in this case. Otherwise, it will copy the string into + // *scratch and return that. + // + // Note: It is perfectly reasonable and useful to write code like: + // str = reflection->GetStringReference(field, &str); + // This line would ensure that only one copy of the string is made + // regardless of the field's underlying representation. When initializing + // a newly-constructed string, though, it's just as fast and more readable + // to use code like: + // string str = reflection->GetString(field); + virtual const string& GetStringReference(const Message& message, + const FieldDescriptor* field, + string* scratch) const = 0; + + + // Singular field mutators ----------------------------------------- + // These mutate the value of a non-repeated field. + + virtual void SetInt32 (Message* message, + const FieldDescriptor* field, int32 value) const = 0; + virtual void SetInt64 (Message* message, + const FieldDescriptor* field, int64 value) const = 0; + virtual void SetUInt32(Message* message, + const FieldDescriptor* field, uint32 value) const = 0; + virtual void SetUInt64(Message* message, + const FieldDescriptor* field, uint64 value) const = 0; + virtual void SetFloat (Message* message, + const FieldDescriptor* field, float value) const = 0; + virtual void SetDouble(Message* message, + const FieldDescriptor* field, double value) const = 0; + virtual void SetBool (Message* message, + const FieldDescriptor* field, bool value) const = 0; + virtual void SetString(Message* message, + const FieldDescriptor* field, + const string& value) const = 0; + virtual void SetEnum (Message* message, + const FieldDescriptor* field, + const EnumValueDescriptor* value) const = 0; + // Get a mutable pointer to a field with a message type. If a MessageFactory + // is provided, it will be used to construct instances of the sub-message; + // otherwise, the default factory is used. If the field is an extension that + // does not live in the same pool as the containing message's descriptor (e.g. + // it lives in an overlay pool), then a MessageFactory must be provided. + // If you have no idea what that meant, then you probably don't need to worry + // about it (don't provide a MessageFactory). WARNING: If the + // FieldDescriptor is for a compiled-in extension, then + // factory->GetPrototype(field->message_type() MUST return an instance of the + // compiled-in class for this type, NOT DynamicMessage. + virtual Message* MutableMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; + // Releases the message specified by 'field' and returns the pointer, + // ReleaseMessage() will return the message the message object if it exists. + // Otherwise, it may or may not return NULL. In any case, if the return value + // is non-NULL, the caller takes ownership of the pointer. + // If the field existed (HasField() is true), then the returned pointer will + // be the same as the pointer returned by MutableMessage(). + // This function has the same effect as ClearField(). + virtual Message* ReleaseMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; + + + // Repeated field getters ------------------------------------------ + // These get the value of one element of a repeated field. + + virtual int32 GetRepeatedInt32 (const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual int64 GetRepeatedInt64 (const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual uint32 GetRepeatedUInt32(const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual uint64 GetRepeatedUInt64(const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual float GetRepeatedFloat (const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual double GetRepeatedDouble(const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual bool GetRepeatedBool (const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual string GetRepeatedString(const Message& message, + const FieldDescriptor* field, + int index) const = 0; + virtual const EnumValueDescriptor* GetRepeatedEnum( + const Message& message, + const FieldDescriptor* field, int index) const = 0; + virtual const Message& GetRepeatedMessage( + const Message& message, + const FieldDescriptor* field, int index) const = 0; + + // See GetStringReference(), above. + virtual const string& GetRepeatedStringReference( + const Message& message, const FieldDescriptor* field, + int index, string* scratch) const = 0; + + + // Repeated field mutators ----------------------------------------- + // These mutate the value of one element of a repeated field. + + virtual void SetRepeatedInt32 (Message* message, + const FieldDescriptor* field, + int index, int32 value) const = 0; + virtual void SetRepeatedInt64 (Message* message, + const FieldDescriptor* field, + int index, int64 value) const = 0; + virtual void SetRepeatedUInt32(Message* message, + const FieldDescriptor* field, + int index, uint32 value) const = 0; + virtual void SetRepeatedUInt64(Message* message, + const FieldDescriptor* field, + int index, uint64 value) const = 0; + virtual void SetRepeatedFloat (Message* message, + const FieldDescriptor* field, + int index, float value) const = 0; + virtual void SetRepeatedDouble(Message* message, + const FieldDescriptor* field, + int index, double value) const = 0; + virtual void SetRepeatedBool (Message* message, + const FieldDescriptor* field, + int index, bool value) const = 0; + virtual void SetRepeatedString(Message* message, + const FieldDescriptor* field, + int index, const string& value) const = 0; + virtual void SetRepeatedEnum(Message* message, + const FieldDescriptor* field, int index, + const EnumValueDescriptor* value) const = 0; + // Get a mutable pointer to an element of a repeated field with a message + // type. + virtual Message* MutableRepeatedMessage( + Message* message, const FieldDescriptor* field, int index) const = 0; + + + // Repeated field adders ------------------------------------------- + // These add an element to a repeated field. + + virtual void AddInt32 (Message* message, + const FieldDescriptor* field, int32 value) const = 0; + virtual void AddInt64 (Message* message, + const FieldDescriptor* field, int64 value) const = 0; + virtual void AddUInt32(Message* message, + const FieldDescriptor* field, uint32 value) const = 0; + virtual void AddUInt64(Message* message, + const FieldDescriptor* field, uint64 value) const = 0; + virtual void AddFloat (Message* message, + const FieldDescriptor* field, float value) const = 0; + virtual void AddDouble(Message* message, + const FieldDescriptor* field, double value) const = 0; + virtual void AddBool (Message* message, + const FieldDescriptor* field, bool value) const = 0; + virtual void AddString(Message* message, + const FieldDescriptor* field, + const string& value) const = 0; + virtual void AddEnum (Message* message, + const FieldDescriptor* field, + const EnumValueDescriptor* value) const = 0; + // See MutableMessage() for comments on the "factory" parameter. + virtual Message* AddMessage(Message* message, + const FieldDescriptor* field, + MessageFactory* factory = NULL) const = 0; + + + // Repeated field accessors ------------------------------------------------- + // The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular + // access to the data in a RepeatedField. The methods below provide aggregate + // access by exposing the RepeatedField object itself with the Message. + // Applying these templates to inappropriate types will lead to an undefined + // reference at link time (e.g. GetRepeatedField<***double>), or possibly a + // template matching error at compile time (e.g. GetRepeatedPtrField). + // + // Usage example: my_doubs = refl->GetRepeatedField(msg, fd); + + // for T = Cord and all protobuf scalar types except enums. + template + const RepeatedField& GetRepeatedField( + const Message&, const FieldDescriptor*) const; + + // for T = Cord and all protobuf scalar types except enums. + template + RepeatedField* MutableRepeatedField( + Message*, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template + const RepeatedPtrField& GetRepeatedPtrField( + const Message&, const FieldDescriptor*) const; + + // for T = string, google::protobuf::internal::StringPieceField + // google::protobuf::Message & descendants. + template + RepeatedPtrField* MutableRepeatedPtrField( + Message*, const FieldDescriptor*) const; + + // Extensions ---------------------------------------------------------------- + + // Try to find an extension of this message type by fully-qualified field + // name. Returns NULL if no extension is known for this name or number. + virtual const FieldDescriptor* FindKnownExtensionByName( + const string& name) const = 0; + + // Try to find an extension of this message type by field number. + // Returns NULL if no extension is known for this name or number. + virtual const FieldDescriptor* FindKnownExtensionByNumber( + int number) const = 0; + + // --------------------------------------------------------------------------- + + protected: + // Obtain a pointer to a Repeated Field Structure and do some type checking: + // on field->cpp_type(), + // on field->field_option().ctype() (if ctype >= 0) + // of field->message_type() (if message_type != NULL). + // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer). + virtual void* MutableRawRepeatedField( + Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, + int ctype, const Descriptor* message_type) const = 0; + + private: + // Special version for specialized implementations of string. We can't call + // MutableRawRepeatedField directly here because we don't have access to + // FieldOptions::* which are defined in descriptor.pb.h. Including that + // file here is not possible because it would cause a circular include cycle. + void* MutableRawRepeatedString( + Message* message, const FieldDescriptor* field, bool is_string) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection); +}; + +// Abstract interface for a factory for message objects. +class LIBPROTOBUF_EXPORT MessageFactory { + public: + inline MessageFactory() {} + virtual ~MessageFactory(); + + // Given a Descriptor, gets or constructs the default (prototype) Message + // of that type. You can then call that message's New() method to construct + // a mutable message of that type. + // + // Calling this method twice with the same Descriptor returns the same + // object. The returned object remains property of the factory. Also, any + // objects created by calling the prototype's New() method share some data + // with the prototype, so these must be destoyed before the MessageFactory + // is destroyed. + // + // The given descriptor must outlive the returned message, and hence must + // outlive the MessageFactory. + // + // Some implementations do not support all types. GetPrototype() will + // return NULL if the descriptor passed in is not supported. + // + // This method may or may not be thread-safe depending on the implementation. + // Each implementation should document its own degree thread-safety. + virtual const Message* GetPrototype(const Descriptor* type) = 0; + + // Gets a MessageFactory which supports all generated, compiled-in messages. + // In other words, for any compiled-in type FooMessage, the following is true: + // MessageFactory::generated_factory()->GetPrototype( + // FooMessage::descriptor()) == FooMessage::default_instance() + // This factory supports all types which are found in + // DescriptorPool::generated_pool(). If given a descriptor from any other + // pool, GetPrototype() will return NULL. (You can also check if a + // descriptor is for a generated message by checking if + // descriptor->file()->pool() == DescriptorPool::generated_pool().) + // + // This factory is 100% thread-safe; calling GetPrototype() does not modify + // any shared data. + // + // This factory is a singleton. The caller must not delete the object. + static MessageFactory* generated_factory(); + + // For internal use only: Registers a .proto file at static initialization + // time, to be placed in generated_factory. The first time GetPrototype() + // is called with a descriptor from this file, |register_messages| will be + // called, with the file name as the parameter. It must call + // InternalRegisterGeneratedMessage() (below) to register each message type + // in the file. This strange mechanism is necessary because descriptors are + // built lazily, so we can't register types by their descriptor until we + // know that the descriptor exists. |filename| must be a permanent string. + static void InternalRegisterGeneratedFile( + const char* filename, void (*register_messages)(const string&)); + + // For internal use only: Registers a message type. Called only by the + // functions which are registered with InternalRegisterGeneratedFile(), + // above. + static void InternalRegisterGeneratedMessage(const Descriptor* descriptor, + const Message* prototype); + + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory); +}; + +#define DECLARE_GET_REPEATED_FIELD(TYPE) \ +template<> \ +LIBPROTOBUF_EXPORT \ +const RepeatedField& Reflection::GetRepeatedField( \ + const Message& message, const FieldDescriptor* field) const; \ + \ +template<> \ +LIBPROTOBUF_EXPORT \ +RepeatedField* Reflection::MutableRepeatedField( \ + Message* message, const FieldDescriptor* field) const; + +DECLARE_GET_REPEATED_FIELD(int32) +DECLARE_GET_REPEATED_FIELD(int64) +DECLARE_GET_REPEATED_FIELD(uint32) +DECLARE_GET_REPEATED_FIELD(uint64) +DECLARE_GET_REPEATED_FIELD(float) +DECLARE_GET_REPEATED_FIELD(double) +DECLARE_GET_REPEATED_FIELD(bool) + +#undef DECLARE_GET_REPEATED_FIELD + +// ============================================================================= +// Implementation details for {Get,Mutable}RawRepeatedPtrField. We provide +// specializations for , and and handle +// everything else with the default template which will match any type having +// a method with signature "static const google::protobuf::Descriptor* descriptor()". +// Such a type presumably is a descendant of google::protobuf::Message. + +template<> +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedString(const_cast(&message), field, true)); +} + +template<> +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedString(message, field, true)); +} + + +// ----- + +template<> +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedField(const_cast(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template<> +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + NULL)); +} + +template +inline const RepeatedPtrField& Reflection::GetRepeatedPtrField( + const Message& message, const FieldDescriptor* field) const { + return *static_cast* >( + MutableRawRepeatedField(const_cast(&message), field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + +template +inline RepeatedPtrField* Reflection::MutableRepeatedPtrField( + Message* message, const FieldDescriptor* field) const { + return static_cast* >( + MutableRawRepeatedField(message, field, + FieldDescriptor::CPPTYPE_MESSAGE, -1, + PB::default_instance().GetDescriptor())); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MESSAGE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.cc new file mode 100644 index 000000000..49dbe6e09 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.cc @@ -0,0 +1,334 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +MessageLite::~MessageLite() {} + +string MessageLite::InitializationErrorString() const { + return "(cannot determine missing fields for lite message)"; +} + +namespace { + +// When serializing, we first compute the byte size, then serialize the message. +// If serialization produces a different number of bytes than expected, we +// call this function, which crashes. The problem could be due to a bug in the +// protobuf implementation but is more likely caused by concurrent modification +// of the message. This function attempts to distinguish between the two and +// provide a useful error message. +void ByteSizeConsistencyError(int byte_size_before_serialization, + int byte_size_after_serialization, + int bytes_produced_by_serialization) { + GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization) + << "Protocol message was modified concurrently during serialization."; + GOOGLE_CHECK_EQ(bytes_produced_by_serialization, byte_size_before_serialization) + << "Byte size calculation and serialization were inconsistent. This " + "may indicate a bug in protocol buffers or it may be caused by " + "concurrent modification of the message."; + GOOGLE_LOG(FATAL) << "This shouldn't be called if all the sizes are equal."; +} + +string InitializationErrorMessage(const char* action, + const MessageLite& message) { + // Note: We want to avoid depending on strutil in the lite library, otherwise + // we'd use: + // + // return strings::Substitute( + // "Can't $0 message of type \"$1\" because it is missing required " + // "fields: $2", + // action, message.GetTypeName(), + // message.InitializationErrorString()); + + string result; + result += "Can't "; + result += action; + result += " message of type \""; + result += message.GetTypeName(); + result += "\" because it is missing required fields: "; + result += message.InitializationErrorString(); + return result; +} + +// Several of the Parse methods below just do one thing and then call another +// method. In a naive implementation, we might have ParseFromString() call +// ParseFromArray() which would call ParseFromZeroCopyStream() which would call +// ParseFromCodedStream() which would call MergeFromCodedStream() which would +// call MergePartialFromCodedStream(). However, when parsing very small +// messages, every function call introduces significant overhead. To avoid +// this without reproducing code, we use these forced-inline helpers. +// +// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not +// definitions. +inline bool InlineMergeFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParseFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParseFromArray(const void* data, int size, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline bool InlineParsePartialFromArray(const void* data, int size, + MessageLite* message) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + +bool InlineMergeFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + if (!message->MergePartialFromCodedStream(input)) return false; + if (!message->IsInitialized()) { + GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message); + return false; + } + return true; +} + +bool InlineParseFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + message->Clear(); + return InlineMergeFromCodedStream(input, message); +} + +bool InlineParsePartialFromCodedStream(io::CodedInputStream* input, + MessageLite* message) { + message->Clear(); + return message->MergePartialFromCodedStream(input); +} + +bool InlineParseFromArray(const void* data, int size, MessageLite* message) { + io::CodedInputStream input(reinterpret_cast(data), size); + return InlineParseFromCodedStream(&input, message) && + input.ConsumedEntireMessage(); +} + +bool InlineParsePartialFromArray(const void* data, int size, + MessageLite* message) { + io::CodedInputStream input(reinterpret_cast(data), size); + return InlineParsePartialFromCodedStream(&input, message) && + input.ConsumedEntireMessage(); +} + +} // namespace + +bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) { + return InlineMergeFromCodedStream(input, this); +} + +bool MessageLite::ParseFromCodedStream(io::CodedInputStream* input) { + return InlineParseFromCodedStream(input, this); +} + +bool MessageLite::ParsePartialFromCodedStream(io::CodedInputStream* input) { + return InlineParsePartialFromCodedStream(input, this); +} + +bool MessageLite::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParseFromCodedStream(&decoder) && decoder.ConsumedEntireMessage(); +} + +bool MessageLite::ParsePartialFromZeroCopyStream( + io::ZeroCopyInputStream* input) { + io::CodedInputStream decoder(input); + return ParsePartialFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage(); +} + +bool MessageLite::ParseFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + io::CodedInputStream decoder(input); + decoder.PushLimit(size); + return ParseFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage() && + decoder.BytesUntilLimit() == 0; +} + +bool MessageLite::ParsePartialFromBoundedZeroCopyStream( + io::ZeroCopyInputStream* input, int size) { + io::CodedInputStream decoder(input); + decoder.PushLimit(size); + return ParsePartialFromCodedStream(&decoder) && + decoder.ConsumedEntireMessage() && + decoder.BytesUntilLimit() == 0; +} + +bool MessageLite::ParseFromString(const string& data) { + return InlineParseFromArray(data.data(), data.size(), this); +} + +bool MessageLite::ParsePartialFromString(const string& data) { + return InlineParsePartialFromArray(data.data(), data.size(), this); +} + +bool MessageLite::ParseFromArray(const void* data, int size) { + return InlineParseFromArray(data, size, this); +} + +bool MessageLite::ParsePartialFromArray(const void* data, int size) { + return InlineParsePartialFromArray(data, size, this); +} + + +// =================================================================== + +uint8* MessageLite::SerializeWithCachedSizesToArray(uint8* target) const { + // We only optimize this when using optimize_for = SPEED. In other cases + // we just use the CodedOutputStream path. + int size = GetCachedSize(); + io::ArrayOutputStream out(target, size); + io::CodedOutputStream coded_out(&out); + SerializeWithCachedSizes(&coded_out); + GOOGLE_CHECK(!coded_out.HadError()); + return target + size; +} + +bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToCodedStream(output); +} + +bool MessageLite::SerializePartialToCodedStream( + io::CodedOutputStream* output) const { + const int size = ByteSize(); // Force size to be cached. + uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size); + if (buffer != NULL) { + uint8* end = SerializeWithCachedSizesToArray(buffer); + if (end - buffer != size) { + ByteSizeConsistencyError(size, ByteSize(), end - buffer); + } + return true; + } else { + int original_byte_count = output->ByteCount(); + SerializeWithCachedSizes(output); + if (output->HadError()) { + return false; + } + int final_byte_count = output->ByteCount(); + + if (final_byte_count - original_byte_count != size) { + ByteSizeConsistencyError(size, ByteSize(), + final_byte_count - original_byte_count); + } + + return true; + } +} + +bool MessageLite::SerializeToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializeToCodedStream(&encoder); +} + +bool MessageLite::SerializePartialToZeroCopyStream( + io::ZeroCopyOutputStream* output) const { + io::CodedOutputStream encoder(output); + return SerializePartialToCodedStream(&encoder); +} + +bool MessageLite::AppendToString(string* output) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return AppendPartialToString(output); +} + +bool MessageLite::AppendPartialToString(string* output) const { + int old_size = output->size(); + int byte_size = ByteSize(); + STLStringResizeUninitialized(output, old_size + byte_size); + uint8* start = reinterpret_cast(string_as_array(output) + old_size); + uint8* end = SerializeWithCachedSizesToArray(start); + if (end - start != byte_size) { + ByteSizeConsistencyError(byte_size, ByteSize(), end - start); + } + return true; +} + +bool MessageLite::SerializeToString(string* output) const { + output->clear(); + return AppendToString(output); +} + +bool MessageLite::SerializePartialToString(string* output) const { + output->clear(); + return AppendPartialToString(output); +} + +bool MessageLite::SerializeToArray(void* data, int size) const { + GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this); + return SerializePartialToArray(data, size); +} + +bool MessageLite::SerializePartialToArray(void* data, int size) const { + int byte_size = ByteSize(); + if (size < byte_size) return false; + uint8* start = reinterpret_cast(data); + uint8* end = SerializeWithCachedSizesToArray(start); + if (end - start != byte_size) { + ByteSizeConsistencyError(byte_size, ByteSize(), end - start); + } + return true; +} + +string MessageLite::SerializeAsString() const { + // If the compiler implements the (Named) Return Value Optimization, + // the local variable 'result' will not actually reside on the stack + // of this function, but will be overlaid with the object that the + // caller supplied for the return value to be constructed in. + string output; + if (!AppendToString(&output)) + output.clear(); + return output; +} + +string MessageLite::SerializePartialAsString() const { + string output; + if (!AppendPartialToString(&output)) + output.clear(); + return output; +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.h new file mode 100644 index 000000000..1ec3068cf --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_lite.h @@ -0,0 +1,246 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// Authors: wink@google.com (Wink Saville), +// kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Defines MessageLite, the abstract interface implemented by all (lite +// and non-lite) protocol message objects. + +#ifndef GOOGLE_PROTOBUF_MESSAGE_LITE_H__ +#define GOOGLE_PROTOBUF_MESSAGE_LITE_H__ + +#include + +namespace google { +namespace protobuf { + +namespace io { + class CodedInputStream; + class CodedOutputStream; + class ZeroCopyInputStream; + class ZeroCopyOutputStream; +} + +// Interface to light weight protocol messages. +// +// This interface is implemented by all protocol message objects. Non-lite +// messages additionally implement the Message interface, which is a +// subclass of MessageLite. Use MessageLite instead when you only need +// the subset of features which it supports -- namely, nothing that uses +// descriptors or reflection. You can instruct the protocol compiler +// to generate classes which implement only MessageLite, not the full +// Message interface, by adding the following line to the .proto file: +// +// option optimize_for = LITE_RUNTIME; +// +// This is particularly useful on resource-constrained systems where +// the full protocol buffers runtime library is too big. +// +// Note that on non-constrained systems (e.g. servers) when you need +// to link in lots of protocol definitions, a better way to reduce +// total code footprint is to use optimize_for = CODE_SIZE. This +// will make the generated code smaller while still supporting all the +// same features (at the expense of speed). optimize_for = LITE_RUNTIME +// is best when you only have a small number of message types linked +// into your binary, in which case the size of the protocol buffers +// runtime itself is the biggest problem. +class LIBPROTOBUF_EXPORT MessageLite { + public: + inline MessageLite() {} + virtual ~MessageLite(); + + // Basic Operations ------------------------------------------------ + + // Get the name of this message type, e.g. "foo.bar.BazProto". + virtual string GetTypeName() const = 0; + + // Construct a new instance of the same type. Ownership is passed to the + // caller. + virtual MessageLite* New() const = 0; + + // Clear all fields of the message and set them to their default values. + // Clear() avoids freeing memory, assuming that any memory allocated + // to hold parts of the message will be needed again to hold the next + // message. If you actually want to free the memory used by a Message, + // you must delete it. + virtual void Clear() = 0; + + // Quickly check if all required fields have values set. + virtual bool IsInitialized() const = 0; + + // This is not implemented for Lite messages -- it just returns "(cannot + // determine missing fields for lite message)". However, it is implemented + // for full messages. See message.h. + virtual string InitializationErrorString() const; + + // If |other| is the exact same class as this, calls MergeFrom(). Otherwise, + // results are undefined (probably crash). + virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0; + + // Parsing --------------------------------------------------------- + // Methods for parsing in protocol buffer format. Most of these are + // just simple wrappers around MergeFromCodedStream(). + + // Fill the message with a protocol buffer parsed from the given input + // stream. Returns false on a read error or if the input is in the + // wrong format. + bool ParseFromCodedStream(io::CodedInputStream* input); + // Like ParseFromCodedStream(), but accepts messages that are missing + // required fields. + bool ParsePartialFromCodedStream(io::CodedInputStream* input); + // Read a protocol buffer from the given zero-copy input stream. If + // successful, the entire input will be consumed. + bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); + // Like ParseFromZeroCopyStream(), but accepts messages that are missing + // required fields. + bool ParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input); + // Read a protocol buffer from the given zero-copy input stream, expecting + // the message to be exactly "size" bytes long. If successful, exactly + // this many bytes will have been consumed from the input. + bool ParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); + // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are + // missing required fields. + bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, + int size); + // Parse a protocol buffer contained in a string. + bool ParseFromString(const string& data); + // Like ParseFromString(), but accepts messages that are missing + // required fields. + bool ParsePartialFromString(const string& data); + // Parse a protocol buffer contained in an array of bytes. + bool ParseFromArray(const void* data, int size); + // Like ParseFromArray(), but accepts messages that are missing + // required fields. + bool ParsePartialFromArray(const void* data, int size); + + + // Reads a protocol buffer from the stream and merges it into this + // Message. Singular fields read from the input overwrite what is + // already in the Message and repeated fields are appended to those + // already present. + // + // It is the responsibility of the caller to call input->LastTagWas() + // (for groups) or input->ConsumedEntireMessage() (for non-groups) after + // this returns to verify that the message's end was delimited correctly. + // + // ParsefromCodedStream() is implemented as Clear() followed by + // MergeFromCodedStream(). + bool MergeFromCodedStream(io::CodedInputStream* input); + + // Like MergeFromCodedStream(), but succeeds even if required fields are + // missing in the input. + // + // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() + // followed by IsInitialized(). + virtual bool MergePartialFromCodedStream(io::CodedInputStream* input) = 0; + + + // Serialization --------------------------------------------------- + // Methods for serializing in protocol buffer format. Most of these + // are just simple wrappers around ByteSize() and SerializeWithCachedSizes(). + + // Write a protocol buffer of this message to the given output. Returns + // false on a write error. If the message is missing required fields, + // this may GOOGLE_CHECK-fail. + bool SerializeToCodedStream(io::CodedOutputStream* output) const; + // Like SerializeToCodedStream(), but allows missing required fields. + bool SerializePartialToCodedStream(io::CodedOutputStream* output) const; + // Write the message to the given zero-copy output stream. All required + // fields must be set. + bool SerializeToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Like SerializeToZeroCopyStream(), but allows missing required fields. + bool SerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output) const; + // Serialize the message and store it in the given string. All required + // fields must be set. + bool SerializeToString(string* output) const; + // Like SerializeToString(), but allows missing required fields. + bool SerializePartialToString(string* output) const; + // Serialize the message and store it in the given byte array. All required + // fields must be set. + bool SerializeToArray(void* data, int size) const; + // Like SerializeToArray(), but allows missing required fields. + bool SerializePartialToArray(void* data, int size) const; + + // Make a string encoding the message. Is equivalent to calling + // SerializeToString() on a string and using that. Returns the empty + // string if SerializeToString() would have returned an error. + // Note: If you intend to generate many such strings, you may + // reduce heap fragmentation by instead re-using the same string + // object with calls to SerializeToString(). + string SerializeAsString() const; + // Like SerializeAsString(), but allows missing required fields. + string SerializePartialAsString() const; + + // Like SerializeToString(), but appends to the data to the string's existing + // contents. All required fields must be set. + bool AppendToString(string* output) const; + // Like AppendToString(), but allows missing required fields. + bool AppendPartialToString(string* output) const; + + // Computes the serialized size of the message. This recursively calls + // ByteSize() on all embedded messages. If a subclass does not override + // this, it MUST override SetCachedSize(). + virtual int ByteSize() const = 0; + + // Serializes the message without recomputing the size. The message must + // not have changed since the last call to ByteSize(); if it has, the results + // are undefined. + virtual void SerializeWithCachedSizes( + io::CodedOutputStream* output) const = 0; + + // Like SerializeWithCachedSizes, but writes directly to *target, returning + // a pointer to the byte immediately after the last byte written. "target" + // must point at a byte array of at least ByteSize() bytes. + virtual uint8* SerializeWithCachedSizesToArray(uint8* target) const; + + // Returns the result of the last call to ByteSize(). An embedded message's + // size is needed both to serialize it (because embedded messages are + // length-delimited) and to compute the outer message's size. Caching + // the size avoids computing it multiple times. + // + // ByteSize() does not automatically use the cached size when available + // because this would require invalidating it every time the message was + // modified, which would be too hard and expensive. (E.g. if a deeply-nested + // sub-message is changed, all of its parents' cached sizes would need to be + // invalidated, which is too much work for an otherwise inlined setter + // method.) + virtual int GetCachedSize() const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MESSAGE_LITE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_unittest.cc new file mode 100644 index 000000000..a1449c76f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/message_unittest.cc @@ -0,0 +1,354 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#ifdef _MSC_VER +#include +#else +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#endif +#endif + +TEST(MessageTest, SerializeHelpers) { + // TODO(kenton): Test more helpers? They're all two-liners so it seems + // like a waste of time. + + protobuf_unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + stringstream stream; + + string str1("foo"); + string str2("bar"); + + EXPECT_TRUE(message.SerializeToString(&str1)); + EXPECT_TRUE(message.AppendToString(&str2)); + EXPECT_TRUE(message.SerializeToOstream(&stream)); + + EXPECT_EQ(str1.size() + 3, str2.size()); + EXPECT_EQ("bar", str2.substr(0, 3)); + // Don't use EXPECT_EQ because we don't want to dump raw binary data to + // stdout. + EXPECT_TRUE(str2.substr(3) == str1); + + // GCC gives some sort of error if we try to just do stream.str() == str1. + string temp = stream.str(); + EXPECT_TRUE(temp == str1); + + EXPECT_TRUE(message.SerializeAsString() == str1); + +} + +TEST(MessageTest, SerializeToBrokenOstream) { + ofstream out; + protobuf_unittest::TestAllTypes message; + message.set_optional_int32(123); + + EXPECT_FALSE(message.SerializeToOstream(&out)); +} + +TEST(MessageTest, ParseFromFileDescriptor) { + string filename = TestSourceDir() + + "/google/protobuf/testdata/golden_message"; + int file = open(filename.c_str(), O_RDONLY | O_BINARY); + + unittest::TestAllTypes message; + EXPECT_TRUE(message.ParseFromFileDescriptor(file)); + TestUtil::ExpectAllFieldsSet(message); + + EXPECT_GE(close(file), 0); +} + +TEST(MessageTest, ParsePackedFromFileDescriptor) { + string filename = + TestSourceDir() + + "/google/protobuf/testdata/golden_packed_fields_message"; + int file = open(filename.c_str(), O_RDONLY | O_BINARY); + + unittest::TestPackedTypes message; + EXPECT_TRUE(message.ParseFromFileDescriptor(file)); + TestUtil::ExpectPackedFieldsSet(message); + + EXPECT_GE(close(file), 0); +} + +TEST(MessageTest, ParseHelpers) { + // TODO(kenton): Test more helpers? They're all two-liners so it seems + // like a waste of time. + string data; + + { + // Set up. + protobuf_unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + message.SerializeToString(&data); + } + + { + // Test ParseFromString. + protobuf_unittest::TestAllTypes message; + EXPECT_TRUE(message.ParseFromString(data)); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test ParseFromIstream. + protobuf_unittest::TestAllTypes message; + stringstream stream(data); + EXPECT_TRUE(message.ParseFromIstream(&stream)); + EXPECT_TRUE(stream.eof()); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test ParseFromBoundedZeroCopyStream. + string data_with_junk(data); + data_with_junk.append("some junk on the end"); + io::ArrayInputStream stream(data_with_junk.data(), data_with_junk.size()); + protobuf_unittest::TestAllTypes message; + EXPECT_TRUE(message.ParseFromBoundedZeroCopyStream(&stream, data.size())); + TestUtil::ExpectAllFieldsSet(message); + } + + { + // Test that ParseFromBoundedZeroCopyStream fails (but doesn't crash) if + // EOF is reached before the expected number of bytes. + io::ArrayInputStream stream(data.data(), data.size()); + protobuf_unittest::TestAllTypes message; + EXPECT_FALSE( + message.ParseFromBoundedZeroCopyStream(&stream, data.size() + 1)); + } +} + +TEST(MessageTest, ParseFailsIfNotInitialized) { + unittest::TestRequired message; + vector errors; + + { + ScopedMemoryLog log; + EXPECT_FALSE(message.ParseFromString("")); + errors = log.GetMessages(ERROR); + } + + ASSERT_EQ(1, errors.size()); + EXPECT_EQ("Can't parse message of type \"protobuf_unittest.TestRequired\" " + "because it is missing required fields: a, b, c", + errors[0]); +} + +TEST(MessageTest, BypassInitializationCheckOnParse) { + unittest::TestRequired message; + io::ArrayInputStream raw_input(NULL, 0); + io::CodedInputStream input(&raw_input); + EXPECT_TRUE(message.MergePartialFromCodedStream(&input)); +} + +TEST(MessageTest, InitializationErrorString) { + unittest::TestRequired message; + EXPECT_EQ("a, b, c", message.InitializationErrorString()); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST + +TEST(MessageTest, SerializeFailsIfNotInitialized) { + unittest::TestRequired message; + string data; + EXPECT_DEBUG_DEATH(EXPECT_TRUE(message.SerializeToString(&data)), + "Can't serialize message of type \"protobuf_unittest.TestRequired\" because " + "it is missing required fields: a, b, c"); +} + +TEST(MessageTest, CheckInitialized) { + unittest::TestRequired message; + EXPECT_DEATH(message.CheckInitialized(), + "Message of type \"protobuf_unittest.TestRequired\" is missing required " + "fields: a, b, c"); +} + +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(MessageTest, BypassInitializationCheckOnSerialize) { + unittest::TestRequired message; + io::ArrayOutputStream raw_output(NULL, 0); + io::CodedOutputStream output(&raw_output); + EXPECT_TRUE(message.SerializePartialToCodedStream(&output)); +} + +TEST(MessageTest, FindInitializationErrors) { + unittest::TestRequired message; + vector errors; + message.FindInitializationErrors(&errors); + ASSERT_EQ(3, errors.size()); + EXPECT_EQ("a", errors[0]); + EXPECT_EQ("b", errors[1]); + EXPECT_EQ("c", errors[2]); +} + +TEST(MessageTest, ParseFailsOnInvalidMessageEnd) { + unittest::TestAllTypes message; + + // Control case. + EXPECT_TRUE(message.ParseFromArray("", 0)); + + // The byte is a valid varint, but not a valid tag (zero). + EXPECT_FALSE(message.ParseFromArray("\0", 1)); + + // The byte is a malformed varint. + EXPECT_FALSE(message.ParseFromArray("\200", 1)); + + // The byte is an endgroup tag, but we aren't parsing a group. + EXPECT_FALSE(message.ParseFromArray("\014", 1)); +} + +namespace { + +void ExpectMessageMerged(const unittest::TestAllTypes& message) { + EXPECT_EQ(3, message.optional_int32()); + EXPECT_EQ(2, message.optional_int64()); + EXPECT_EQ("hello", message.optional_string()); +} + +void AssignParsingMergeMessages( + unittest::TestAllTypes* msg1, + unittest::TestAllTypes* msg2, + unittest::TestAllTypes* msg3) { + msg1->set_optional_int32(1); + msg2->set_optional_int64(2); + msg3->set_optional_int32(3); + msg3->set_optional_string("hello"); +} + +} // namespace + +// Test that if an optional or required message/group field appears multiple +// times in the input, they need to be merged. +TEST(MessageTest, ParsingMerge) { + unittest::TestParsingMerge::RepeatedFieldsGenerator generator; + unittest::TestAllTypes* msg1; + unittest::TestAllTypes* msg2; + unittest::TestAllTypes* msg3; + +#define ASSIGN_REPEATED_FIELD(FIELD) \ + msg1 = generator.add_##FIELD(); \ + msg2 = generator.add_##FIELD(); \ + msg3 = generator.add_##FIELD(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_FIELD(field1); + ASSIGN_REPEATED_FIELD(field2); + ASSIGN_REPEATED_FIELD(field3); + ASSIGN_REPEATED_FIELD(ext1); + ASSIGN_REPEATED_FIELD(ext2); + +#undef ASSIGN_REPEATED_FIELD +#define ASSIGN_REPEATED_GROUP(FIELD) \ + msg1 = generator.add_##FIELD()->mutable_field1(); \ + msg2 = generator.add_##FIELD()->mutable_field1(); \ + msg3 = generator.add_##FIELD()->mutable_field1(); \ + AssignParsingMergeMessages(msg1, msg2, msg3) + + ASSIGN_REPEATED_GROUP(group1); + ASSIGN_REPEATED_GROUP(group2); + +#undef ASSIGN_REPEATED_GROUP + + string buffer; + generator.SerializeToString(&buffer); + unittest::TestParsingMerge parsing_merge; + parsing_merge.ParseFromString(buffer); + + // Required and optional fields should be merged. + ExpectMessageMerged(parsing_merge.required_all_types()); + ExpectMessageMerged(parsing_merge.optional_all_types()); + ExpectMessageMerged( + parsing_merge.optionalgroup().optional_group_all_types()); + ExpectMessageMerged( + parsing_merge.GetExtension(unittest::TestParsingMerge::optional_ext)); + + // Repeated fields should not be merged. + EXPECT_EQ(3, parsing_merge.repeated_all_types_size()); + EXPECT_EQ(3, parsing_merge.repeatedgroup_size()); + EXPECT_EQ(3, parsing_merge.ExtensionSize( + unittest::TestParsingMerge::repeated_ext)); +} + +TEST(MessageFactoryTest, GeneratedFactoryLookup) { + EXPECT_EQ( + MessageFactory::generated_factory()->GetPrototype( + protobuf_unittest::TestAllTypes::descriptor()), + &protobuf_unittest::TestAllTypes::default_instance()); +} + +TEST(MessageFactoryTest, GeneratedFactoryUnknownType) { + // Construct a new descriptor. + DescriptorPool pool; + FileDescriptorProto file; + file.set_name("foo.proto"); + file.add_message_type()->set_name("Foo"); + const Descriptor* descriptor = pool.BuildFile(file)->message_type(0); + + // Trying to construct it should return NULL. + EXPECT_TRUE( + MessageFactory::generated_factory()->GetPrototype(descriptor) == NULL); +} + + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/package_info.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/package_info.h new file mode 100644 index 000000000..60cd3994c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/package_info.h @@ -0,0 +1,64 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 exists solely to document the google::protobuf namespace. +// It is not compiled into anything, but it may be read by an automated +// documentation generator. + +namespace google { + +// Core components of the Protocol Buffers runtime library. +// +// The files in this package represent the core of the Protocol Buffer +// system. All of them are part of the libprotobuf library. +// +// A note on thread-safety: +// +// Thread-safety in the Protocol Buffer library follows a simple rule: +// unless explicitly noted otherwise, it is always safe to use an object +// from multiple threads simultaneously as long as the object is declared +// const in all threads (or, it is only used in ways that would be allowed +// if it were declared const). However, if an object is accessed in one +// thread in a way that would not be allowed if it were const, then it is +// not safe to access that object in any other thread simultaneously. +// +// Put simply, read-only access to an object can happen in multiple threads +// simultaneously, but write access can only happen in a single thread at +// a time. +// +// The implementation does contain some "const" methods which actually modify +// the object behind the scenes -- e.g., to cache results -- but in these cases +// mutex locking is used to make the access thread-safe. +namespace protobuf {} +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.cc new file mode 100644 index 000000000..f00997c69 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.cc @@ -0,0 +1,267 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +void ReflectionOps::Copy(const Message& from, Message* to) { + if (&from == to) return; + Clear(to); + Merge(from, to); +} + +void ReflectionOps::Merge(const Message& from, Message* to) { + GOOGLE_CHECK_NE(&from, to); + + const Descriptor* descriptor = from.GetDescriptor(); + GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) + << "Tried to merge messages of different types."; + + const Reflection* from_reflection = from.GetReflection(); + const Reflection* to_reflection = to->GetReflection(); + + vector fields; + from_reflection->ListFields(from, &fields); + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + + if (field->is_repeated()) { + int count = from_reflection->FieldSize(from, field); + for (int j = 0; j < count; j++) { + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Add##METHOD(to, field, \ + from_reflection->GetRepeated##METHOD(from, field, j)); \ + break; + + HANDLE_TYPE(INT32 , Int32 ); + HANDLE_TYPE(INT64 , Int64 ); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(FLOAT , Float ); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL , Bool ); + HANDLE_TYPE(STRING, String); + HANDLE_TYPE(ENUM , Enum ); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + to_reflection->AddMessage(to, field)->MergeFrom( + from_reflection->GetRepeatedMessage(from, field, j)); + break; + } + } + } else { + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + to_reflection->Set##METHOD(to, field, \ + from_reflection->Get##METHOD(from, field)); \ + break; + + HANDLE_TYPE(INT32 , Int32 ); + HANDLE_TYPE(INT64 , Int64 ); + HANDLE_TYPE(UINT32, UInt32); + HANDLE_TYPE(UINT64, UInt64); + HANDLE_TYPE(FLOAT , Float ); + HANDLE_TYPE(DOUBLE, Double); + HANDLE_TYPE(BOOL , Bool ); + HANDLE_TYPE(STRING, String); + HANDLE_TYPE(ENUM , Enum ); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_MESSAGE: + to_reflection->MutableMessage(to, field)->MergeFrom( + from_reflection->GetMessage(from, field)); + break; + } + } + } + + to_reflection->MutableUnknownFields(to)->MergeFrom( + from_reflection->GetUnknownFields(from)); +} + +void ReflectionOps::Clear(Message* message) { + const Reflection* reflection = message->GetReflection(); + + vector fields; + reflection->ListFields(*message, &fields); + for (int i = 0; i < fields.size(); i++) { + reflection->ClearField(message, fields[i]); + } + + reflection->MutableUnknownFields(message)->Clear(); +} + +bool ReflectionOps::IsInitialized(const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + + // Check required fields of this message. + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + return false; + } + } + } + + // Check that sub-messages are initialized. + 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_repeated()) { + int size = reflection->FieldSize(message, field); + + for (int j = 0; j < size; j++) { + if (!reflection->GetRepeatedMessage(message, field, j) + .IsInitialized()) { + return false; + } + } + } else { + if (!reflection->GetMessage(message, field).IsInitialized()) { + return false; + } + } + } + } + + return true; +} + +void ReflectionOps::DiscardUnknownFields(Message* message) { + const Reflection* reflection = message->GetReflection(); + + reflection->MutableUnknownFields(message)->Clear(); + + 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_repeated()) { + int size = reflection->FieldSize(*message, field); + for (int j = 0; j < size; j++) { + reflection->MutableRepeatedMessage(message, field, j) + ->DiscardUnknownFields(); + } + } else { + reflection->MutableMessage(message, field)->DiscardUnknownFields(); + } + } + } +} + +static string SubMessagePrefix(const string& prefix, + const FieldDescriptor* field, + int index) { + string result(prefix); + if (field->is_extension()) { + result.append("("); + result.append(field->full_name()); + result.append(")"); + } else { + result.append(field->name()); + } + if (index != -1) { + result.append("["); + result.append(SimpleItoa(index)); + result.append("]"); + } + result.append("."); + return result; +} + +void ReflectionOps::FindInitializationErrors( + const Message& message, + const string& prefix, + vector* errors) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + + // Check required fields of this message. + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_required()) { + if (!reflection->HasField(message, descriptor->field(i))) { + errors->push_back(prefix + descriptor->field(i)->name()); + } + } + } + + // Check sub-messages. + 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_repeated()) { + int size = reflection->FieldSize(message, field); + + for (int j = 0; j < size; j++) { + const Message& sub_message = + reflection->GetRepeatedMessage(message, field, j); + FindInitializationErrors(sub_message, + SubMessagePrefix(prefix, field, j), + errors); + } + } else { + const Message& sub_message = reflection->GetMessage(message, field); + FindInitializationErrors(sub_message, + SubMessagePrefix(prefix, field, -1), + errors); + } + } + } +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.h new file mode 100644 index 000000000..60165c2a6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops.h @@ -0,0 +1,81 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__ +#define GOOGLE_PROTOBUF_REFLECTION_OPS_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +// Basic operations that can be performed using reflection. +// These can be used as a cheap way to implement the corresponding +// methods of the Message interface, though they are likely to be +// slower than implementations tailored for the specific message type. +// +// This class should stay limited to operations needed to implement +// the Message interface. +// +// This class is really a namespace that contains only static methods. +class LIBPROTOBUF_EXPORT ReflectionOps { + public: + static void Copy(const Message& from, Message* to); + static void Merge(const Message& from, Message* to); + static void Clear(Message* message); + static bool IsInitialized(const Message& message); + static void DiscardUnknownFields(Message* message); + + // Finds all unset required fields in the message and adds their full + // paths (e.g. "foo.bar[5].baz") to *names. "prefix" will be attached to + // the front of each name. + static void FindInitializationErrors(const Message& message, + const string& prefix, + vector* errors); + + private: + // All methods are static. No need to construct. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps); +}; + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_REFLECTION_OPS_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops_unittest.cc new file mode 100644 index 000000000..29229b5a7 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/reflection_ops_unittest.cc @@ -0,0 +1,405 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST(ReflectionOpsTest, SanityCheck) { + unittest::TestAllTypes message; + + TestUtil::SetAllFields(&message); + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(ReflectionOpsTest, Copy) { + unittest::TestAllTypes message, message2; + + TestUtil::SetAllFields(&message); + + ReflectionOps::Copy(message, &message2); + + TestUtil::ExpectAllFieldsSet(message2); + + // Copying from self should be a no-op. + ReflectionOps::Copy(message2, &message2); + TestUtil::ExpectAllFieldsSet(message2); +} + +TEST(ReflectionOpsTest, CopyExtensions) { + unittest::TestAllExtensions message, message2; + + TestUtil::SetAllExtensions(&message); + + ReflectionOps::Copy(message, &message2); + + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ReflectionOpsTest, Merge) { + // Note: Copy is implemented in terms of Merge() so technically the Copy + // test already tested most of this. + + unittest::TestAllTypes message, message2; + + TestUtil::SetAllFields(&message); + + // This field will test merging into an empty spot. + message2.set_optional_int32(message.optional_int32()); + message.clear_optional_int32(); + + // This tests overwriting. + message2.set_optional_string(message.optional_string()); + message.set_optional_string("something else"); + + // This tests concatenating. + message2.add_repeated_int32(message.repeated_int32(1)); + int32 i = message.repeated_int32(0); + message.clear_repeated_int32(); + message.add_repeated_int32(i); + + ReflectionOps::Merge(message2, &message); + + TestUtil::ExpectAllFieldsSet(message); +} + +TEST(ReflectionOpsTest, MergeExtensions) { + // Note: Copy is implemented in terms of Merge() so technically the Copy + // test already tested most of this. + + unittest::TestAllExtensions message, message2; + + TestUtil::SetAllExtensions(&message); + + // This field will test merging into an empty spot. + message2.SetExtension(unittest::optional_int32_extension, + message.GetExtension(unittest::optional_int32_extension)); + message.ClearExtension(unittest::optional_int32_extension); + + // This tests overwriting. + message2.SetExtension(unittest::optional_string_extension, + message.GetExtension(unittest::optional_string_extension)); + message.SetExtension(unittest::optional_string_extension, "something else"); + + // This tests concatenating. + message2.AddExtension(unittest::repeated_int32_extension, + message.GetExtension(unittest::repeated_int32_extension, 1)); + int32 i = message.GetExtension(unittest::repeated_int32_extension, 0); + message.ClearExtension(unittest::repeated_int32_extension); + message.AddExtension(unittest::repeated_int32_extension, i); + + ReflectionOps::Merge(message2, &message); + + TestUtil::ExpectAllExtensionsSet(message); +} + +TEST(ReflectionOpsTest, MergeUnknown) { + // Test that the messages' UnknownFieldSets are correctly merged. + unittest::TestEmptyMessage message1, message2; + message1.mutable_unknown_fields()->AddVarint(1234, 1); + message2.mutable_unknown_fields()->AddVarint(1234, 2); + + ReflectionOps::Merge(message2, &message1); + + ASSERT_EQ(2, message1.unknown_fields().field_count()); + ASSERT_EQ(UnknownField::TYPE_VARINT, + message1.unknown_fields().field(0).type()); + EXPECT_EQ(1, message1.unknown_fields().field(0).varint()); + ASSERT_EQ(UnknownField::TYPE_VARINT, + message1.unknown_fields().field(1).type()); + EXPECT_EQ(2, message1.unknown_fields().field(1).varint()); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST + +TEST(ReflectionOpsTest, MergeFromSelf) { + // Note: Copy is implemented in terms of Merge() so technically the Copy + // test already tested most of this. + + unittest::TestAllTypes message; + + EXPECT_DEATH( + ReflectionOps::Merge(message, &message), + "&from"); +} + +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(ReflectionOpsTest, Clear) { + unittest::TestAllTypes message; + + TestUtil::SetAllFields(&message); + + ReflectionOps::Clear(&message); + + TestUtil::ExpectClear(message); + + // Check that getting embedded messages returns the objects created during + // SetAllFields() rather than default instances. + EXPECT_NE(&unittest::TestAllTypes::OptionalGroup::default_instance(), + &message.optionalgroup()); + EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.optional_nested_message()); + EXPECT_NE(&unittest::ForeignMessage::default_instance(), + &message.optional_foreign_message()); + EXPECT_NE(&unittest_import::ImportMessage::default_instance(), + &message.optional_import_message()); +} + +TEST(ReflectionOpsTest, ClearExtensions) { + unittest::TestAllExtensions message; + + TestUtil::SetAllExtensions(&message); + + ReflectionOps::Clear(&message); + + TestUtil::ExpectExtensionsClear(message); + + // Check that getting embedded messages returns the objects created during + // SetAllExtensions() rather than default instances. + EXPECT_NE(&unittest::OptionalGroup_extension::default_instance(), + &message.GetExtension(unittest::optionalgroup_extension)); + EXPECT_NE(&unittest::TestAllTypes::NestedMessage::default_instance(), + &message.GetExtension(unittest::optional_nested_message_extension)); + EXPECT_NE(&unittest::ForeignMessage::default_instance(), + &message.GetExtension( + unittest::optional_foreign_message_extension)); + EXPECT_NE(&unittest_import::ImportMessage::default_instance(), + &message.GetExtension(unittest::optional_import_message_extension)); +} + +TEST(ReflectionOpsTest, ClearUnknown) { + // Test that the message's UnknownFieldSet is correctly cleared. + unittest::TestEmptyMessage message; + message.mutable_unknown_fields()->AddVarint(1234, 1); + + ReflectionOps::Clear(&message); + + EXPECT_EQ(0, message.unknown_fields().field_count()); +} + +TEST(ReflectionOpsTest, DiscardUnknownFields) { + unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + + // Set some unknown fields in message. + message.mutable_unknown_fields() + ->AddVarint(123456, 654321); + message.mutable_optional_nested_message() + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); + message.mutable_repeated_nested_message(0) + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); + + EXPECT_EQ(1, message.unknown_fields().field_count()); + EXPECT_EQ(1, message.optional_nested_message() + .unknown_fields().field_count()); + EXPECT_EQ(1, message.repeated_nested_message(0) + .unknown_fields().field_count()); + + // Discard them. + ReflectionOps::DiscardUnknownFields(&message); + TestUtil::ExpectAllFieldsSet(message); + + EXPECT_EQ(0, message.unknown_fields().field_count()); + EXPECT_EQ(0, message.optional_nested_message() + .unknown_fields().field_count()); + EXPECT_EQ(0, message.repeated_nested_message(0) + .unknown_fields().field_count()); +} + +TEST(ReflectionOpsTest, DiscardUnknownExtensions) { + unittest::TestAllExtensions message; + TestUtil::SetAllExtensions(&message); + + // Set some unknown fields. + message.mutable_unknown_fields() + ->AddVarint(123456, 654321); + message.MutableExtension(unittest::optional_nested_message_extension) + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); + message.MutableExtension(unittest::repeated_nested_message_extension, 0) + ->mutable_unknown_fields() + ->AddVarint(123456, 654321); + + EXPECT_EQ(1, message.unknown_fields().field_count()); + EXPECT_EQ(1, + message.GetExtension(unittest::optional_nested_message_extension) + .unknown_fields().field_count()); + EXPECT_EQ(1, + message.GetExtension(unittest::repeated_nested_message_extension, 0) + .unknown_fields().field_count()); + + // Discard them. + ReflectionOps::DiscardUnknownFields(&message); + TestUtil::ExpectAllExtensionsSet(message); + + EXPECT_EQ(0, message.unknown_fields().field_count()); + EXPECT_EQ(0, + message.GetExtension(unittest::optional_nested_message_extension) + .unknown_fields().field_count()); + EXPECT_EQ(0, + message.GetExtension(unittest::repeated_nested_message_extension, 0) + .unknown_fields().field_count()); +} + +TEST(ReflectionOpsTest, IsInitialized) { + unittest::TestRequired message; + + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + message.set_a(1); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + message.set_b(2); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + message.set_c(3); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); +} + +TEST(ReflectionOpsTest, ForeignIsInitialized) { + unittest::TestRequiredForeign message; + + // Starts out initialized because the foreign message is itself an optional + // field. + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + // Once we create that field, the message is no longer initialized. + message.mutable_optional_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + // Initialize it. Now we're initialized. + message.mutable_optional_message()->set_a(1); + message.mutable_optional_message()->set_b(2); + message.mutable_optional_message()->set_c(3); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + // Add a repeated version of the message. No longer initialized. + unittest::TestRequired* sub_message = message.add_repeated_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + // Initialize that repeated version. + sub_message->set_a(1); + sub_message->set_b(2); + sub_message->set_c(3); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); +} + +TEST(ReflectionOpsTest, ExtensionIsInitialized) { + unittest::TestAllExtensions message; + + // Starts out initialized because the foreign message is itself an optional + // field. + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + // Once we create that field, the message is no longer initialized. + message.MutableExtension(unittest::TestRequired::single); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + // Initialize it. Now we're initialized. + message.MutableExtension(unittest::TestRequired::single)->set_a(1); + message.MutableExtension(unittest::TestRequired::single)->set_b(2); + message.MutableExtension(unittest::TestRequired::single)->set_c(3); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + // Add a repeated version of the message. No longer initialized. + message.AddExtension(unittest::TestRequired::multi); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + // Initialize that repeated version. + message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1); + message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2); + message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); +} + +static string FindInitializationErrors(const Message& message) { + vector errors; + ReflectionOps::FindInitializationErrors(message, "", &errors); + return JoinStrings(errors, ","); +} + +TEST(ReflectionOpsTest, FindInitializationErrors) { + unittest::TestRequired message; + EXPECT_EQ("a,b,c", FindInitializationErrors(message)); +} + +TEST(ReflectionOpsTest, FindForeignInitializationErrors) { + unittest::TestRequiredForeign message; + message.mutable_optional_message(); + message.add_repeated_message(); + message.add_repeated_message(); + EXPECT_EQ("optional_message.a," + "optional_message.b," + "optional_message.c," + "repeated_message[0].a," + "repeated_message[0].b," + "repeated_message[0].c," + "repeated_message[1].a," + "repeated_message[1].b," + "repeated_message[1].c", + FindInitializationErrors(message)); +} + +TEST(ReflectionOpsTest, FindExtensionInitializationErrors) { + unittest::TestAllExtensions message; + message.MutableExtension(unittest::TestRequired::single); + message.AddExtension(unittest::TestRequired::multi); + message.AddExtension(unittest::TestRequired::multi); + EXPECT_EQ("(protobuf_unittest.TestRequired.single).a," + "(protobuf_unittest.TestRequired.single).b," + "(protobuf_unittest.TestRequired.single).c," + "(protobuf_unittest.TestRequired.multi)[0].a," + "(protobuf_unittest.TestRequired.multi)[0].b," + "(protobuf_unittest.TestRequired.multi)[0].c," + "(protobuf_unittest.TestRequired.multi)[1].a," + "(protobuf_unittest.TestRequired.multi)[1].b," + "(protobuf_unittest.TestRequired.multi)[1].c", + FindInitializationErrors(message)); +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.cc new file mode 100644 index 000000000..2c1f74c58 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.cc @@ -0,0 +1,87 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +namespace google { +namespace protobuf { + +namespace internal { + +void RepeatedPtrFieldBase::Reserve(int new_size) { + if (total_size_ >= new_size) return; + + void** old_elements = elements_; + total_size_ = max(kMinRepeatedFieldAllocationSize, + max(total_size_ * 2, new_size)); + elements_ = new void*[total_size_]; + if (old_elements != NULL) { + memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0])); + delete [] old_elements; + } +} + +void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { + if (this == other) return; + void** swap_elements = elements_; + int swap_current_size = current_size_; + int swap_allocated_size = allocated_size_; + int swap_total_size = total_size_; + + elements_ = other->elements_; + current_size_ = other->current_size_; + allocated_size_ = other->allocated_size_; + total_size_ = other->total_size_; + + other->elements_ = swap_elements; + other->current_size_ = swap_current_size; + other->allocated_size_ = swap_allocated_size; + other->total_size_ = swap_total_size; +} + +string* StringTypeHandlerBase::New() { + return new string; +} +void StringTypeHandlerBase::Delete(string* value) { + delete value; +} + +} // namespace internal + + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.h new file mode 100644 index 000000000..570d4b751 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field.h @@ -0,0 +1,1519 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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__ + +#include +#include +#include +#include +#include +#include +#include + +namespace google { + +namespace upb { +namespace google_opensource { +class GMR_Handlers; +} // namespace google_opensource +} // namespace upb + +namespace protobuf { + +class Message; + +namespace internal { + +static const int kMinRepeatedFieldAllocationSize = 4; + +// A utility function for logging that doesn't need any template types. +void LogIndexOutOfBounds(int index, int size); +} // 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 { + public: + RepeatedField(); + RepeatedField(const RepeatedField& other); + template + RepeatedField(Iter begin, const Iter& end); + ~RepeatedField(); + + RepeatedField& operator=(const RepeatedField& other); + + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + void Set(int index, const Element& value); + void Add(const Element& value); + 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); + Element* AddAlreadyReserved(); + int Capacity() const; + + // 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". + void Swap(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; + iterator end(); + const_iterator end() 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) + int SpaceUsedExcludingSelf() const; + + private: + static const int kInitialSize = 0; + + Element* elements_; + int current_size_; + int total_size_; + + // 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); +}; + +namespace internal { +template class RepeatedPtrIterator; +template class RepeatedPtrOverPtrsIterator; +} // namespace internal + +namespace internal { + +// This is a helper template to copy an array of elements effeciently 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 { + +// 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; +// static Type* New(); +// 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 SpaceUsed(const Type&); +// }; +class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { + protected: + // 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 SpaceUsed(), and thus need to call SpaceUsedExcludingSelf() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make + // use of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + // To parse directly into a proto2 generated class, the upb class GMR_Handlers + // needs to be able to modify a RepeatedPtrFieldBase directly. + friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers; + + RepeatedPtrFieldBase(); + + // Must be called from destructor. + template + void Destroy(); + + int size() const; + + template + const typename TypeHandler::Type& Get(int index) const; + template + typename TypeHandler::Type* Mutable(int index); + template + typename TypeHandler::Type* Add(); + template + void RemoveLast(); + template + void Clear(); + template + void MergeFrom(const RepeatedPtrFieldBase& other); + template + void CopyFrom(const RepeatedPtrFieldBase& other); + + void CloseGap(int start, int num) { + // Close up a gap of "num" elements starting at offset "start". + for (int i = start + num; i < allocated_size_; ++i) + elements_[i - num] = elements_[i]; + current_size_ -= num; + allocated_size_ -= 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; + + void Swap(RepeatedPtrFieldBase* other); + + void SwapElements(int index1, int index2); + + template + int SpaceUsedExcludingSelf() 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); + template + typename TypeHandler::Type* ReleaseLast(); + + int ClearedCount() const; + template + void AddCleared(typename TypeHandler::Type* value); + template + typename TypeHandler::Type* ReleaseCleared(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); + + static const int kInitialSize = 0; + + void** elements_; + int current_size_; + int allocated_size_; + int total_size_; + + 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); + } +}; + +template +class GenericTypeHandler { + public: + typedef GenericType Type; + static GenericType* New() { return new GenericType; } + static void Delete(GenericType* value) { delete value; } + static void Clear(GenericType* value) { value->Clear(); } + static void Merge(const GenericType& from, GenericType* to) { + to->MergeFrom(from); + } + static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); } + static const Type& default_instance() { return Type::default_instance(); } +}; + +template <> +inline void GenericTypeHandler::Merge( + const MessageLite& from, MessageLite* to) { + to->CheckTypeAndMergeFrom(from); +} + +template <> +inline const MessageLite& GenericTypeHandler::default_instance() { + // Yes, the behavior of the code is undefined, but this function is only + // called when we're already deep into the world of undefined, because the + // caller called Get(index) out of bounds. + MessageLite* null = NULL; + return *null; +} + +template <> +inline const Message& GenericTypeHandler::default_instance() { + // Yes, the behavior of the code is undefined, but this function is only + // called when we're already deep into the world of undefined, because the + // caller called Get(index) out of bounds. + Message* null = NULL; + return *null; +} + + +// HACK: If a class is declared as DLL-exported in MSVC, it insists on +// generating copies of all its methods -- even inline ones -- to include +// in the DLL. But SpaceUsed() calls StringSpaceUsedExcludingSelf() which +// isn't in the lite library, therefore the lite library cannot link if +// StringTypeHandler is exported. So, we factor out StringTypeHandlerBase, +// export that, then make StringTypeHandler be a subclass which is NOT +// exported. +// TODO(kenton): There has to be a better way. +class LIBPROTOBUF_EXPORT StringTypeHandlerBase { + public: + typedef string Type; + static string* New(); + static void Delete(string* value); + static void Clear(string* value) { value->clear(); } + static void Merge(const string& from, string* to) { *to = from; } + static const Type& default_instance() { + return ::google::protobuf::internal::kEmptyString; + } +}; + +class StringTypeHandler : public StringTypeHandlerBase { + public: + static int SpaceUsed(const string& value) { + return sizeof(value) + StringSpaceUsedExcludingSelf(value); + } +}; + + +} // namespace internal + +// RepeatedPtrField is like RepeatedField, but used for repeated strings or +// Messages. +template +class RepeatedPtrField : public internal::RepeatedPtrFieldBase { + public: + RepeatedPtrField(); + RepeatedPtrField(const RepeatedPtrField& other); + template + RepeatedPtrField(Iter begin, const Iter& end); + ~RepeatedPtrField(); + + RepeatedPtrField& operator=(const RepeatedPtrField& other); + + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + Element* Add(); + + // 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". + void Swap(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; + iterator end(); + const_iterator end() 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). + int SpaceUsedExcludingSelf() const; + + // 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. + void AddAllocated(Element* value); + // Remove the last element and return it, passing ownership to the caller. + // Requires: size() > 0 + Element* ReleaseLast(); + + // 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. + void ExtractSubrange(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. + 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 + Element* ReleaseCleared(); + + protected: + // Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only + // subclass it in one place as a hack for compatibility with proto1. The + // subclass needs to know about TypeHandler in order to call protected + // methods on RepeatedPtrFieldBase. + class TypeHandler; + +}; + +// implementation ==================================================== + +template +inline RepeatedField::RepeatedField() + : elements_(NULL), + current_size_(0), + total_size_(kInitialSize) { +} + +template +inline RepeatedField::RepeatedField(const RepeatedField& other) + : elements_(NULL), + current_size_(0), + total_size_(kInitialSize) { + CopyFrom(other); +} + +template +template +inline RepeatedField::RepeatedField(Iter begin, const Iter& end) + : elements_(NULL), + current_size_(0), + total_size_(kInitialSize) { + for (; begin != end; ++begin) { + Add(*begin); + } +} + +template +RepeatedField::~RepeatedField() { + delete [] elements_; +} + +template +inline RepeatedField& +RepeatedField::operator=(const RepeatedField& other) { + if (this != &other) + CopyFrom(other); + return *this; +} + +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(size(), Capacity()); + elements_[current_size_++] = value; +} + +template +inline Element* RepeatedField::AddAlreadyReserved() { + GOOGLE_DCHECK_LT(size(), Capacity()); + return &elements_[current_size_++]; +} + +template +inline const Element& RepeatedField::Get(int index) const { + GOOGLE_DCHECK_LT(index, size()); + return elements_[index]; +} + +template +inline Element* RepeatedField::Mutable(int index) { + GOOGLE_DCHECK_LT(index, size()); + return elements_ + index; +} + +template +inline void RepeatedField::Set(int index, const Element& value) { + GOOGLE_DCHECK_LT(index, size()); + elements_[index] = value; +} + +template +inline void RepeatedField::Add(const Element& value) { + if (current_size_ == total_size_) Reserve(total_size_ + 1); + elements_[current_size_++] = value; +} + +template +inline Element* RepeatedField::Add() { + if (current_size_ == total_size_) Reserve(total_size_ + 1); + return &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->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->size(); ++i) + this->Set(i - num, this->Get(i)); + this->Truncate(this->size() - num); + } +} + +template +inline void RepeatedField::Clear() { + current_size_ = 0; +} + +template +inline void RepeatedField::MergeFrom(const RepeatedField& other) { + if (other.current_size_ != 0) { + Reserve(current_size_ + other.current_size_); + CopyArray(elements_ + current_size_, other.elements_, other.current_size_); + current_size_ += other.current_size_; + } +} + +template +inline void RepeatedField::CopyFrom(const RepeatedField& other) { + Clear(); + MergeFrom(other); +} + +template +inline Element* RepeatedField::mutable_data() { + return elements_; +} + +template +inline const Element* RepeatedField::data() const { + return elements_; +} + + +template +void RepeatedField::Swap(RepeatedField* other) { + if (this == other) return; + Element* swap_elements = elements_; + int swap_current_size = current_size_; + int swap_total_size = total_size_; + + elements_ = other->elements_; + current_size_ = other->current_size_; + total_size_ = other->total_size_; + + other->elements_ = swap_elements; + other->current_size_ = swap_current_size; + other->total_size_ = swap_total_size; +} + +template +void RepeatedField::SwapElements(int index1, int index2) { + std::swap(elements_[index1], elements_[index2]); +} + +template +inline typename RepeatedField::iterator +RepeatedField::begin() { + return elements_; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::begin() const { + return elements_; +} +template +inline typename RepeatedField::iterator +RepeatedField::end() { + return elements_ + current_size_; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::end() const { + return elements_ + current_size_; +} + +template +inline int RepeatedField::SpaceUsedExcludingSelf() const { + return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 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; + + Element* old_elements = elements_; + total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, + max(total_size_ * 2, new_size)); + elements_ = new Element[total_size_]; + if (old_elements != NULL) { + MoveArray(elements_, old_elements, current_size_); + delete [] old_elements; + } +} + +template +inline void RepeatedField::Truncate(int new_size) { + GOOGLE_DCHECK_LE(new_size, current_size_); + 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, array_size * sizeof(Element)); + } +}; + +} // namespace internal + + +// ------------------------------------------------------------------- + +namespace internal { + +inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() + : elements_(NULL), + current_size_(0), + allocated_size_(0), + total_size_(kInitialSize) { +} + +template +void RepeatedPtrFieldBase::Destroy() { + for (int i = 0; i < allocated_size_; i++) { + TypeHandler::Delete(cast(elements_[i])); + } + delete [] elements_; +} + +inline int RepeatedPtrFieldBase::size() const { + return current_size_; +} + +template +inline const typename TypeHandler::Type& +RepeatedPtrFieldBase::Get(int index) const { + GOOGLE_DCHECK_LT(index, size()); + return *cast(elements_[index]); +} + + +template +inline typename TypeHandler::Type* +RepeatedPtrFieldBase::Mutable(int index) { + GOOGLE_DCHECK_LT(index, size()); + return cast(elements_[index]); +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() { + if (current_size_ < allocated_size_) { + return cast(elements_[current_size_++]); + } + if (allocated_size_ == total_size_) Reserve(total_size_ + 1); + ++allocated_size_; + typename TypeHandler::Type* result = TypeHandler::New(); + elements_[current_size_++] = result; + return result; +} + +template +inline void RepeatedPtrFieldBase::RemoveLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + TypeHandler::Clear(cast(elements_[--current_size_])); +} + +template +void RepeatedPtrFieldBase::Clear() { + for (int i = 0; i < current_size_; i++) { + TypeHandler::Clear(cast(elements_[i])); + } + current_size_ = 0; +} + +template +inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { + Reserve(current_size_ + other.current_size_); + for (int i = 0; i < other.current_size_; i++) { + TypeHandler::Merge(other.template Get(i), Add()); + } +} + +template +inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + RepeatedPtrFieldBase::Clear(); + RepeatedPtrFieldBase::MergeFrom(other); +} + +inline int RepeatedPtrFieldBase::Capacity() const { + return total_size_; +} + +inline void* const* RepeatedPtrFieldBase::raw_data() const { + return elements_; +} + +inline void** RepeatedPtrFieldBase::raw_mutable_data() const { + return elements_; +} + +template +inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast(elements_); +} + +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(elements_); +} + +inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { + std::swap(elements_[index1], elements_[index2]); +} + +template +inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const { + int allocated_bytes = + (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0; + for (int i = 0; i < allocated_size_; ++i) { + allocated_bytes += TypeHandler::SpaceUsed(*cast(elements_[i])); + } + return allocated_bytes; +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { + if (current_size_ < allocated_size_) { + return cast(elements_[current_size_++]); + } else { + return NULL; + } +} + +template +void RepeatedPtrFieldBase::AddAllocated( + typename TypeHandler::Type* value) { + // Make room for the new pointer. + if (current_size_ == total_size_) { + // The array is completely full with no cleared objects, so grow it. + Reserve(total_size_ + 1); + ++allocated_size_; + } else if (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(elements_[current_size_])); + } else if (current_size_ < 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. + elements_[allocated_size_] = elements_[current_size_]; + ++allocated_size_; + } else { + // There are no cleared objects. + ++allocated_size_; + } + + elements_[current_size_++] = value; +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + typename TypeHandler::Type* result = + cast(elements_[--current_size_]); + --allocated_size_; + if (current_size_ < allocated_size_) { + // There are cleared elements on the end; replace the removed element + // with the last allocated element. + elements_[current_size_] = elements_[allocated_size_]; + } + return result; +} + +inline int RepeatedPtrFieldBase::ClearedCount() const { + return allocated_size_ - current_size_; +} + +template +inline void RepeatedPtrFieldBase::AddCleared( + typename TypeHandler::Type* value) { + if (allocated_size_ == total_size_) Reserve(total_size_ + 1); + elements_[allocated_size_++] = value; +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { + GOOGLE_DCHECK_GT(allocated_size_, current_size_); + return cast(elements_[--allocated_size_]); +} + +} // namespace internal + +// ------------------------------------------------------------------- + +template +class RepeatedPtrField::TypeHandler + : public internal::GenericTypeHandler { +}; + +template <> +class RepeatedPtrField::TypeHandler + : public internal::StringTypeHandler { +}; + + +template +inline RepeatedPtrField::RepeatedPtrField() {} + +template +inline RepeatedPtrField::RepeatedPtrField( + const RepeatedPtrField& other) { + CopyFrom(other); +} + +template +template +inline RepeatedPtrField::RepeatedPtrField( + Iter begin, const Iter& end) { + 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 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::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) + delete RepeatedPtrFieldBase::Mutable(start + i); + ExtractSubrange(start, num, NULL); +} + +template +inline void RepeatedPtrField::ExtractSubrange( + 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 Element** RepeatedPtrField::mutable_data() { + return RepeatedPtrFieldBase::mutable_data(); +} + +template +inline const Element* const* RepeatedPtrField::data() const { + return RepeatedPtrFieldBase::data(); +} + +template +void RepeatedPtrField::Swap(RepeatedPtrField* other) { + RepeatedPtrFieldBase::Swap(other); +} + +template +void RepeatedPtrField::SwapElements(int index1, int index2) { + RepeatedPtrFieldBase::SwapElements(index1, index2); +} + +template +inline int RepeatedPtrField::SpaceUsedExcludingSelf() const { + return RepeatedPtrFieldBase::SpaceUsedExcludingSelf(); +} + +template +inline void RepeatedPtrField::AddAllocated(Element* value) { + RepeatedPtrFieldBase::AddAllocated(value); +} + +template +inline Element* RepeatedPtrField::ReleaseLast() { + return RepeatedPtrFieldBase::ReleaseLast(); +} + + +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; + + // 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(0); + } + } + + // 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. + 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 *" for a constant iterator. +template +class RepeatedPtrOverPtrsIterator + : public std::iterator { + public: + typedef RepeatedPtrOverPtrsIterator iterator; + typedef std::iterator< + std::random_access_iterator_tag, Element*> superclass; + + // 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_; +}; + +} // 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::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::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_mutable_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_mutable_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 RepatedPtrField. 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*() { + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator++() { + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedPtrField* field_; +}; + +// A back inserter for RepeatedPtrFields that inserts by transfering 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_; +}; +} // 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); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc new file mode 100644 index 000000000..a40162d0b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -0,0 +1,195 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +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 get 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)); + } +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_unittest.cc new file mode 100644 index 000000000..257701eb3 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/repeated_field_unittest.cc @@ -0,0 +1,1357 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// TODO(kenton): Improve this unittest to bring it up to the standards of +// other proto2 unittests. + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +using protobuf_unittest::TestAllTypes; + +namespace protobuf { +namespace { + +// Test operations on a small RepeatedField. +TEST(RepeatedField, Small) { + RepeatedField field; + + EXPECT_EQ(field.size(), 0); + + field.Add(5); + + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), 5); + + field.Add(42); + + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.Get(1), 42); + + field.Set(1, 23); + + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), 5); + EXPECT_EQ(field.Get(1), 23); + + field.RemoveLast(); + + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), 5); + + field.Clear(); + + EXPECT_EQ(field.size(), 0); + int expected_usage = 4 * sizeof(int); + EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); +} + + +// Test operations on a RepeatedField which is large enough to allocate a +// separate array. +TEST(RepeatedField, Large) { + RepeatedField field; + + for (int i = 0; i < 16; i++) { + field.Add(i * i); + } + + EXPECT_EQ(field.size(), 16); + + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field.Get(i), i * i); + } + + int expected_usage = 16 * sizeof(int); + EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage); +} + +// Test swapping between various types of RepeatedFields. +TEST(RepeatedField, SwapSmallSmall) { + RepeatedField field1; + RepeatedField field2; + + field1.Add(5); + field1.Add(42); + + field1.Swap(&field2); + + EXPECT_EQ(field1.size(), 0); + EXPECT_EQ(field2.size(), 2); + EXPECT_EQ(field2.Get(0), 5); + EXPECT_EQ(field2.Get(1), 42); +} + +TEST(RepeatedField, SwapLargeSmall) { + RepeatedField field1; + RepeatedField field2; + + for (int i = 0; i < 16; i++) { + field1.Add(i * i); + } + field2.Add(5); + field2.Add(42); + field1.Swap(&field2); + + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), 5); + EXPECT_EQ(field1.Get(1), 42); + EXPECT_EQ(field2.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field2.Get(i), i * i); + } +} + +TEST(RepeatedField, SwapLargeLarge) { + RepeatedField field1; + RepeatedField field2; + + field1.Add(5); + field1.Add(42); + for (int i = 0; i < 16; i++) { + field1.Add(i); + field2.Add(i * i); + } + field2.Swap(&field1); + + EXPECT_EQ(field1.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field1.Get(i), i * i); + } + EXPECT_EQ(field2.size(), 18); + EXPECT_EQ(field2.Get(0), 5); + EXPECT_EQ(field2.Get(1), 42); + for (int i = 2; i < 18; i++) { + EXPECT_EQ(field2.Get(i), i - 2); + } +} + +// Determines how much space was reserved by the given field by adding elements +// to it until it re-allocates its space. +static int ReservedSpace(RepeatedField* field) { + const int* ptr = field->data(); + do { + field->Add(0); + } while (field->data() == ptr); + + return field->size() - 1; +} + +TEST(RepeatedField, ReserveMoreThanDouble) { + // Reserve more than double the previous space in the field and expect the + // field to reserve exactly the amount specified. + RepeatedField field; + field.Reserve(20); + + EXPECT_EQ(20, ReservedSpace(&field)); +} + +TEST(RepeatedField, ReserveLessThanDouble) { + // Reserve less than double the previous space in the field and expect the + // field to grow by double instead. + RepeatedField field; + field.Reserve(20); + field.Reserve(30); + + EXPECT_EQ(40, ReservedSpace(&field)); +} + +TEST(RepeatedField, ReserveLessThanExisting) { + // Reserve less than the previous space in the field and expect the + // field to not re-allocate at all. + RepeatedField field; + field.Reserve(20); + const int* previous_ptr = field.data(); + field.Reserve(10); + + EXPECT_EQ(previous_ptr, field.data()); + EXPECT_EQ(20, ReservedSpace(&field)); +} + +TEST(RepeatedField, MergeFrom) { + RepeatedField source, destination; + source.Add(4); + source.Add(5); + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination.MergeFrom(source); + + ASSERT_EQ(5, destination.size()); + EXPECT_EQ(1, destination.Get(0)); + EXPECT_EQ(2, destination.Get(1)); + EXPECT_EQ(3, destination.Get(2)); + EXPECT_EQ(4, destination.Get(3)); + EXPECT_EQ(5, destination.Get(4)); +} + +TEST(RepeatedField, CopyFrom) { + RepeatedField source, destination; + source.Add(4); + source.Add(5); + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + +TEST(RepeatedField, CopyConstruct) { + RepeatedField source; + source.Add(1); + source.Add(2); + + RepeatedField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(1, destination.Get(0)); + EXPECT_EQ(2, destination.Get(1)); +} + +TEST(RepeatedField, IteratorConstruct) { + vector values; + values.push_back(1); + values.push_back(2); + + RepeatedField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0], field.Get(0)); + EXPECT_EQ(values[1], field.Get(1)); + + RepeatedField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0], other.Get(0)); + EXPECT_EQ(values[1], other.Get(1)); +} + +TEST(RepeatedField, CopyAssign) { + RepeatedField source, destination; + source.Add(4); + source.Add(5); + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination = source; + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + +TEST(RepeatedField, SelfAssign) { + // Verify that assignment to self does not destroy data. + RepeatedField source, *p; + p = &source; + source.Add(7); + source.Add(8); + + *p = source; + + ASSERT_EQ(2, source.size()); + EXPECT_EQ(7, source.Get(0)); + EXPECT_EQ(8, source.Get(1)); +} + +TEST(RepeatedField, MutableDataIsMutable) { + RepeatedField field; + field.Add(1); + EXPECT_EQ(1, field.Get(0)); + // The fact that this line compiles would be enough, but we'll check the + // value anyway. + *field.mutable_data() = 2; + EXPECT_EQ(2, field.Get(0)); +} + +TEST(RepeatedField, Truncate) { + RepeatedField field; + + field.Add(12); + field.Add(34); + field.Add(56); + field.Add(78); + EXPECT_EQ(4, field.size()); + + field.Truncate(3); + EXPECT_EQ(3, field.size()); + + field.Add(90); + EXPECT_EQ(4, field.size()); + EXPECT_EQ(90, field.Get(3)); + + // Truncations that don't change the size are allowed, but growing is not + // allowed. + field.Truncate(field.size()); +#ifdef PROTOBUF_HAS_DEATH_TEST + EXPECT_DEBUG_DEATH(field.Truncate(field.size() + 1), "new_size"); +#endif +} + + +TEST(RepeatedField, ExtractSubrange) { + // Exhaustively test every subrange in arrays of all sizes from 0 through 9. + for (int sz = 0; sz < 10; ++sz) { + for (int num = 0; num <= sz; ++num) { + for (int start = 0; start < sz - num; ++start) { + // Create RepeatedField with sz elements having values 0 through sz-1. + RepeatedField field; + for (int i = 0; i < sz; ++i) + field.Add(i); + EXPECT_EQ(field.size(), sz); + + // Create a catcher array and call ExtractSubrange. + int32 catcher[10]; + for (int i = 0; i < 10; ++i) + catcher[i] = -1; + field.ExtractSubrange(start, num, catcher); + + // Does the resulting array have the right size? + EXPECT_EQ(field.size(), sz - num); + + // Were the removed elements extracted into the catcher array? + for (int i = 0; i < num; ++i) + EXPECT_EQ(catcher[i], start + i); + EXPECT_EQ(catcher[num], -1); + + // Does the resulting array contain the right values? + for (int i = 0; i < start; ++i) + EXPECT_EQ(field.Get(i), i); + for (int i = start; i < field.size(); ++i) + EXPECT_EQ(field.Get(i), i + num); + } + } + } +} + +// =================================================================== +// RepeatedPtrField tests. These pretty much just mirror the RepeatedField +// tests above. + +TEST(RepeatedPtrField, Small) { + RepeatedPtrField field; + + EXPECT_EQ(field.size(), 0); + + field.Add()->assign("foo"); + + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), "foo"); + + field.Add()->assign("bar"); + + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.Get(1), "bar"); + + field.Mutable(1)->assign("baz"); + + EXPECT_EQ(field.size(), 2); + EXPECT_EQ(field.Get(0), "foo"); + EXPECT_EQ(field.Get(1), "baz"); + + field.RemoveLast(); + + EXPECT_EQ(field.size(), 1); + EXPECT_EQ(field.Get(0), "foo"); + + field.Clear(); + + EXPECT_EQ(field.size(), 0); +} + + +TEST(RepeatedPtrField, Large) { + RepeatedPtrField field; + + for (int i = 0; i < 16; i++) { + *field.Add() += 'a' + i; + } + + EXPECT_EQ(field.size(), 16); + + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field.Get(i).size(), 1); + EXPECT_EQ(field.Get(i)[0], 'a' + i); + } + + int min_expected_usage = 16 * sizeof(string); + EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage); +} + +TEST(RepeatedPtrField, SwapSmallSmall) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + field1.Add()->assign("foo"); + field1.Add()->assign("bar"); + field1.Swap(&field2); + + EXPECT_EQ(field1.size(), 0); + EXPECT_EQ(field2.size(), 2); + EXPECT_EQ(field2.Get(0), "foo"); + EXPECT_EQ(field2.Get(1), "bar"); +} + +TEST(RepeatedPtrField, SwapLargeSmall) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + field2.Add()->assign("foo"); + field2.Add()->assign("bar"); + for (int i = 0; i < 16; i++) { + *field1.Add() += 'a' + i; + } + field1.Swap(&field2); + + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), "foo"); + EXPECT_EQ(field1.Get(1), "bar"); + EXPECT_EQ(field2.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field2.Get(i).size(), 1); + EXPECT_EQ(field2.Get(i)[0], 'a' + i); + } +} + +TEST(RepeatedPtrField, SwapLargeLarge) { + RepeatedPtrField field1; + RepeatedPtrField field2; + + field1.Add()->assign("foo"); + field1.Add()->assign("bar"); + for (int i = 0; i < 16; i++) { + *field1.Add() += 'A' + i; + *field2.Add() += 'a' + i; + } + field2.Swap(&field1); + + EXPECT_EQ(field1.size(), 16); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(field1.Get(i).size(), 1); + EXPECT_EQ(field1.Get(i)[0], 'a' + i); + } + EXPECT_EQ(field2.size(), 18); + EXPECT_EQ(field2.Get(0), "foo"); + EXPECT_EQ(field2.Get(1), "bar"); + for (int i = 2; i < 18; i++) { + EXPECT_EQ(field2.Get(i).size(), 1); + EXPECT_EQ(field2.Get(i)[0], 'A' + i - 2); + } +} + +static int ReservedSpace(RepeatedPtrField* field) { + const string* const* ptr = field->data(); + do { + field->Add(); + } while (field->data() == ptr); + + return field->size() - 1; +} + +TEST(RepeatedPtrField, ReserveMoreThanDouble) { + RepeatedPtrField field; + field.Reserve(20); + + EXPECT_EQ(20, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveLessThanDouble) { + RepeatedPtrField field; + field.Reserve(20); + field.Reserve(30); + + EXPECT_EQ(40, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveLessThanExisting) { + RepeatedPtrField field; + field.Reserve(20); + const string* const* previous_ptr = field.data(); + field.Reserve(10); + + EXPECT_EQ(previous_ptr, field.data()); + EXPECT_EQ(20, ReservedSpace(&field)); +} + +TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { + // Check that a bug is fixed: An earlier implementation of Reserve() + // failed to copy pointers to allocated-but-cleared objects, possibly + // leading to segfaults. + RepeatedPtrField field; + string* first = field.Add(); + field.RemoveLast(); + + field.Reserve(20); + EXPECT_EQ(first, field.Add()); +} + +// Clearing elements is tricky with RepeatedPtrFields since the memory for +// the elements is retained and reused. +TEST(RepeatedPtrField, ClearedElements) { + RepeatedPtrField field; + + string* original = field.Add(); + *original = "foo"; + + EXPECT_EQ(field.ClearedCount(), 0); + + field.RemoveLast(); + EXPECT_TRUE(original->empty()); + EXPECT_EQ(field.ClearedCount(), 1); + + EXPECT_EQ(field.Add(), original); // Should return same string for reuse. + + EXPECT_EQ(field.ReleaseLast(), original); // We take ownership. + EXPECT_EQ(field.ClearedCount(), 0); + + EXPECT_NE(field.Add(), original); // Should NOT return the same string. + EXPECT_EQ(field.ClearedCount(), 0); + + field.AddAllocated(original); // Give ownership back. + EXPECT_EQ(field.ClearedCount(), 0); + EXPECT_EQ(field.Mutable(1), original); + + field.Clear(); + EXPECT_EQ(field.ClearedCount(), 2); + EXPECT_EQ(field.ReleaseCleared(), original); // Take ownership again. + EXPECT_EQ(field.ClearedCount(), 1); + EXPECT_NE(field.Add(), original); + EXPECT_EQ(field.ClearedCount(), 0); + EXPECT_NE(field.Add(), original); + EXPECT_EQ(field.ClearedCount(), 0); + + field.AddCleared(original); // Give ownership back, but as a cleared object. + EXPECT_EQ(field.ClearedCount(), 1); + EXPECT_EQ(field.Add(), original); + EXPECT_EQ(field.ClearedCount(), 0); +} + +// Test all code paths in AddAllocated(). +TEST(RepeatedPtrField, AddAlocated) { + RepeatedPtrField field; + while (field.size() < field.Capacity()) { + field.Add()->assign("filler"); + } + + int index = field.size(); + + // First branch: Field is at capacity with no cleared objects. + string* foo = new string("foo"); + field.AddAllocated(foo); + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(0, field.ClearedCount()); + EXPECT_EQ(foo, &field.Get(index)); + + // Last branch: Field is not at capacity and there are no cleared objects. + string* bar = new string("bar"); + field.AddAllocated(bar); + ++index; + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(0, field.ClearedCount()); + EXPECT_EQ(bar, &field.Get(index)); + + // Third branch: Field is not at capacity and there are no cleared objects. + field.RemoveLast(); + string* baz = new string("baz"); + field.AddAllocated(baz); + EXPECT_EQ(index + 1, field.size()); + EXPECT_EQ(1, field.ClearedCount()); + EXPECT_EQ(baz, &field.Get(index)); + + // Second branch: Field is at capacity but has some cleared objects. + while (field.size() < field.Capacity()) { + field.Add()->assign("filler2"); + } + field.RemoveLast(); + index = field.size(); + string* qux = new string("qux"); + field.AddAllocated(qux); + EXPECT_EQ(index + 1, field.size()); + // We should have discarded the cleared object. + EXPECT_EQ(0, field.ClearedCount()); + EXPECT_EQ(qux, &field.Get(index)); +} + +TEST(RepeatedPtrField, MergeFrom) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.MergeFrom(source); + + ASSERT_EQ(5, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); + EXPECT_EQ("3", destination.Get(2)); + EXPECT_EQ("4", destination.Get(3)); + EXPECT_EQ("5", destination.Get(4)); +} + +TEST(RepeatedPtrField, CopyFrom) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, CopyConstruct) { + RepeatedPtrField source; + source.Add()->assign("1"); + source.Add()->assign("2"); + + RepeatedPtrField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_String) { + vector values; + values.push_back("1"); + values.push_back("2"); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0], field.Get(0)); + EXPECT_EQ(values[1], field.Get(1)); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0], other.Get(0)); + EXPECT_EQ(values[1], other.Get(1)); +} + +TEST(RepeatedPtrField, IteratorConstruct_Proto) { + typedef TestAllTypes::NestedMessage Nested; + vector values; + values.push_back(Nested()); + values.back().set_bb(1); + values.push_back(Nested()); + values.back().set_bb(2); + + RepeatedPtrField field(values.begin(), values.end()); + ASSERT_EQ(values.size(), field.size()); + EXPECT_EQ(values[0].bb(), field.Get(0).bb()); + EXPECT_EQ(values[1].bb(), field.Get(1).bb()); + + RepeatedPtrField other(field.begin(), field.end()); + ASSERT_EQ(values.size(), other.size()); + EXPECT_EQ(values[0].bb(), other.Get(0).bb()); + EXPECT_EQ(values[1].bb(), other.Get(1).bb()); +} + +TEST(RepeatedPtrField, CopyAssign) { + RepeatedPtrField source, destination; + source.Add()->assign("4"); + source.Add()->assign("5"); + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination = source; + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, SelfAssign) { + // Verify that assignment to self does not destroy data. + RepeatedPtrField source, *p; + p = &source; + source.Add()->assign("7"); + source.Add()->assign("8"); + + *p = source; + + ASSERT_EQ(2, source.size()); + EXPECT_EQ("7", source.Get(0)); + EXPECT_EQ("8", source.Get(1)); +} + +TEST(RepeatedPtrField, MutableDataIsMutable) { + RepeatedPtrField field; + *field.Add() = "1"; + EXPECT_EQ("1", field.Get(0)); + // The fact that this line compiles would be enough, but we'll check the + // value anyway. + string** data = field.mutable_data(); + **data = "2"; + EXPECT_EQ("2", field.Get(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. + for (int sz = 0; sz < 10; ++sz) { + for (int num = 0; num <= sz; ++num) { + for (int start = 0; start < sz - num; ++start) { + for (int extra = 0; extra < 4; ++extra) { + vector subject; + + // Create an array with "sz" elements and "extra" cleared elements. + RepeatedPtrField field; + for (int i = 0; i < sz + extra; ++i) { + subject.push_back(new string()); + field.AddAllocated(subject[i]); + } + EXPECT_EQ(field.size(), sz + extra); + for (int i = 0; i < extra; ++i) + field.RemoveLast(); + EXPECT_EQ(field.size(), sz); + EXPECT_EQ(field.ClearedCount(), extra); + + // Create a catcher array and call ExtractSubrange. + string* catcher[10]; + for (int i = 0; i < 10; ++i) + catcher[i] = NULL; + field.ExtractSubrange(start, num, catcher); + + // Does the resulting array have the right size? + EXPECT_EQ(field.size(), sz - num); + + // Were the removed elements extracted into the catcher array? + for (int i = 0; i < num; ++i) + EXPECT_EQ(catcher[i], subject[start + i]); + EXPECT_EQ(NULL, catcher[num]); + + // Does the resulting array contain the right values? + for (int i = 0; i < start; ++i) + EXPECT_EQ(field.Mutable(i), subject[i]); + for (int i = start; i < field.size(); ++i) + EXPECT_EQ(field.Mutable(i), subject[i + num]); + + // Reinstate the cleared elements. + EXPECT_EQ(field.ClearedCount(), extra); + for (int i = 0; i < extra; ++i) + field.Add(); + EXPECT_EQ(field.ClearedCount(), 0); + EXPECT_EQ(field.size(), sz - num + extra); + + // Make sure the extra elements are all there (in some order). + for (int i = sz; i < sz + extra; ++i) { + int count = 0; + for (int j = sz; j < sz + extra; ++j) { + if (field.Mutable(j - num) == subject[i]) + count += 1; + } + EXPECT_EQ(count, 1); + } + + // Release the caught elements. + for (int i = 0; i < num; ++i) + delete catcher[i]; + } + } + } + } +} + +TEST(RepeatedPtrField, DeleteSubrange) { + // DeleteSubrange is a trivial extension of ExtendSubrange. +} + +// =================================================================== + +// Iterator tests stolen from net/proto/proto-array_unittest. +class RepeatedFieldIteratorTest : public testing::Test { + protected: + virtual void SetUp() { + for (int i = 0; i < 3; ++i) { + proto_array_.Add(i); + } + } + + RepeatedField proto_array_; +}; + +TEST_F(RepeatedFieldIteratorTest, Convertible) { + RepeatedField::iterator iter = proto_array_.begin(); + RepeatedField::const_iterator c_iter = iter; + RepeatedField::value_type value = *c_iter; + EXPECT_EQ(0, value); +} + +TEST_F(RepeatedFieldIteratorTest, MutableIteration) { + RepeatedField::iterator iter = proto_array_.begin(); + EXPECT_EQ(0, *iter); + ++iter; + EXPECT_EQ(1, *iter++); + EXPECT_EQ(2, *iter); + ++iter; + EXPECT_TRUE(proto_array_.end() == iter); + + EXPECT_EQ(2, *(proto_array_.end() - 1)); +} + +TEST_F(RepeatedFieldIteratorTest, ConstIteration) { + const RepeatedField& const_proto_array = proto_array_; + RepeatedField::const_iterator iter = const_proto_array.begin(); + EXPECT_EQ(0, *iter); + ++iter; + EXPECT_EQ(1, *iter++); + EXPECT_EQ(2, *iter); + ++iter; + EXPECT_TRUE(proto_array_.end() == iter); + EXPECT_EQ(2, *(proto_array_.end() - 1)); +} + +TEST_F(RepeatedFieldIteratorTest, Mutation) { + RepeatedField::iterator iter = proto_array_.begin(); + *iter = 7; + EXPECT_EQ(7, proto_array_.Get(0)); +} + +// ------------------------------------------------------------------- + +class RepeatedPtrFieldIteratorTest : public testing::Test { + protected: + virtual void SetUp() { + proto_array_.Add()->assign("foo"); + proto_array_.Add()->assign("bar"); + proto_array_.Add()->assign("baz"); + } + + RepeatedPtrField proto_array_; +}; + +TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator c_iter = iter; + RepeatedPtrField::value_type value = *c_iter; + EXPECT_EQ("foo", value); +} + +TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_TRUE(proto_array_.end() == iter); + EXPECT_EQ("baz", *(--proto_array_.end())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ConstIteration) { + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_iterator iter = const_proto_array.begin(); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_TRUE(const_proto_array.end() == iter); + EXPECT_EQ("baz", *(--const_proto_array.end())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, MutableReverseIteration) { + RepeatedPtrField::reverse_iterator iter = proto_array_.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(proto_array_.rend() == iter); + EXPECT_EQ("foo", *(--proto_array_.rend())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, ConstReverseIteration) { + const RepeatedPtrField& const_proto_array = proto_array_; + RepeatedPtrField::const_reverse_iterator iter + = const_proto_array.rbegin(); + EXPECT_EQ("baz", *iter); + ++iter; + EXPECT_EQ("bar", *(iter++)); + EXPECT_EQ("foo", *iter); + ++iter; + EXPECT_TRUE(const_proto_array.rend() == iter); + EXPECT_EQ("foo", *(--const_proto_array.rend())); +} + +TEST_F(RepeatedPtrFieldIteratorTest, RandomAccess) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + RepeatedPtrField::iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", iter[2]); + EXPECT_EQ("baz", *(iter + 2)); + EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, Comparable) { + RepeatedPtrField::const_iterator iter = proto_array_.begin(); + RepeatedPtrField::const_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +// Uninitialized iterator does not point to any of the RepeatedPtrField. +TEST_F(RepeatedPtrFieldIteratorTest, UninitializedIterator) { + RepeatedPtrField::iterator iter; + EXPECT_TRUE(iter != proto_array_.begin()); + EXPECT_TRUE(iter != proto_array_.begin() + 1); + EXPECT_TRUE(iter != proto_array_.begin() + 2); + EXPECT_TRUE(iter != proto_array_.begin() + 3); + EXPECT_TRUE(iter != proto_array_.end()); +} + +TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { + proto_array_.Clear(); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("x"); + proto_array_.Add()->assign("y"); + + string v = "f"; + RepeatedPtrField::const_iterator it = + lower_bound(proto_array_.begin(), proto_array_.end(), v); + + EXPECT_EQ(*it, "n"); + EXPECT_TRUE(it == proto_array_.begin() + 3); +} + +TEST_F(RepeatedPtrFieldIteratorTest, Mutation) { + RepeatedPtrField::iterator iter = proto_array_.begin(); + *iter = "qux"; + EXPECT_EQ("qux", proto_array_.Get(0)); +} + +// ------------------------------------------------------------------- + +class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { + protected: + virtual void SetUp() { + proto_array_.Add()->assign("foo"); + proto_array_.Add()->assign("bar"); + proto_array_.Add()->assign("baz"); + const_proto_array_ = &proto_array_; + } + + RepeatedPtrField proto_array_; + const RepeatedPtrField* const_proto_array_; +}; + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + (void) iter; +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + (void) iter; +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + EXPECT_EQ("foo", **iter); + ++iter; + EXPECT_EQ("bar", **(iter++)); + EXPECT_EQ("baz", **iter); + ++iter; + EXPECT_TRUE(proto_array_.pointer_end() == iter); + EXPECT_EQ("baz", **(--proto_array_.pointer_end())); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutableConstPtrIteration) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + EXPECT_EQ("foo", **iter); + ++iter; + EXPECT_EQ("bar", **(iter++)); + EXPECT_EQ("baz", **iter); + ++iter; + EXPECT_TRUE(const_proto_array_->pointer_end() == iter); + EXPECT_EQ("baz", **(--const_proto_array_->pointer_end())); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomPtrAccess) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + RepeatedPtrField::pointer_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", *iter[2]); + EXPECT_EQ("baz", **(iter + 2)); + EXPECT_EQ(3, proto_array_.end() - proto_array_.begin()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, RandomConstPtrAccess) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter; + ++iter2; + ++iter2; + EXPECT_TRUE(iter + 2 == iter2); + EXPECT_TRUE(iter == iter2 - 2); + EXPECT_EQ("baz", *iter[2]); + EXPECT_EQ("baz", **(iter + 2)); + EXPECT_EQ(3, const_proto_array_->end() - const_proto_array_->begin()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparablePtr) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + RepeatedPtrField::pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, ComparableConstPtr) { + RepeatedPtrField::const_pointer_iterator iter = + const_proto_array_->pointer_begin(); + RepeatedPtrField::const_pointer_iterator iter2 = iter + 1; + EXPECT_TRUE(iter == iter); + EXPECT_TRUE(iter != iter2); + EXPECT_TRUE(iter < iter2); + EXPECT_TRUE(iter <= iter2); + EXPECT_TRUE(iter <= iter); + EXPECT_TRUE(iter2 > iter); + EXPECT_TRUE(iter2 >= iter); + EXPECT_TRUE(iter >= iter); +} + +// Uninitialized iterator does not point to any of the RepeatedPtrOverPtrs. +// Dereferencing an uninitialized iterator crashes the process. +TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedPtrIterator) { + RepeatedPtrField::pointer_iterator iter; + EXPECT_TRUE(iter != proto_array_.pointer_begin()); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 1); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 2); + EXPECT_TRUE(iter != proto_array_.pointer_begin() + 3); + EXPECT_TRUE(iter != proto_array_.pointer_end()); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, UninitializedConstPtrIterator) { + RepeatedPtrField::const_pointer_iterator iter; + EXPECT_TRUE(iter != const_proto_array_->pointer_begin()); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 1); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 2); + EXPECT_TRUE(iter != const_proto_array_->pointer_begin() + 3); + EXPECT_TRUE(iter != const_proto_array_->pointer_end()); +} + +// This comparison functor is required by the tests for RepeatedPtrOverPtrs. +// They operate on strings and need to compare strings as strings in +// any stl algorithm, even though the iterator returns a pointer to a string +// - i.e. *iter has type string*. +struct StringLessThan { + bool operator()(const string* z, const string& y) { + return *z < y; + } + bool operator()(const string* z, const string* y) { + return *z < *y; + } +}; + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { + proto_array_.Clear(); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("x"); + proto_array_.Add()->assign("y"); + + { + string v = "f"; + RepeatedPtrField::pointer_iterator it = + lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), + &v, StringLessThan()); + + GOOGLE_CHECK(*it != NULL); + + EXPECT_EQ(**it, "n"); + EXPECT_TRUE(it == proto_array_.pointer_begin() + 3); + } + { + string v = "f"; + RepeatedPtrField::const_pointer_iterator it = + lower_bound(const_proto_array_->pointer_begin(), + const_proto_array_->pointer_end(), + &v, StringLessThan()); + + GOOGLE_CHECK(*it != NULL); + + EXPECT_EQ(**it, "n"); + EXPECT_TRUE(it == const_proto_array_->pointer_begin() + 3); + } +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrMutation) { + RepeatedPtrField::pointer_iterator iter = + proto_array_.pointer_begin(); + **iter = "qux"; + EXPECT_EQ("qux", proto_array_.Get(0)); + + EXPECT_EQ("bar", proto_array_.Get(1)); + EXPECT_EQ("baz", proto_array_.Get(2)); + ++iter; + delete *iter; + *iter = new string("a"); + ++iter; + delete *iter; + *iter = new string("b"); + EXPECT_EQ("a", proto_array_.Get(1)); + EXPECT_EQ("b", proto_array_.Get(2)); +} + +TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { + proto_array_.Add()->assign("c"); + proto_array_.Add()->assign("d"); + proto_array_.Add()->assign("n"); + proto_array_.Add()->assign("p"); + proto_array_.Add()->assign("a"); + proto_array_.Add()->assign("y"); + proto_array_.Add()->assign("x"); + 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()); + EXPECT_EQ("a", proto_array_.Get(0)); + EXPECT_EQ("baz", proto_array_.Get(2)); + EXPECT_EQ("y", proto_array_.Get(9)); +} + + +// ----------------------------------------------------------------------------- +// Unit-tests for the insert iterators +// google::protobuf::RepeatedFieldBackInserter, +// google::protobuf::AllocatedRepeatedPtrFieldBackInserter +// Ported from util/gtl/proto-array-iterators_unittest. + +class RepeatedFieldInsertionIteratorsTest : public testing::Test { + protected: + std::list halves; + std::list fibonacci; + std::vector words; + typedef TestAllTypes::NestedMessage Nested; + Nested nesteds[2]; + std::vector nested_ptrs; + TestAllTypes protobuffer; + + virtual void SetUp() { + fibonacci.push_back(1); + fibonacci.push_back(1); + fibonacci.push_back(2); + fibonacci.push_back(3); + fibonacci.push_back(5); + fibonacci.push_back(8); + std::copy(fibonacci.begin(), fibonacci.end(), + RepeatedFieldBackInserter(protobuffer.mutable_repeated_int32())); + + halves.push_back(1.0); + halves.push_back(0.5); + halves.push_back(0.25); + halves.push_back(0.125); + halves.push_back(0.0625); + std::copy(halves.begin(), halves.end(), + RepeatedFieldBackInserter(protobuffer.mutable_repeated_double())); + + words.push_back("Able"); + words.push_back("was"); + words.push_back("I"); + words.push_back("ere"); + words.push_back("I"); + words.push_back("saw"); + words.push_back("Elba"); + std::copy(words.begin(), words.end(), + RepeatedFieldBackInserter(protobuffer.mutable_repeated_string())); + + nesteds[0].set_bb(17); + nesteds[1].set_bb(4711); + std::copy(&nesteds[0], &nesteds[2], + RepeatedFieldBackInserter( + protobuffer.mutable_repeated_nested_message())); + + nested_ptrs.push_back(new Nested); + nested_ptrs.back()->set_bb(170); + nested_ptrs.push_back(new Nested); + nested_ptrs.back()->set_bb(47110); + std::copy(nested_ptrs.begin(), nested_ptrs.end(), + RepeatedFieldBackInserter( + protobuffer.mutable_repeated_nested_message())); + + } + + virtual void TearDown() { + STLDeleteContainerPointers(nested_ptrs.begin(), nested_ptrs.end()); + } +}; + +TEST_F(RepeatedFieldInsertionIteratorsTest, Fibonacci) { + EXPECT_TRUE(std::equal(fibonacci.begin(), + fibonacci.end(), + protobuffer.repeated_int32().begin())); + EXPECT_TRUE(std::equal(protobuffer.repeated_int32().begin(), + protobuffer.repeated_int32().end(), + fibonacci.begin())); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, Halves) { + EXPECT_TRUE(std::equal(halves.begin(), + halves.end(), + protobuffer.repeated_double().begin())); + EXPECT_TRUE(std::equal(protobuffer.repeated_double().begin(), + protobuffer.repeated_double().end(), + halves.begin())); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, Words) { + ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); + for (int i = 0; i < words.size(); ++i) + EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, Words2) { + words.clear(); + words.push_back("sing"); + words.push_back("a"); + words.push_back("song"); + words.push_back("of"); + words.push_back("six"); + words.push_back("pence"); + protobuffer.mutable_repeated_string()->Clear(); + std::copy(words.begin(), words.end(), RepeatedPtrFieldBackInserter( + protobuffer.mutable_repeated_string())); + ASSERT_EQ(words.size(), protobuffer.repeated_string_size()); + for (int i = 0; i < words.size(); ++i) + EXPECT_EQ(words.at(i), protobuffer.repeated_string(i)); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) { + ASSERT_EQ(protobuffer.repeated_nested_message_size(), 4); + EXPECT_EQ(protobuffer.repeated_nested_message(0).bb(), 17); + EXPECT_EQ(protobuffer.repeated_nested_message(1).bb(), 4711); + EXPECT_EQ(protobuffer.repeated_nested_message(2).bb(), 170); + EXPECT_EQ(protobuffer.repeated_nested_message(3).bb(), 47110); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, + AllocatedRepeatedPtrFieldWithStringIntData) { + 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; + copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, + AllocatedRepeatedPtrFieldWithString) { + 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; + copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +} // namespace + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.cc new file mode 100644 index 000000000..caf968ca5 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.cc @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +namespace google { +namespace protobuf { + +Service::~Service() {} +RpcChannel::~RpcChannel() {} +RpcController::~RpcController() {} + +} // namespace protobuf + +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.h new file mode 100644 index 000000000..a6a7d16de --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/service.h @@ -0,0 +1,291 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// DEPRECATED: This module declares the abstract interfaces underlying proto2 +// RPC services. These are intented to be independent of any particular RPC +// implementation, so that proto2 services can be used on top of a variety +// of implementations. Starting with version 2.3.0, RPC implementations should +// not try to build on these, but should instead provide code generator plugins +// which generate code specific to the particular RPC implementation. This way +// the generated code can be more appropriate for the implementation in use +// and can avoid unnecessary layers of indirection. +// +// +// When you use the protocol compiler to compile a service definition, it +// generates two classes: An abstract interface for the service (with +// methods matching the service definition) and a "stub" implementation. +// A stub is just a type-safe wrapper around an RpcChannel which emulates a +// local implementation of the service. +// +// For example, the service definition: +// service MyService { +// rpc Foo(MyRequest) returns(MyResponse); +// } +// will generate abstract interface "MyService" and class "MyService::Stub". +// You could implement a MyService as follows: +// class MyServiceImpl : public MyService { +// public: +// MyServiceImpl() {} +// ~MyServiceImpl() {} +// +// // implements MyService --------------------------------------- +// +// void Foo(google::protobuf::RpcController* controller, +// const MyRequest* request, +// MyResponse* response, +// Closure* done) { +// // ... read request and fill in response ... +// done->Run(); +// } +// }; +// You would then register an instance of MyServiceImpl with your RPC server +// implementation. (How to do that depends on the implementation.) +// +// 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: +// MyRpcChannel channel("rpc:hostname:1234/myservice"); +// MyRpcController controller; +// MyServiceImpl::Stub stub(&channel); +// FooRequest request; +// FooRespnose response; +// +// // ... fill in request ... +// +// stub.Foo(&controller, request, &response, NewCallback(HandleResponse)); +// +// On Thread-Safety: +// +// Different RPC implementations may make different guarantees about what +// threads they may run callbacks on, and what threads the application is +// allowed to use to call the RPC system. Portable software should be ready +// for callbacks to be called on any thread, but should not try to call the +// RPC system from any thread except for the ones on which it received the +// callbacks. Realistically, though, simple software will probably want to +// use a single-threaded RPC system while high-end software will want to +// use multiple threads. RPC implementations should provide multiple +// choices. + +#ifndef GOOGLE_PROTOBUF_SERVICE_H__ +#define GOOGLE_PROTOBUF_SERVICE_H__ + +#include +#include + +namespace google { +namespace protobuf { + +// Defined in this file. +class Service; +class RpcController; +class RpcChannel; + +// Defined in other files. +class Descriptor; // descriptor.h +class ServiceDescriptor; // descriptor.h +class MethodDescriptor; // descriptor.h +class Message; // message.h + +// Abstract base interface for protocol-buffer-based RPC services. Services +// themselves are abstract interfaces (implemented either by servers or as +// stubs), but they subclass this base interface. The methods of this +// interface can be used to call the methods of the Service without knowing +// its exact type at compile time (analogous to Reflection). +class LIBPROTOBUF_EXPORT Service { + public: + inline Service() {} + virtual ~Service(); + + // When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second + // parameter to the constructor to tell it to delete its RpcChannel when + // destroyed. + enum ChannelOwnership { + STUB_OWNS_CHANNEL, + STUB_DOESNT_OWN_CHANNEL + }; + + // Get the ServiceDescriptor describing this service and its methods. + virtual const ServiceDescriptor* GetDescriptor() = 0; + + // Call a method of the service specified by MethodDescriptor. This is + // normally implemented as a simple switch() that calls the standard + // definitions of the service's methods. + // + // Preconditions: + // * method->service() == GetDescriptor() + // * request and response are of the exact same classes as the objects + // returned by GetRequestPrototype(method) and + // GetResponsePrototype(method). + // * After the call has started, the request must not be modified and the + // response must not be accessed at all until "done" is called. + // * "controller" is of the correct type for the RPC implementation being + // used by this Service. For stubs, the "correct type" depends on the + // RpcChannel which the stub is using. Server-side Service + // implementations are expected to accept whatever type of RpcController + // the server-side RPC implementation uses. + // + // Postconditions: + // * "done" will be called when the method is complete. This may be + // before CallMethod() returns or it may be at some point in the future. + // * If the RPC succeeded, "response" contains the response returned by + // the server. + // * If the RPC failed, "response"'s contents are undefined. The + // RpcController can be queried to determine if an error occurred and + // possibly to get more information about the error. + virtual void CallMethod(const MethodDescriptor* method, + RpcController* controller, + const Message* request, + Message* response, + Closure* done) = 0; + + // CallMethod() requires that the request and response passed in are of a + // particular subclass of Message. GetRequestPrototype() and + // GetResponsePrototype() get the default instances of these required types. + // You can then call Message::New() on these instances to construct mutable + // objects which you can then pass to CallMethod(). + // + // Example: + // const MethodDescriptor* method = + // service->GetDescriptor()->FindMethodByName("Foo"); + // Message* request = stub->GetRequestPrototype (method)->New(); + // Message* response = stub->GetResponsePrototype(method)->New(); + // request->ParseFromString(input); + // service->CallMethod(method, *request, response, callback); + virtual const Message& GetRequestPrototype( + const MethodDescriptor* method) const = 0; + virtual const Message& GetResponsePrototype( + const MethodDescriptor* method) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service); +}; + +// An RpcController mediates a single method call. The primary purpose of +// the controller is to provide a way to manipulate settings specific to the +// RPC implementation and to find out about RPC-level errors. +// +// The methods provided by the RpcController interface are intended to be a +// "least common denominator" set of features which we expect all +// implementations to support. Specific implementations may provide more +// advanced features (e.g. deadline propagation). +class LIBPROTOBUF_EXPORT RpcController { + public: + inline RpcController() {} + virtual ~RpcController(); + + // Client-side methods --------------------------------------------- + // These calls may be made from the client side only. Their results + // are undefined on the server side (may crash). + + // Resets the RpcController to its initial state so that it may be reused in + // a new call. Must not be called while an RPC is in progress. + virtual void Reset() = 0; + + // After a call has finished, returns true if the call failed. The possible + // reasons for failure depend on the RPC implementation. Failed() must not + // be called before a call has finished. If Failed() returns true, the + // contents of the response message are undefined. + virtual bool Failed() const = 0; + + // If Failed() is true, returns a human-readable description of the error. + virtual string ErrorText() const = 0; + + // Advises the RPC system that the caller desires that the RPC call be + // canceled. The RPC system may cancel it immediately, may wait awhile and + // then cancel it, or may not even cancel the call at all. If the call is + // canceled, the "done" callback will still be called and the RpcController + // will indicate that the call failed at that time. + virtual void StartCancel() = 0; + + // Server-side methods --------------------------------------------- + // These calls may be made from the server side only. Their results + // are undefined on the client side (may crash). + + // Causes Failed() to return true on the client side. "reason" will be + // incorporated into the message returned by ErrorText(). If you find + // you need to return machine-readable information about failures, you + // should incorporate it into your response protocol buffer and should + // NOT call SetFailed(). + virtual void SetFailed(const string& reason) = 0; + + // If true, indicates that the client canceled the RPC, so the server may + // as well give up on replying to it. The server should still call the + // final "done" callback. + virtual bool IsCanceled() const = 0; + + // Asks that the given callback be called when the RPC is canceled. The + // callback will always be called exactly once. If the RPC completes without + // being canceled, the callback will be called after completion. If the RPC + // has already been canceled when NotifyOnCancel() is called, the callback + // will be called immediately. + // + // NotifyOnCancel() must be called no more than once per request. + virtual void NotifyOnCancel(Closure* callback) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController); +}; + +// Abstract interface for an RPC channel. An RpcChannel represents a +// communication line to a Service which can be used to call that Service's +// methods. The Service may be running on another machine. Normally, you +// should not call an RpcChannel directly, but instead construct a stub Service +// wrapping it. Example: +// RpcChannel* channel = new MyRpcChannel("remotehost.example.com:1234"); +// MyService* service = new MyService::Stub(channel); +// service->MyMethod(request, &response, callback); +class LIBPROTOBUF_EXPORT RpcChannel { + public: + inline RpcChannel() {} + virtual ~RpcChannel(); + + // Call the given method of the remote service. The signature of this + // procedure looks the same as Service::CallMethod(), but the requirements + // are less strict in one important way: the request and response objects + // need not be of any specific class as long as their descriptors are + // method->input_type() and method->output_type(). + virtual void CallMethod(const MethodDescriptor* method, + RpcController* controller, + const Message* request, + Message* response, + Closure* done) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_SERVICE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops.h new file mode 100644 index 000000000..b8581fa27 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops.h @@ -0,0 +1,206 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// The routines exported by this module are subtle. If you use them, even if +// you get the code right, it will depend on careful reasoning about atomicity +// and memory ordering; it will be less readable, and harder to maintain. If +// you plan to use these routines, you should have a good reason, such as solid +// evidence that performance would otherwise suffer, or there being no +// alternative. You should assume only properties explicitly guaranteed by the +// specifications in this file. You are almost certainly _not_ writing code +// just for the x86; if you assume x86 semantics, x86 hardware bugs and +// implementations on other archtectures will cause your code to break. If you +// do not know what you are doing, avoid these routines, and use a Mutex. +// +// It is incorrect to make direct assignments to/from an atomic variable. +// You should use one of the Load or Store routines. The NoBarrier +// versions are provided when no barriers are needed: +// NoBarrier_Store() +// NoBarrier_Load() +// Although there are currently no compiler enforcement, you are encouraged +// to use these. + +// This header and the implementations for each platform (located in +// atomicops_internals_*) must be kept in sync with the upstream code (V8). + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_H_ + +// Don't include this file for people not concerned about thread safety. +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#include + +namespace google { +namespace protobuf { +namespace internal { + +typedef int32 Atomic32; +#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT +// We need to be able to go between Atomic64 and AtomicWord implicitly. This +// means Atomic64 and AtomicWord should be the same type on 64-bit. +#if defined(GOOGLE_PROTOBUF_OS_NACL) +// NaCl's intptr_t is not actually 64-bits on 64-bit! +// http://code.google.com/p/nativeclient/issues/detail?id=1162 +typedef int64 Atomic64; +#else +typedef intptr_t Atomic64; +#endif +#endif + +// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or +// Atomic64 routines below, depending on your architecture. +typedef intptr_t AtomicWord; + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); + +Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment); + +// These following lower-level operations are typically useful only to people +// implementing higher-level synchronization operations like spinlocks, +// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or +// a store with appropriate memory-ordering instructions. "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); +Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value); + +void MemoryBarrier(); +void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); +void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); +void Release_Store(volatile Atomic32* ptr, Atomic32 value); + +Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); +Atomic32 Acquire_Load(volatile const Atomic32* ptr); +Atomic32 Release_Load(volatile const Atomic32* ptr); + +// 64-bit atomic operations (only available on 64-bit processors). +#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); +Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); +Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); + +Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value); +void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); +void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); +void Release_Store(volatile Atomic64* ptr, Atomic64 value); +Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); +Atomic64 Acquire_Load(volatile const Atomic64* ptr); +Atomic64 Release_Load(volatile const Atomic64* ptr); +#endif // GOOGLE_PROTOBUF_ARCH_64_BIT + +} // namespace internal +} // namespace protobuf +} // namespace google + +// Include our platform specific implementation. +#define GOOGLE_PROTOBUF_ATOMICOPS_ERROR \ +#error "Atomic operations are not supported on your platform" + +// MSVC. +#if defined(_MSC_VER) +#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) +#include +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// Apple. +#elif defined(GOOGLE_PROTOBUF_OS_APPLE) +#include + +// GCC. +#elif defined(__GNUC__) +#if defined(GOOGLE_PROTOBUF_ARCH_IA32) || defined(GOOGLE_PROTOBUF_ARCH_X64) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_ARM) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX) +#include +#elif defined(GOOGLE_PROTOBUF_ARCH_MIPS) +#include +#elif defined(__pnacl__) +#include +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// Unknown. +#else +GOOGLE_PROTOBUF_ATOMICOPS_ERROR +#endif + +// On some platforms we need additional declarations to make AtomicWord +// compatible with our other Atomic* types. +#if defined(GOOGLE_PROTOBUF_OS_APPLE) +#include +#endif + +#undef GOOGLE_PROTOBUF_ATOMICOPS_ERROR + +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h new file mode 100644 index 000000000..1f4dedc0f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h @@ -0,0 +1,151 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. +// +// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// 0xffff0fc0 is the hard coded address of a function provided by +// the kernel which implements an atomic compare-exchange. On older +// ARM architecture revisions (pre-v6) this may be implemented using +// a syscall. This address is stable, and in active use (hard coded) +// by at least glibc-2.7 and the Android C library. +typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr); +LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = + (LinuxKernelCmpxchgFunc) 0xffff0fc0; + +typedef void (*LinuxKernelMemoryBarrierFunc)(void); +LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = + (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; + + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = *ptr; + do { + if (!pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + for (;;) { + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; + if (pLinuxKernelCmpxchg(old_value, new_value, + const_cast(ptr)) == 0) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + pLinuxKernelMemoryBarrier(); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_GCC_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h new file mode 100644 index 000000000..f05076978 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h @@ -0,0 +1,146 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ + +// For _smp_cmpxchg() +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 QNXCmpxchg(Atomic32 old_value, + Atomic32 new_value, + volatile Atomic32* ptr) { + return static_cast( + _smp_cmpxchg((volatile unsigned *)ptr, + (unsigned)old_value, + (unsigned)new_value)); +} + + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value = *ptr; + do { + if (!QNXCmpxchg(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (QNXCmpxchg(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + for (;;) { + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; + if (QNXCmpxchg(old_value, new_value, + const_cast(ptr)) == 0) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + __sync_synchronize(); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM_QNX_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h new file mode 100644 index 000000000..e9d86797b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h @@ -0,0 +1,122 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ + +// AtomicWord is a synonym for intptr_t, and Atomic32 is a synonym for int32, +// which in turn means int. On some LP32 platforms, intptr_t is an int, but +// on others, it's a long. When AtomicWord and Atomic32 are based on different +// fundamental types, their pointers are incompatible. +// +// This file defines function overloads to allow both AtomicWord and Atomic32 +// data to be used with this interface. +// +// On LP64 platforms, AtomicWord and Atomic64 are both always long, +// so this problem doesn't occur. + +#if !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + +namespace google { +namespace protobuf { +namespace internal { + +inline AtomicWord NoBarrier_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return NoBarrier_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord NoBarrier_AtomicExchange(volatile AtomicWord* ptr, + AtomicWord new_value) { + return NoBarrier_AtomicExchange( + reinterpret_cast(ptr), new_value); +} + +inline AtomicWord NoBarrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return NoBarrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Barrier_AtomicIncrement(volatile AtomicWord* ptr, + AtomicWord increment) { + return Barrier_AtomicIncrement( + reinterpret_cast(ptr), increment); +} + +inline AtomicWord Acquire_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return Acquire_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, + AtomicWord old_value, + AtomicWord new_value) { + return Release_CompareAndSwap( + reinterpret_cast(ptr), old_value, new_value); +} + +inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { + NoBarrier_Store(reinterpret_cast(ptr), value); +} + +inline void Acquire_Store(volatile AtomicWord* ptr, AtomicWord value) { + return Acquire_Store(reinterpret_cast(ptr), value); +} + +inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { + return Release_Store(reinterpret_cast(ptr), value); +} + +inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { + return NoBarrier_Load(reinterpret_cast(ptr)); +} + +inline AtomicWord Acquire_Load(volatile const AtomicWord* ptr) { + return Acquire_Load(reinterpret_cast(ptr)); +} + +inline AtomicWord Release_Load(volatile const AtomicWord* ptr) { + return Release_Load(reinterpret_cast(ptr)); +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // !defined(GOOGLE_PROTOBUF_ARCH_64_BIT) + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ATOMICWORD_COMPAT_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h new file mode 100644 index 000000000..f9b7581ad --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_macosx.h @@ -0,0 +1,225 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap32(old_value, new_value, + const_cast(ptr))); + return old_value; +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32(increment, const_cast(ptr)); +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return OSAtomicAdd32Barrier(increment, const_cast(ptr)); +} + +inline void MemoryBarrier() { + OSMemoryBarrier(); +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev_value; + do { + if (OSAtomicCompareAndSwap32Barrier(old_value, new_value, + const_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#ifdef __LP64__ + +// 64-bit implementation on 64-bit platform + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + Atomic64 old_value; + do { + old_value = *ptr; + } while (!OSAtomicCompareAndSwap64(old_value, new_value, + reinterpret_cast(ptr))); + return old_value; +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64(increment, reinterpret_cast(ptr)); +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return OSAtomicAdd64Barrier(increment, + reinterpret_cast(ptr)); +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev_value; + do { + if (OSAtomicCompareAndSwap64Barrier( + old_value, new_value, reinterpret_cast(ptr))) { + return old_value; + } + prev_value = *ptr; + } while (prev_value == old_value); + return prev_value; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + // The lib kern interface does not distinguish between + // Acquire and Release memory barriers; they are equivalent. + return Acquire_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +#endif // defined(__LP64__) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MACOSX_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h new file mode 100644 index 000000000..dc468517a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h @@ -0,0 +1,187 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +namespace google { +namespace protobuf { +namespace internal { + +// Atomically execute: +// result = *ptr; +// if (*ptr == old_value) +// *ptr = new_value; +// return result; +// +// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". +// Always return the old value of "*ptr" +// +// This routine implies no memory barriers. +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev, tmp; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %0, %5\n" // prev = *ptr + "bne %0, %3, 2f\n" // if (prev != old_value) goto 2 + "move %2, %4\n" // tmp = new_value + "sc %2, %1\n" // *ptr = tmp (with atomic check) + "beqz %2, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + "2:\n" + ".set pop\n" + : "=&r" (prev), "=m" (*ptr), "=&r" (tmp) + : "Ir" (old_value), "r" (new_value), "m" (*ptr) + : "memory"); + return prev; +} + +// Atomically store new_value into *ptr, returning the previous value held in +// *ptr. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 temp, old; + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %1, %2\n" // old = *ptr + "move %0, %3\n" // temp = new_value + "sc %0, %2\n" // *ptr = temp (with atomic check) + "beqz %0, 1b\n" // start again on atomic error + "nop\n" // delay slot nop + ".set pop\n" + : "=&r" (temp), "=&r" (old), "=m" (*ptr) + : "r" (new_value), "m" (*ptr) + : "memory"); + + return old; +} + +// Atomically increment *ptr by "increment". Returns the new value of +// *ptr with the increment applied. This routine implies no memory barriers. +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp, temp2; + + __asm__ __volatile__(".set push\n" + ".set noreorder\n" + "1:\n" + "ll %0, %2\n" // temp = *ptr + "addu %1, %0, %3\n" // temp2 = temp + increment + "sc %1, %2\n" // *ptr = temp2 (with atomic check) + "beqz %1, 1b\n" // start again on atomic error + "addu %1, %0, %3\n" // temp2 = temp + increment + ".set pop\n" + : "=&r" (temp), "=&r" (temp2), "=m" (*ptr) + : "Ir" (increment), "m" (*ptr) + : "memory"); + // temp2 now holds the final value. + return temp2; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_AtomicIncrement(ptr, increment); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +// "Acquire" operations +// ensure that no later memory access can be reordered ahead of the operation. +// "Release" operations ensure that no previous memory access can be reordered +// after the operation. "Barrier" operations have both "Acquire" and "Release" +// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory +// access. +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + ATOMICOPS_COMPILER_BARRIER(); + Atomic32 res = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + ATOMICOPS_COMPILER_BARRIER(); + return res; +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void MemoryBarrier() { + __asm__ __volatile__("sync" : : : "memory"); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + MemoryBarrier(); + *ptr = value; +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + MemoryBarrier(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_MIPS_GCC_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_pnacl.h new file mode 100644 index 000000000..04a91a83f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_pnacl.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ + +namespace google { +namespace protobuf { +namespace internal { + +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; +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc new file mode 100644 index 000000000..07748723f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc @@ -0,0 +1,137 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 module gets enough CPU information to optimize the +// atomicops module on x86. + +#include + +#include + +// This file only makes sense with atomicops_internals_x86_gcc.h -- it +// depends on structs that are defined in that file. If atomicops.h +// doesn't sub-include that file, then we aren't needed, and shouldn't +// try to do anything. +#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ + +// Inline cpuid instruction. In PIC compilations, %ebx contains the address +// of the global offset table. To avoid breaking such executables, this code +// must preserve that register's value across cpuid instructions. +#if defined(__i386__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%ebx, %%edi\n" \ + "cpuid\n" \ + "xchg %%edi, %%ebx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#elif defined(__x86_64__) +#define cpuid(a, b, c, d, inp) \ + asm("mov %%rbx, %%rdi\n" \ + "cpuid\n" \ + "xchg %%rdi, %%rbx\n" \ + : "=a" (a), "=D" (b), "=c" (c), "=d" (d) : "a" (inp)) +#endif + +#if defined(cpuid) // initialize the struct only on x86 + +namespace google { +namespace protobuf { +namespace internal { + +// Set the flags so that code will run correctly and conservatively, so even +// if we haven't been initialized yet, we're probably single threaded, and our +// default values should hopefully be pretty safe. +struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures = { + false, // bug can't exist before process spawns multiple threads + false, // no SSE2 +}; + +namespace { + +// Initialize the AtomicOps_Internalx86CPUFeatures struct. +void AtomicOps_Internalx86CPUFeaturesInit() { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + + // Get vendor string (issue CPUID with eax = 0) + cpuid(eax, ebx, ecx, edx, 0); + char vendor[13]; + memcpy(vendor, &ebx, 4); + memcpy(vendor + 4, &edx, 4); + memcpy(vendor + 8, &ecx, 4); + vendor[12] = 0; + + // get feature flags in ecx/edx, and family/model in eax + cpuid(eax, ebx, ecx, edx, 1); + + int family = (eax >> 8) & 0xf; // family and model fields + int model = (eax >> 4) & 0xf; + if (family == 0xf) { // use extended family and model fields + family += (eax >> 20) & 0xff; + model += ((eax >> 16) & 0xf) << 4; + } + + // Opteron Rev E has a bug in which on very rare occasions a locked + // instruction doesn't act as a read-acquire barrier if followed by a + // non-locked read-modify-write instruction. Rev F has this bug in + // pre-release versions, but not in versions released to customers, + // so we test only for Rev E, which is family 15, model 32..63 inclusive. + if (strcmp(vendor, "AuthenticAMD") == 0 && // AMD + family == 15 && + 32 <= model && model <= 63) { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = true; + } else { + AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug = false; + } + + // edx bit 26 is SSE2 which we use to tell use whether we can use mfence + AtomicOps_Internalx86CPUFeatures.has_sse2 = ((edx >> 26) & 1); +} + +class AtomicOpsx86Initializer { + public: + AtomicOpsx86Initializer() { + AtomicOps_Internalx86CPUFeaturesInit(); + } +}; + +// A global to get use initialized on startup via static initialization :/ +AtomicOpsx86Initializer g_initer; + +} // namespace + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // __i386__ + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h new file mode 100644 index 000000000..5324dfbcb --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h @@ -0,0 +1,293 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// This struct is not part of the public API of this module; clients may not +// use it. +// Features of this x86. Values may not be correct before main() is run, +// but are set conservatively. +struct AtomicOps_x86CPUFeatureStruct { + bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence + // after acquire compare-and-swap. + bool has_sse2; // Processor has SSE2. +}; +extern struct AtomicOps_x86CPUFeatureStruct AtomicOps_Internalx86CPUFeatures; + +#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory") + +// 32-bit low-level operations on any platform. + +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 prev; + __asm__ __volatile__("lock; cmpxchgl %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + __asm__ __volatile__("xchgl %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + return temp + increment; +} + +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + Atomic32 temp = increment; + __asm__ __volatile__("lock; xaddl %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now holds the old value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + Atomic32 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +#if defined(__x86_64__) + +// 64-bit implementations of memory barrier can be simpler, because it +// "mfence" is guaranteed to exist. +inline void MemoryBarrier() { + __asm__ __volatile__("mfence" : : : "memory"); +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +} + +#else + +inline void MemoryBarrier() { + if (AtomicOps_Internalx86CPUFeatures.has_sse2) { + __asm__ __volatile__("mfence" : : : "memory"); + } else { // mfence is faster but not present on PIII + Atomic32 x = 0; + NoBarrier_AtomicExchange(&x, 0); // acts as a barrier on PIII + } +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + if (AtomicOps_Internalx86CPUFeatures.has_sse2) { + *ptr = value; + __asm__ __volatile__("mfence" : : : "memory"); + } else { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier on PIII + } +} +#endif + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + ATOMICOPS_COMPILER_BARRIER(); + *ptr = value; // An x86 store acts as a release barrier. + // See comments in Atomic64 version of Release_Store(), below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; // An x86 load acts as a acquire barrier. + // See comments in Atomic64 version of Release_Store(), below. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(__x86_64__) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 prev; + __asm__ __volatile__("lock; cmpxchgq %1,%2" + : "=a" (prev) + : "q" (new_value), "m" (*ptr), "0" (old_value) + : "memory"); + return prev; +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + __asm__ __volatile__("xchgq %1,%0" // The lock prefix is implicit for xchg. + : "=r" (new_value) + : "m" (*ptr), "0" (new_value) + : "memory"); + return new_value; // Now it's the previous value. +} + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + return temp + increment; +} + +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + Atomic64 temp = increment; + __asm__ __volatile__("lock; xaddq %0,%1" + : "+r" (temp), "+m" (*ptr) + : : "memory"); + // temp now contains the previous value of *ptr + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return temp + increment; +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; + MemoryBarrier(); +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + ATOMICOPS_COMPILER_BARRIER(); + + *ptr = value; // An x86 store acts as a release barrier + // for current AMD/Intel chips as of Jan 2008. + // See also Acquire_Load(), below. + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm + // + // x86 stores/loads fail to act as barriers for a few instructions (clflush + // maskmovdqu maskmovq movntdq movnti movntpd movntps movntq) but these are + // not generated by the compiler, and are rare. Users of these instructions + // need to know about cache behaviour in any case since all of these involve + // either flushing cache lines or non-temporal cache hints. +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; // An x86 load acts as a acquire barrier, + // for current AMD/Intel chips as of Jan 2008. + // See also Release_Store(), above. + ATOMICOPS_COMPILER_BARRIER(); + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + Atomic64 x = NoBarrier_CompareAndSwap(ptr, old_value, new_value); + if (AtomicOps_Internalx86CPUFeatures.has_amd_lock_mb_bug) { + __asm__ __volatile__("lfence" : : : "memory"); + } + return x; +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +#endif // defined(__x86_64__) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#undef ATOMICOPS_COMPILER_BARRIER + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_GCC_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc new file mode 100644 index 000000000..0b359796e --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc @@ -0,0 +1,112 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +// The compilation of extension_set.cc fails when windows.h is included. +// Therefore we move the code depending on windows.h to this separate cc file. + +// Don't compile this file for people not concerned about thread safety. +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#include + +#ifdef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +inline void MemoryBarrier() { + // We use MemoryBarrier from WinNT.h + ::MemoryBarrier(); +} + +Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + LONG result = InterlockedCompareExchange( + reinterpret_cast(ptr), + static_cast(new_value), + static_cast(old_value)); + return static_cast(result); +} + +Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + LONG result = InterlockedExchange( + reinterpret_cast(ptr), + static_cast(new_value)); + return static_cast(result); +} + +Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return InterlockedExchangeAdd( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +#if defined(_WIN64) + +// 64-bit low-level operations on 64-bit platform. + +Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + PVOID result = InterlockedCompareExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value), reinterpret_cast(old_value)); + return reinterpret_cast(result); +} + +Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + PVOID result = InterlockedExchangePointer( + reinterpret_cast(ptr), + reinterpret_cast(new_value)); + return reinterpret_cast(result); +} + +Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return InterlockedExchangeAdd64( + reinterpret_cast(ptr), + static_cast(increment)) + increment; +} + +#endif // defined(_WIN64) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h new file mode 100644 index 000000000..6f9869d1f --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h @@ -0,0 +1,150 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 is an internal atomic implementation, use atomicops.h instead. + +#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ +#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ + +namespace google { +namespace protobuf { +namespace internal { + +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, + Atomic32 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +#if !(defined(_MSC_VER) && _MSC_VER >= 1400) +#error "We require at least vs2005 for MemoryBarrier" +#endif + +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + // See comments in Atomic64 version of Release_Store() below. +} + +inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { + return *ptr; +} + +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; + return value; +} + +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { + MemoryBarrier(); + return *ptr; +} + +#if defined(_WIN64) + +// 64-bit low-level operations on 64-bit platform. + +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return Barrier_AtomicIncrement(ptr, increment); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; +} + +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { + NoBarrier_AtomicExchange(ptr, value); + // acts as a barrier in this implementation +} + +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { + *ptr = value; // works w/o barrier for current Intel chips as of June 2005 + + // When new chips come out, check: + // IA-32 Intel Architecture Software Developer's Manual, Volume 3: + // System Programming Guide, Chatper 7: Multiple-processor management, + // Section 7.2, Memory Ordering. + // Last seen at: + // http://developer.intel.com/design/pentium4/manuals/index_new.htm +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return *ptr; +} + +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { + Atomic64 value = *ptr; + return value; +} + +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { + MemoryBarrier(); + return *ptr; +} + +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, + Atomic64 old_value, + Atomic64 new_value) { + return NoBarrier_CompareAndSwap(ptr, old_value, new_value); +} + +#endif // defined(_WIN64) + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_X86_MSVC_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.cc new file mode 100644 index 000000000..e60450267 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.cc @@ -0,0 +1,395 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include +#include +#include +#include + +#include "config.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN // We only need minimal includes +#include +#define snprintf _snprintf // see comment in strutil.cc +#elif defined(HAVE_PTHREAD) +#include +#else +#error "No suitable threading library available." +#endif + +namespace google { +namespace protobuf { + +namespace internal { + +void VerifyVersion(int headerVersion, + int minLibraryVersion, + const char* filename) { + if (GOOGLE_PROTOBUF_VERSION < minLibraryVersion) { + // Library is too old for headers. + GOOGLE_LOG(FATAL) + << "This program requires version " << VersionString(minLibraryVersion) + << " of the Protocol Buffer runtime library, but the installed version " + "is " << VersionString(GOOGLE_PROTOBUF_VERSION) << ". Please update " + "your library. If you compiled the program yourself, make sure that " + "your headers are from the same version of Protocol Buffers as your " + "link-time library. (Version verification failed in \"" + << filename << "\".)"; + } + if (headerVersion < kMinHeaderVersionForLibrary) { + // Headers are too old for library. + GOOGLE_LOG(FATAL) + << "This program was compiled against version " + << VersionString(headerVersion) << " of the Protocol Buffer runtime " + "library, which is not compatible with the installed version (" + << VersionString(GOOGLE_PROTOBUF_VERSION) << "). Contact the program " + "author for an update. If you compiled the program yourself, make " + "sure that your headers are from the same version of Protocol Buffers " + "as your link-time library. (Version verification failed in \"" + << filename << "\".)"; + } +} + +string VersionString(int version) { + int major = version / 1000000; + int minor = (version / 1000) % 1000; + int micro = version % 1000; + + // 128 bytes should always be enough, but we use snprintf() anyway to be + // safe. + char buffer[128]; + snprintf(buffer, sizeof(buffer), "%d.%d.%d", major, minor, micro); + + // Guard against broken MSVC snprintf(). + buffer[sizeof(buffer)-1] = '\0'; + + return buffer; +} + +} // namespace internal + +// =================================================================== +// emulates google3/base/logging.cc + +namespace internal { + +void DefaultLogHandler(LogLevel level, const char* filename, int line, + const string& message) { + static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" }; + + // We use fprintf() instead of cerr because we want this to work at static + // initialization time. + fprintf(stderr, "[libprotobuf %s %s:%d] %s\n", + level_names[level], filename, line, message.c_str()); + fflush(stderr); // Needed on MSVC. +} + +void NullLogHandler(LogLevel level, const char* filename, int line, + const string& message) { + // Nothing. +} + +static LogHandler* log_handler_ = &DefaultLogHandler; +static int log_silencer_count_ = 0; + +static Mutex* log_silencer_count_mutex_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(log_silencer_count_init_); + +void DeleteLogSilencerCount() { + delete log_silencer_count_mutex_; + log_silencer_count_mutex_ = NULL; +} +void InitLogSilencerCount() { + log_silencer_count_mutex_ = new Mutex; + OnShutdown(&DeleteLogSilencerCount); +} +void InitLogSilencerCountOnce() { + GoogleOnceInit(&log_silencer_count_init_, &InitLogSilencerCount); +} + +LogMessage& LogMessage::operator<<(const string& value) { + message_ += value; + return *this; +} + +LogMessage& LogMessage::operator<<(const char* value) { + message_ += value; + 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(). +#undef DECLARE_STREAM_OPERATOR +#define DECLARE_STREAM_OPERATOR(TYPE, FORMAT) \ + LogMessage& LogMessage::operator<<(TYPE value) { \ + /* 128 bytes should be big enough for any of the primitive */ \ + /* values which we print with this, but well use snprintf() */ \ + /* anyway to be extra safe. */ \ + char buffer[128]; \ + snprintf(buffer, sizeof(buffer), FORMAT, value); \ + /* Guard against broken MSVC snprintf(). */ \ + buffer[sizeof(buffer)-1] = '\0'; \ + message_ += buffer; \ + return *this; \ + } + +DECLARE_STREAM_OPERATOR(char , "%c" ) +DECLARE_STREAM_OPERATOR(int , "%d" ) +DECLARE_STREAM_OPERATOR(uint , "%u" ) +DECLARE_STREAM_OPERATOR(long , "%ld") +DECLARE_STREAM_OPERATOR(unsigned long, "%lu") +DECLARE_STREAM_OPERATOR(double , "%g" ) +#undef DECLARE_STREAM_OPERATOR + +LogMessage::LogMessage(LogLevel level, const char* filename, int line) + : level_(level), filename_(filename), line_(line) {} +LogMessage::~LogMessage() {} + +void LogMessage::Finish() { + bool suppress = false; + + if (level_ != LOGLEVEL_FATAL) { + InitLogSilencerCountOnce(); + MutexLock lock(log_silencer_count_mutex_); + suppress = log_silencer_count_ > 0; + } + + if (!suppress) { + log_handler_(level_, filename_, line_, message_); + } + + if (level_ == LOGLEVEL_FATAL) { +#if PROTOBUF_USE_EXCEPTIONS + throw FatalException(filename_, line_, message_); +#else + abort(); +#endif + } +} + +void LogFinisher::operator=(LogMessage& other) { + other.Finish(); +} + +} // namespace internal + +LogHandler* SetLogHandler(LogHandler* new_func) { + LogHandler* old = internal::log_handler_; + if (old == &internal::NullLogHandler) { + old = NULL; + } + if (new_func == NULL) { + internal::log_handler_ = &internal::NullLogHandler; + } else { + internal::log_handler_ = new_func; + } + return old; +} + +LogSilencer::LogSilencer() { + internal::InitLogSilencerCountOnce(); + MutexLock lock(internal::log_silencer_count_mutex_); + ++internal::log_silencer_count_; +}; + +LogSilencer::~LogSilencer() { + internal::InitLogSilencerCountOnce(); + MutexLock lock(internal::log_silencer_count_mutex_); + --internal::log_silencer_count_; +}; + +// =================================================================== +// emulates google3/base/callback.cc + +Closure::~Closure() {} + +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 +// +// TODO(xiaofeng): PROTOBUF_LITTLE_ENDIAN is unfortunately defined in +// google/protobuf/io/coded_stream.h and therefore can not be used here. +// Maybe move that macro definition here in the furture. +uint32 ghtonl(uint32 x) { + union { + uint32 result; + uint8 result_array[4]; + }; + result_array[0] = static_cast(x >> 24); + result_array[1] = static_cast((x >> 16) & 0xFF); + result_array[2] = static_cast((x >> 8) & 0xFF); + result_array[3] = static_cast(x & 0xFF); + return result; +} + +// =================================================================== +// Shutdown support. + +namespace internal { + +typedef void OnShutdownFunc(); +vector* shutdown_functions = NULL; +Mutex* shutdown_functions_mutex = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); + +void InitShutdownFunctions() { + shutdown_functions = new vector; + shutdown_functions_mutex = new Mutex; +} + +inline void InitShutdownFunctionsOnce() { + GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions); +} + +void OnShutdown(void (*func)()) { + InitShutdownFunctionsOnce(); + MutexLock lock(shutdown_functions_mutex); + shutdown_functions->push_back(func); +} + +} // 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)(); + } + delete internal::shutdown_functions; + internal::shutdown_functions = NULL; + delete internal::shutdown_functions_mutex; + internal::shutdown_functions_mutex = NULL; +} + +#if PROTOBUF_USE_EXCEPTIONS +FatalException::~FatalException() throw() {} + +const char* FatalException::what() const throw() { + return message_.c_str(); +} +#endif + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.h new file mode 100644 index 000000000..f287ddfbc --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common.h @@ -0,0 +1,1223 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#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 + +#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(_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 { + +#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS +#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#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 + +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 2005000 + +// The minimum library version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2005000 + +// 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 = 2005000; + +// The minimum protoc version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2005000 + +// The minimum header version which works with the current version of +// protoc. This constant should only be used in VerifyVersion(). +static const int kMinHeaderVersionForProtoc = 2005000; + +// 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/base/port.h + +typedef unsigned int uint; + +#ifdef _MSC_VER +typedef __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 +#define GOOGLE_LONGLONG(x) x##LL +#define GOOGLE_ULONGLONG(x) x##ULL +#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 + +#ifndef GOOGLE_ATTRIBUTE_DEPRECATED +#ifdef __GNUC__ +// If the method/variable/type is used anywhere, produce a warning. +#define GOOGLE_ATTRIBUTE_DEPRECATED __attribute__((deprecated)) +#else +#define GOOGLE_ATTRIBUTE_DEPRECATED +#endif +#endif + +#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 +#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 + +// =================================================================== +// 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))))) + +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); +} + +} // 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; + +// 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 +#define GOOGLE_COMPILE_ASSERT(expr, msg) \ + typedef ::google::protobuf::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1] + + +// 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. + +// =================================================================== +// from google3/base/scoped_ptr.h + +namespace internal { + +// This is an implementation designed to match the anticipated future TR2 +// implementation of the scoped_ptr class, and its closely-related brethren, +// scoped_array, scoped_ptr_malloc, and make_scoped_ptr. + +template class scoped_ptr; +template class scoped_array; + +// A scoped_ptr is like a T*, except that the destructor of scoped_ptr +// automatically deletes the pointer it holds (if any). +// That is, scoped_ptr owns the T object that it points to. +// Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. +// +// The size of a scoped_ptr is small: +// sizeof(scoped_ptr) == sizeof(C*) +template +class scoped_ptr { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_ptr. + // The input parameter must be allocated with new. + explicit scoped_ptr(C* p = NULL) : ptr_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_ptr() { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != ptr_) { + enum { type_must_be_complete = sizeof(C) }; + delete ptr_; + ptr_ = p; + } + } + + // Accessors to get the owned object. + // operator* and operator-> will assert() if there is no current object. + C& operator*() const { + assert(ptr_ != NULL); + return *ptr_; + } + C* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + C* get() const { return ptr_; } + + // Comparison operators. + // These return whether two scoped_ptr refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return ptr_ == p; } + bool operator!=(C* p) const { return ptr_ != p; } + + // Swap two scoped pointers. + void swap(scoped_ptr& p2) { + C* tmp = ptr_; + ptr_ = p2.ptr_; + p2.ptr_ = tmp; + } + + // Release a pointer. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = ptr_; + ptr_ = NULL; + return retVal; + } + + private: + C* ptr_; + + // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't + // make sense, and if C2 == C, it still doesn't make sense because you should + // never have the same object owned by two different scoped_ptrs. + template bool operator==(scoped_ptr const& p2) const; + template bool operator!=(scoped_ptr const& p2) const; + + // Disallow evil constructors + scoped_ptr(const scoped_ptr&); + void operator=(const scoped_ptr&); +}; + +// scoped_array is like scoped_ptr, except that the caller must allocate +// with new [] and the destructor deletes objects with delete []. +// +// As with scoped_ptr, a scoped_array either points to an object +// or is NULL. A scoped_array owns the object that it points to. +// +// Size: sizeof(scoped_array) == sizeof(C*) +template +class scoped_array { + public: + + // The element type + typedef C element_type; + + // Constructor. Defaults to intializing with NULL. + // There is no way to create an uninitialized scoped_array. + // The input parameter must be allocated with new []. + explicit scoped_array(C* p = NULL) : array_(p) { } + + // Destructor. If there is a C object, delete it. + // We don't need to test ptr_ == NULL because C++ does that for us. + ~scoped_array() { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + } + + // Reset. Deletes the current owned object, if any. + // Then takes ownership of a new object, if given. + // this->reset(this->get()) works. + void reset(C* p = NULL) { + if (p != array_) { + enum { type_must_be_complete = sizeof(C) }; + delete[] array_; + array_ = p; + } + } + + // Get one element of the current object. + // Will assert() if there is no current object, or index i is negative. + C& operator[](std::ptrdiff_t i) const { + assert(i >= 0); + assert(array_ != NULL); + return array_[i]; + } + + // Get a pointer to the zeroth element of the current object. + // If there is no current object, return NULL. + C* get() const { + return array_; + } + + // Comparison operators. + // These return whether two scoped_array refer to the same object, not just to + // two different but equal objects. + bool operator==(C* p) const { return array_ == p; } + bool operator!=(C* p) const { return array_ != p; } + + // Swap two scoped arrays. + void swap(scoped_array& p2) { + C* tmp = array_; + array_ = p2.array_; + p2.array_ = tmp; + } + + // Release an array. + // The return value is the current pointer held by this object. + // If this object holds a NULL pointer, the return value is NULL. + // After this operation, this object will hold a NULL pointer, + // and will not own the object any more. + C* release() { + C* retVal = array_; + array_ = NULL; + return retVal; + } + + private: + C* array_; + + // Forbid comparison of different scoped_array types. + template bool operator==(scoped_array const& p2) const; + template bool operator!=(scoped_array const& p2) const; + + // Disallow evil constructors + scoped_array(const scoped_array&); + void operator=(const scoped_array&); +}; + +} // 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::scoped_ptr; +using internal::scoped_array; + +// =================================================================== +// emulates google3/base/logging.h + +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 +}; + +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<<(double 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); +}; + +} // 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_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_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_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) \ + internal::CheckNotNull(__FILE__, __LINE__, "'" #A "' must not be NULL", (A)) + +#ifdef NDEBUG + +#define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) + +#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#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_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(); +}; + +// =================================================================== +// emulates google3/base/callback.h + +// 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); +}; + +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_; +}; + +} // 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); +} + +// A function which does nothing. Useful for creating no-op callbacks, e.g.: +// Closure* nothing = NewCallback(&DoNothing); +void LIBPROTOBUF_EXPORT DoNothing(); + +// =================================================================== +// emulates google3/base/mutex.h + +namespace internal { + +// A Mutex is a non-reentrant (aka non-recursive) mutex. At most one thread T +// may hold a mutex at a given time. If T attempts to Lock() the same Mutex +// while holding it, T will deadlock. +class LIBPROTOBUF_EXPORT Mutex { + public: + // Create a Mutex that is not held by anybody. + Mutex(); + + // Destructor + ~Mutex(); + + // Block if necessary until this Mutex is free, then acquire it exclusively. + void Lock(); + + // Release this Mutex. Caller must hold it exclusively. + void 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(); + + private: + struct Internal; + Internal* mInternal; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex); +}; + +// 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); +}; + +} // 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; + +// =================================================================== +// from google3/util/utf8/public/unilib.h + +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); + +} // namespace internal + +// =================================================================== +// from google3/util/endian/endian.h +LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); + +// =================================================================== +// 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. +LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary(); + +namespace internal { + +// Register a function to be called when ShutdownProtocolBuffers() is called. +LIBPROTOBUF_EXPORT void OnShutdown(void (*func)()); + +} // 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 namespace std; // Don't do this at home, kids. + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMMON_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common_unittest.cc new file mode 100644 index 000000000..43cd6d010 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/common_unittest.cc @@ -0,0 +1,357 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include +#include +#include + +#include +#include + +#include "config.h" + +namespace google { +namespace protobuf { +namespace { + +// TODO(kenton): More tests. + +#ifdef PACKAGE_VERSION // only defined when using automake, not MSVC + +TEST(VersionTest, VersionMatchesConfig) { + // Verify that the version string specified in config.h matches the one + // in common.h. The config.h version is a string which may have a suffix + // like "beta" or "rc1", so we remove that. + string version = PACKAGE_VERSION; + int pos = 0; + while (pos < version.size() && + (ascii_isdigit(version[pos]) || version[pos] == '.')) { + ++pos; + } + version.erase(pos); + + EXPECT_EQ(version, internal::VersionString(GOOGLE_PROTOBUF_VERSION)); +} + +#endif // PACKAGE_VERSION + +TEST(CommonTest, IntMinMaxConstants) { + // kint32min was declared incorrectly in the first release of protobufs. + // Ugh. + EXPECT_LT(kint32min, kint32max); + EXPECT_EQ(static_cast(kint32min), static_cast(kint32max) + 1); + EXPECT_LT(kint64min, kint64max); + EXPECT_EQ(static_cast(kint64min), static_cast(kint64max) + 1); + EXPECT_EQ(0, kuint32max + 1); + EXPECT_EQ(0, kuint64max + 1); +} + +vector captured_messages_; + +void CaptureLog(LogLevel level, const char* filename, int line, + const string& message) { + captured_messages_.push_back( + strings::Substitute("$0 $1:$2: $3", + implicit_cast(level), filename, line, message)); +} + +TEST(LoggingTest, DefaultLogging) { + CaptureTestStderr(); + int line = __LINE__; + GOOGLE_LOG(INFO ) << "A message."; + GOOGLE_LOG(WARNING) << "A warning."; + GOOGLE_LOG(ERROR ) << "An error."; + + 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", + text); +} + +TEST(LoggingTest, NullLogging) { + LogHandler* old_handler = SetLogHandler(NULL); + + CaptureTestStderr(); + GOOGLE_LOG(INFO ) << "A message."; + GOOGLE_LOG(WARNING) << "A warning."; + GOOGLE_LOG(ERROR ) << "An error."; + + EXPECT_TRUE(SetLogHandler(old_handler) == NULL); + + string text = GetCapturedTestStderr(); + EXPECT_EQ("", text); +} + +TEST(LoggingTest, CaptureLogging) { + captured_messages_.clear(); + + LogHandler* old_handler = SetLogHandler(&CaptureLog); + + int start_line = __LINE__; + GOOGLE_LOG(ERROR) << "An error."; + GOOGLE_LOG(WARNING) << "A warning."; + + EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog); + + ASSERT_EQ(2, captured_messages_.size()); + EXPECT_EQ( + "2 "__FILE__":" + SimpleItoa(start_line + 1) + ": An error.", + captured_messages_[0]); + EXPECT_EQ( + "1 "__FILE__":" + SimpleItoa(start_line + 2) + ": A warning.", + captured_messages_[1]); +} + +TEST(LoggingTest, SilenceLogging) { + captured_messages_.clear(); + + LogHandler* old_handler = SetLogHandler(&CaptureLog); + + int line1 = __LINE__; GOOGLE_LOG(INFO) << "Visible1"; + LogSilencer* silencer1 = new LogSilencer; + GOOGLE_LOG(INFO) << "Not visible."; + LogSilencer* silencer2 = new LogSilencer; + GOOGLE_LOG(INFO) << "Not visible."; + delete silencer1; + GOOGLE_LOG(INFO) << "Not visible."; + delete silencer2; + int line2 = __LINE__; GOOGLE_LOG(INFO) << "Visible2"; + + EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog); + + ASSERT_EQ(2, captured_messages_.size()); + EXPECT_EQ( + "0 "__FILE__":" + SimpleItoa(line1) + ": Visible1", + captured_messages_[0]); + EXPECT_EQ( + "0 "__FILE__":" + SimpleItoa(line2) + ": Visible2", + captured_messages_[1]); +} + +class ClosureTest : public testing::Test { + public: + void SetA123Method() { a_ = 123; } + static void SetA123Function() { current_instance_->a_ = 123; } + + void SetAMethod(int a) { a_ = a; } + void SetCMethod(string c) { c_ = c; } + + static void SetAFunction(int a) { current_instance_->a_ = a; } + static void SetCFunction(string c) { current_instance_->c_ = c; } + + void SetABMethod(int a, const char* b) { a_ = a; b_ = b; } + static void SetABFunction(int a, const char* b) { + current_instance_->a_ = a; + current_instance_->b_ = b; + } + + virtual void SetUp() { + current_instance_ = this; + a_ = 0; + b_ = NULL; + c_.clear(); + permanent_closure_ = NULL; + } + + void DeleteClosureInCallback() { + delete permanent_closure_; + } + + int a_; + const char* b_; + string c_; + Closure* permanent_closure_; + + static ClosureTest* current_instance_; +}; + +ClosureTest* ClosureTest::current_instance_ = NULL; + +TEST_F(ClosureTest, TestClosureFunction0) { + Closure* closure = NewCallback(&SetA123Function); + EXPECT_NE(123, a_); + closure->Run(); + EXPECT_EQ(123, a_); +} + +TEST_F(ClosureTest, TestClosureMethod0) { + Closure* closure = NewCallback(current_instance_, + &ClosureTest::SetA123Method); + EXPECT_NE(123, a_); + closure->Run(); + EXPECT_EQ(123, a_); +} + +TEST_F(ClosureTest, TestClosureFunction1) { + Closure* closure = NewCallback(&SetAFunction, 456); + EXPECT_NE(456, a_); + closure->Run(); + EXPECT_EQ(456, a_); +} + +TEST_F(ClosureTest, TestClosureMethod1) { + Closure* closure = NewCallback(current_instance_, + &ClosureTest::SetAMethod, 456); + EXPECT_NE(456, a_); + closure->Run(); + EXPECT_EQ(456, a_); +} + +TEST_F(ClosureTest, TestClosureFunction1String) { + Closure* closure = NewCallback(&SetCFunction, string("test")); + EXPECT_NE("test", c_); + closure->Run(); + EXPECT_EQ("test", c_); +} + +TEST_F(ClosureTest, TestClosureMethod1String) { + Closure* closure = NewCallback(current_instance_, + &ClosureTest::SetCMethod, string("test")); + EXPECT_NE("test", c_); + closure->Run(); + EXPECT_EQ("test", c_); +} + +TEST_F(ClosureTest, TestClosureFunction2) { + const char* cstr = "hello"; + Closure* closure = NewCallback(&SetABFunction, 789, cstr); + EXPECT_NE(789, a_); + EXPECT_NE(cstr, b_); + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); +} + +TEST_F(ClosureTest, TestClosureMethod2) { + const char* cstr = "hello"; + Closure* closure = NewCallback(current_instance_, + &ClosureTest::SetABMethod, 789, cstr); + EXPECT_NE(789, a_); + EXPECT_NE(cstr, b_); + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); +} + +// Repeat all of the above with NewPermanentCallback() + +TEST_F(ClosureTest, TestPermanentClosureFunction0) { + Closure* closure = NewPermanentCallback(&SetA123Function); + EXPECT_NE(123, a_); + closure->Run(); + EXPECT_EQ(123, a_); + a_ = 0; + closure->Run(); + EXPECT_EQ(123, a_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureMethod0) { + Closure* closure = NewPermanentCallback(current_instance_, + &ClosureTest::SetA123Method); + EXPECT_NE(123, a_); + closure->Run(); + EXPECT_EQ(123, a_); + a_ = 0; + closure->Run(); + EXPECT_EQ(123, a_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureFunction1) { + Closure* closure = NewPermanentCallback(&SetAFunction, 456); + EXPECT_NE(456, a_); + closure->Run(); + EXPECT_EQ(456, a_); + a_ = 0; + closure->Run(); + EXPECT_EQ(456, a_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureMethod1) { + Closure* closure = NewPermanentCallback(current_instance_, + &ClosureTest::SetAMethod, 456); + EXPECT_NE(456, a_); + closure->Run(); + EXPECT_EQ(456, a_); + a_ = 0; + closure->Run(); + EXPECT_EQ(456, a_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureFunction2) { + const char* cstr = "hello"; + Closure* closure = NewPermanentCallback(&SetABFunction, 789, cstr); + EXPECT_NE(789, a_); + EXPECT_NE(cstr, b_); + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); + a_ = 0; + b_ = NULL; + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureMethod2) { + const char* cstr = "hello"; + Closure* closure = NewPermanentCallback(current_instance_, + &ClosureTest::SetABMethod, 789, cstr); + EXPECT_NE(789, a_); + EXPECT_NE(cstr, b_); + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); + a_ = 0; + b_ = NULL; + closure->Run(); + EXPECT_EQ(789, a_); + EXPECT_EQ(cstr, b_); + delete closure; +} + +TEST_F(ClosureTest, TestPermanentClosureDeleteInCallback) { + permanent_closure_ = NewPermanentCallback((ClosureTest*) this, + &ClosureTest::DeleteClosureInCallback); + permanent_closure_->Run(); +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/hash.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/hash.h new file mode 100644 index 000000000..f7d107127 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/hash.h @@ -0,0 +1,232 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include "config.h" + +#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET) +#include HASH_MAP_H +#include HASH_SET_H +#else +#define MISSING_HASH +#include +#include +#endif + +namespace google { +namespace protobuf { + +#ifdef 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 = int > +class hash_map : public std::map { + public: + hash_map(int = 0) {} +}; + +template , + typename EqualKey = int > +class hash_set : public std::set { + public: + hash_set(int = 0) {} +}; + +#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) + +template +struct hash : public HASH_NAMESPACE::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 HASH_NAMESPACE::hash_compare { +}; + +template , + typename EqualKey = int > +class hash_map : public HASH_NAMESPACE::hash_map< + Key, Data, HashFcn> { + public: + hash_map(int = 0) {} +}; + +template , + typename EqualKey = int > +class hash_set : public HASH_NAMESPACE::hash_set< + Key, HashFcn> { + public: + hash_set(int = 0) {} +}; + +#else + +template +struct hash : public 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 + *str; + } + return result; + } +}; + +template , + typename EqualKey = std::equal_to > +class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey> { + public: + hash_map(int = 0) {} +}; + +template , + typename EqualKey = std::equal_to > +class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS< + Key, HashFcn, EqualKey> { + public: + hash_set(int = 0) {} +}; + +#endif + +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 size_t operator()(const string& a, const string& b) const { + return a < b; + } +}; + +template +struct hash > { + inline size_t operator()(const 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 size_t operator()(const pair& a, + const 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/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/map-util.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/map-util.h new file mode 100644 index 000000000..775848b9c --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/map-util.h @@ -0,0 +1,143 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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/util/gtl/map-util.h +// Author: Anton Carver + +#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ + +#include + +namespace google { +namespace protobuf { + +// Perform a lookup in a map or hash_map. +// If the key is present in the map then the value associated with that +// key is returned, otherwise the value passed as a default is returned. +template +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Perform a lookup in a map or hash_map. +// If the key is present a const pointer to the associated value is returned, +// otherwise a NULL pointer is returned. +template +const typename Collection::value_type::second_type* +FindOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Perform a lookup in a map or hash_map, assuming that the key exists. +// Crash if it does not. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Perform a lookup in a map or hash_map whose values are pointers. +// If the key is present a const pointer to the associated value is returned, +// otherwise a NULL pointer is returned. +// This function does not distinguish between a missing key and a key mapped +// to a NULL value. +template +const typename Collection::value_type::second_type +FindPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return it->second; +} + +// Change the value associated with a particular key in a map or hash_map. +// If the key is not present in the map the key and value are inserted, +// otherwise the value is updated to be a copy of the value provided. +// True indicates that an insert took place, false indicates an update. +template +bool InsertOrUpdate(Collection * const collection, + const Key& key, const Value& value) { + pair ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + // update + ret.first->second = value; + return false; + } + return true; +} + +// Insert a new key and value into a map or hash_map. +// If the key is not present in the map the key and value are +// inserted, otherwise nothing happens. True indicates that an insert +// took place, false indicates the key was already present. +template +bool InsertIfNotPresent(Collection * const collection, + const Key& key, const Value& value) { + pair ret = + collection->insert(typename Collection::value_type(key, value)); + return ret.second; +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.cc new file mode 100644 index 000000000..1e24b8552 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.cc @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// emulates google3/base/once.h +// +// This header is intended to be included only by internal .cc files and +// generated .pb.cc files. Users should not use this directly. + +#include + +#ifndef GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include + +namespace google { +namespace protobuf { + +namespace { + +void SchedYield() { +#ifdef _WIN32 + Sleep(0); +#else // POSIX + sched_yield(); +#endif +} + +} // namespace + +void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure) { + internal::AtomicWord state = internal::Acquire_Load(once); + // Fast path. The provided closure was already executed. + if (state == ONCE_STATE_DONE) { + return; + } + // The closure execution did not complete yet. The once object can be in one + // of the two following states: + // - UNINITIALIZED: We are the first thread calling this function. + // - EXECUTING_CLOSURE: Another thread is already executing the closure. + // + // First, try to change the state from UNINITIALIZED to EXECUTING_CLOSURE + // atomically. + state = internal::Acquire_CompareAndSwap( + once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_CLOSURE); + if (state == ONCE_STATE_UNINITIALIZED) { + // We are the first thread to call this function, so we have to call the + // closure. + closure->Run(); + internal::Release_Store(once, ONCE_STATE_DONE); + } else { + // Another thread has already started executing the closure. We need to + // wait until it completes the initialization. + while (state == ONCE_STATE_EXECUTING_CLOSURE) { + // Note that futex() could be used here on Linux as an improvement. + SchedYield(); + state = internal::Acquire_Load(once); + } + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.h new file mode 100644 index 000000000..7fbc117fe --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once.h @@ -0,0 +1,148 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// +// emulates google3/base/once.h +// +// This header is intended to be included only by internal .cc files and +// generated .pb.cc files. Users should not use this directly. +// +// This is basically a portable version of pthread_once(). +// +// This header declares: +// * A type called ProtobufOnceType. +// * A macro GOOGLE_PROTOBUF_DECLARE_ONCE() which declares a variable of type +// ProtobufOnceType. This is the only legal way to declare such a variable. +// The macro may only be used at the global scope (you cannot create local or +// class member variables of this type). +// * A function GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()). +// This function, when invoked multiple times given the same ProtobufOnceType +// object, will invoke init_func on the first call only, and will make sure +// none of the calls return before that first call to init_func has finished. +// * The user can provide a parameter which GoogleOnceInit() forwards to the +// user-provided function when it is called. Usage example: +// int a = 10; +// GoogleOnceInit(&my_once, &MyFunctionExpectingIntArgument, &a); +// * This implementation guarantees that ProtobufOnceType is a POD (i.e. no +// static initializer generated). +// +// This implements a way to perform lazy initialization. It's more efficient +// than using mutexes as no lock is needed if initialization has already +// happened. +// +// Example usage: +// void Init(); +// GOOGLE_PROTOBUF_DECLARE_ONCE(once_init); +// +// // Calls Init() exactly once. +// void InitOnce() { +// GoogleOnceInit(&once_init, &Init); +// } +// +// Note that if GoogleOnceInit() is called before main() has begun, it must +// only be called by the thread that will eventually call main() -- that is, +// the thread that performs dynamic initialization. In general this is a safe +// assumption since people don't usually construct threads before main() starts, +// but it is technically not guaranteed. Unfortunately, Win32 provides no way +// whatsoever to statically-initialize its synchronization primitives, so our +// only choice is to assume that dynamic initialization is single-threaded. + +#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ +#define GOOGLE_PROTOBUF_STUBS_ONCE_H__ + +#include +#include + +namespace google { +namespace protobuf { + +#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(); + } +} + +template +inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg), + Arg arg) { + if (!*once) { + *once = true; + init_func(arg); + } +} + +#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); + +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); + } +} + +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); + } +} + +#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY + +#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ + ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_ONCE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once_unittest.cc new file mode 100644 index 000000000..b8f86a0fc --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/once_unittest.cc @@ -0,0 +1,253 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace { + +class OnceInitTest : public testing::Test { + protected: + void SetUp() { + state_ = INIT_NOT_STARTED; + current_test_ = this; + } + + // Since ProtobufOnceType is only allowed to be allocated in static storage, + // each test must use a different pair of ProtobufOnceType objects which it + // must declare itself. + void SetOnces(ProtobufOnceType* once, ProtobufOnceType* recursive_once) { + once_ = once; + recursive_once_ = recursive_once; + } + + void InitOnce() { + GoogleOnceInit(once_, &InitStatic); + } + void InitRecursiveOnce() { + GoogleOnceInit(recursive_once_, &InitRecursiveStatic); + } + + void BlockInit() { init_blocker_.Lock(); } + void UnblockInit() { init_blocker_.Unlock(); } + + class TestThread { + public: + TestThread(Closure* callback) + : done_(false), joined_(false), callback_(callback) { +#ifdef _WIN32 + thread_ = CreateThread(NULL, 0, &Start, this, 0, NULL); +#else + pthread_create(&thread_, NULL, &Start, this); +#endif + } + ~TestThread() { + if (!joined_) Join(); + } + + bool IsDone() { + MutexLock lock(&done_mutex_); + return done_; + } + void Join() { + joined_ = true; +#ifdef _WIN32 + WaitForSingleObject(thread_, INFINITE); + CloseHandle(thread_); +#else + pthread_join(thread_, NULL); +#endif + } + + private: +#ifdef _WIN32 + HANDLE thread_; +#else + pthread_t thread_; +#endif + + Mutex done_mutex_; + bool done_; + bool joined_; + Closure* callback_; + +#ifdef _WIN32 + static DWORD WINAPI Start(LPVOID arg) { +#else + static void* Start(void* arg) { +#endif + reinterpret_cast(arg)->Run(); + return 0; + } + + void Run() { + callback_->Run(); + MutexLock lock(&done_mutex_); + done_ = true; + } + }; + + TestThread* RunInitOnceInNewThread() { + return new TestThread(NewCallback(this, &OnceInitTest::InitOnce)); + } + TestThread* RunInitRecursiveOnceInNewThread() { + return new TestThread(NewCallback(this, &OnceInitTest::InitRecursiveOnce)); + } + + enum State { + INIT_NOT_STARTED, + INIT_STARTED, + INIT_DONE + }; + State CurrentState() { + MutexLock lock(&mutex_); + return state_; + } + + void WaitABit() { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); +#endif + } + + private: + Mutex mutex_; + Mutex init_blocker_; + State state_; + ProtobufOnceType* once_; + ProtobufOnceType* recursive_once_; + + void Init() { + MutexLock lock(&mutex_); + EXPECT_EQ(INIT_NOT_STARTED, state_); + state_ = INIT_STARTED; + mutex_.Unlock(); + init_blocker_.Lock(); + init_blocker_.Unlock(); + mutex_.Lock(); + state_ = INIT_DONE; + } + + static OnceInitTest* current_test_; + static void InitStatic() { current_test_->Init(); } + static void InitRecursiveStatic() { current_test_->InitOnce(); } +}; + +OnceInitTest* OnceInitTest::current_test_ = NULL; + +GOOGLE_PROTOBUF_DECLARE_ONCE(simple_once); + +TEST_F(OnceInitTest, Simple) { + SetOnces(&simple_once, NULL); + + EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); + InitOnce(); + EXPECT_EQ(INIT_DONE, CurrentState()); + + // Calling again has no effect. + InitOnce(); + EXPECT_EQ(INIT_DONE, CurrentState()); +} + +GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once1); +GOOGLE_PROTOBUF_DECLARE_ONCE(recursive_once2); + +TEST_F(OnceInitTest, Recursive) { + SetOnces(&recursive_once1, &recursive_once2); + + EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); + InitRecursiveOnce(); + EXPECT_EQ(INIT_DONE, CurrentState()); +} + +GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_once); + +TEST_F(OnceInitTest, MultipleThreads) { + SetOnces(&multiple_threads_once, NULL); + + scoped_ptr threads[4]; + EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); + for (int i = 0; i < 4; i++) { + threads[i].reset(RunInitOnceInNewThread()); + } + for (int i = 0; i < 4; i++) { + threads[i]->Join(); + } + EXPECT_EQ(INIT_DONE, CurrentState()); +} + +GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once1); +GOOGLE_PROTOBUF_DECLARE_ONCE(multiple_threads_blocked_once2); + +TEST_F(OnceInitTest, MultipleThreadsBlocked) { + SetOnces(&multiple_threads_blocked_once1, &multiple_threads_blocked_once2); + + scoped_ptr threads[8]; + EXPECT_EQ(INIT_NOT_STARTED, CurrentState()); + + BlockInit(); + for (int i = 0; i < 4; i++) { + threads[i].reset(RunInitOnceInNewThread()); + } + for (int i = 4; i < 8; i++) { + threads[i].reset(RunInitRecursiveOnceInNewThread()); + } + + WaitABit(); + + // We should now have one thread blocked inside Init(), four blocked waiting + // for Init() to complete, and three blocked waiting for InitRecursive() to + // complete. + EXPECT_EQ(INIT_STARTED, CurrentState()); + UnblockInit(); + + for (int i = 0; i < 8; i++) { + threads[i]->Join(); + } + EXPECT_EQ(INIT_DONE, CurrentState()); +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/platform_macros.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/platform_macros.h new file mode 100644 index 000000000..b1df60e46 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/platform_macros.h @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_PLATFORM_MACROS_H_ +#define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ + +#include + +// Processor architecture detection. For more info on what's defined, see: +// http://msdn.microsoft.com/en-us/library/b0084kay.aspx +// http://www.agner.org/optimize/calling_conventions.pdf +// or with gcc, run: "echo | gcc -E -dM -" +#if defined(_M_X64) || defined(__x86_64__) +#define GOOGLE_PROTOBUF_ARCH_X64 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(_M_IX86) || defined(__i386__) +#define GOOGLE_PROTOBUF_ARCH_IA32 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__QNX__) +#define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__ARMEL__) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__MIPSEL__) +#define GOOGLE_PROTOBUF_ARCH_MIPS 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__pnacl__) +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(__ppc__) +#define GOOGLE_PROTOBUF_ARCH_PPC 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#else +#error Host architecture was not detected as supported by protobuf +#endif + +#if defined(__APPLE__) +#define GOOGLE_PROTOBUF_OS_APPLE +#elif defined(__native_client__) +#define GOOGLE_PROTOBUF_OS_NACL +#endif + +#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stl_util.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stl_util.h new file mode 100644 index 000000000..9021dada9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stl_util.h @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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/util/gtl/stl_util.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ + +#include + +namespace google { +namespace protobuf { + +// STLDeleteContainerPointers() +// For a range within a container of pointers, calls delete +// (non-array version) on these pointers. +// NOTE: for these three functions, we could just implement a DeleteObject +// functor and then call for_each() on the range and functor, but this +// requires us to pull in all of algorithm.h, which seems expensive. +// For hash_[multi]set, it is important that this deletes behind the iterator +// because the hash_set may call the hash function on the iterator when it is +// advanced, which could result in the hash function trying to deference a +// stale pointer. +template +void STLDeleteContainerPointers(ForwardIterator begin, + ForwardIterator end) { + while (begin != end) { + ForwardIterator temp = begin; + ++begin; + delete *temp; + } +} + +// Inside Google, this function implements a horrible, disgusting hack in which +// we reach into the string's private implementation and resize it without +// initializing the new bytes. In some cases doing this can significantly +// improve performance. However, since it's totally non-portable it has no +// place in open source code. Feel free to fill this function in with your +// own disgusting hack if you want the perf boost. +inline void STLStringResizeUninitialized(string* s, size_t new_size) { + s->resize(new_size); +} + +// Return a mutable char* pointing to a string's internal buffer, +// which may not be null-terminated. Writing through this pointer will +// modify the string. +// +// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the +// next call to a string method that invalidates iterators. +// +// As of 2006-04, there is no standard-blessed way of getting a +// mutable reference to a string's internal buffer. However, issue 530 +// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) +// proposes this as the method. According to Matt Austern, this should +// already work on all current implementations. +inline char* string_as_array(string* str) { + // DO NOT USE const_cast(str->data())! See the unittest for why. + return str->empty() ? NULL : &*str->begin(); +} + +// STLDeleteElements() deletes all the elements in an STL container and clears +// the container. This function is suitable for use with a vector, set, +// hash_set, or any other STL container which defines sensible begin(), end(), +// and clear() methods. +// +// If container is NULL, this function is a no-op. +// +// As an alternative to calling STLDeleteElements() directly, consider +// ElementDeleter (defined below), which ensures that your container's elements +// are deleted when the ElementDeleter goes out of scope. +template +void STLDeleteElements(T *container) { + if (!container) return; + STLDeleteContainerPointers(container->begin(), container->end()); + container->clear(); +} + +// Given an STL container consisting of (key, value) pairs, STLDeleteValues +// deletes all the "value" components and clears the container. Does nothing +// in the case it's given a NULL pointer. + +template +void STLDeleteValues(T *v) { + if (!v) return; + for (typename T::iterator i = v->begin(); i != v->end(); ++i) { + delete i->second; + } + v->clear(); +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.cc new file mode 100644 index 000000000..4a5b85825 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.cc @@ -0,0 +1,175 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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/base/stringprintf.cc + +#include + +#include +#include // For va_list and related operations +#include // MSVC requires this for _vsnprintf +#include +#include +#include + +namespace google { +namespace protobuf { + +#ifdef _MSC_VER +enum { IS_COMPILER_MSVC = 1 }; +#ifndef va_copy +// Define va_copy for MSVC. This is a hack, assuming va_list is simply a +// pointer into the stack and is safe to copy. +#define va_copy(dest, src) ((dest) = (src)) +#endif +#else +enum { IS_COMPILER_MSVC = 0 }; +#endif + +void StringAppendV(string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + static const int kSpaceLength = 1024; + char space[kSpaceLength]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, kSpaceLength, format, backup_ap); + va_end(backup_ap); + + if (result < kSpaceLength) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + + if (IS_COMPILER_MSVC) { + // Error or MSVC running out of space. MSVC 8.0 and higher + // can be asked about space needed with the special idiom below: + va_copy(backup_ap, ap); + result = vsnprintf(NULL, 0, format, backup_ap); + va_end(backup_ap); + } + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result+1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + + +string StringPrintf(const char* format, ...) { + va_list ap; + va_start(ap, format); + string result; + StringAppendV(&result, format, ap); + va_end(ap); + return result; +} + +const string& SStringPrintf(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + dst->clear(); + StringAppendV(dst, format, ap); + va_end(ap); + return *dst; +} + +void StringAppendF(string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +// Max arguments supported by StringPrintVector +const int kStringPrintfVectorMaxArgs = 32; + +// An empty block of zero for filler arguments. This is const so that if +// printf tries to write to it (via %n) then the program gets a SIGSEGV +// 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) { + GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) + << "StringPrintfVector currently only supports up to " + << kStringPrintfVectorMaxArgs << " arguments. " + << "Feel free to add support for more if you need it."; + + // Add filler arguments so that bogus format+args have a harder time + // crashing the program, corrupting the program (%n), + // or displaying random chunks of memory to users. + + const char* cstr[kStringPrintfVectorMaxArgs]; + for (int i = 0; i < v.size(); ++i) { + cstr[i] = v[i].c_str(); + } + for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) { + cstr[i] = &string_printf_empty_block[0]; + } + + // I do not know any way to pass kStringPrintfVectorMaxArgs arguments, + // or any way to build a va_list by hand, or any API for printf + // that accepts an array of arguments. The best I can do is stick + // this COMPILE_ASSERT right next to the actual statement. + + GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch); + return StringPrintf(format, + cstr[0], cstr[1], cstr[2], cstr[3], cstr[4], + cstr[5], cstr[6], cstr[7], cstr[8], cstr[9], + cstr[10], cstr[11], cstr[12], cstr[13], cstr[14], + cstr[15], cstr[16], cstr[17], cstr[18], cstr[19], + cstr[20], cstr[21], cstr[22], cstr[23], cstr[24], + cstr[25], cstr[26], cstr[27], cstr[28], cstr[29], + cstr[30], cstr[31]); +} +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.h new file mode 100644 index 000000000..4a03e5ff9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf.h @@ -0,0 +1,76 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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/base/stringprintf.h +// +// Printf variants that place their output in a C++ string. +// +// Usage: +// string result = StringPrintf("%d %s\n", 10, "hello"); +// SStringPrintf(&result, "%d %s\n", 10, "hello"); +// StringAppendF(&result, "%d %s\n", 20, "there"); + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H +#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + +// Return a C++ string +LIBPROTOBUF_EXPORT extern string StringPrintf(const char* format, ...); + +// Store result into a supplied string and return it +LIBPROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, const char* format, ...); + +// Append result to a supplied string +LIBPROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...); + +// Lower-level routine that takes a va_list and appends to a specified +// string. All other routines are just convenience wrappers around it. +LIBPROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, va_list ap); + +// The max arguments supported by StringPrintfVector +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); + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc new file mode 100644 index 000000000..de5ce59fa --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/stringprintf_unittest.cc @@ -0,0 +1,152 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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/base/stringprintf_unittest.cc + +#include + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace { + +TEST(StringPrintfTest, Empty) { +#if 0 + // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this: + // warning: zero-length printf format string. + // so we do not allow them in google3. + EXPECT_EQ("", StringPrintf("")); +#endif + EXPECT_EQ("", StringPrintf("%s", string().c_str())); + EXPECT_EQ("", StringPrintf("%s", "")); +} + +TEST(StringPrintfTest, Misc) { +// MSVC and mingw does not support $ format specifier. +#if !defined(_MSC_VER) && !defined(__MINGW32__) + EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123)); +#endif // !_MSC_VER +} + +TEST(StringAppendFTest, Empty) { + string value("Hello"); + const char* empty = ""; + StringAppendF(&value, "%s", empty); + EXPECT_EQ("Hello", value); +} + +TEST(StringAppendFTest, EmptyString) { + string value("Hello"); + StringAppendF(&value, "%s", ""); + EXPECT_EQ("Hello", value); +} + +TEST(StringAppendFTest, String) { + string value("Hello"); + StringAppendF(&value, " %s", "World"); + EXPECT_EQ("Hello World", value); +} + +TEST(StringAppendFTest, Int) { + string value("Hello"); + StringAppendF(&value, " %d", 123); + EXPECT_EQ("Hello 123", value); +} + +TEST(StringPrintfTest, Multibyte) { + // If we are in multibyte mode and feed invalid multibyte sequence, + // StringPrintf should return an empty string instead of running + // out of memory while trying to determine destination buffer size. + // see b/4194543. + + char* old_locale = setlocale(LC_CTYPE, NULL); + // Push locale with multibyte mode + setlocale(LC_CTYPE, "en_US.utf8"); + + const char kInvalidCodePoint[] = "\375\067s"; + string value = StringPrintf("%.*s", 3, kInvalidCodePoint); + + // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf + // returns error given an invalid codepoint. Other versions + // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim. + // We test that the output is one of the above. + EXPECT_TRUE(value.empty() || value == kInvalidCodePoint); + + // Repeat with longer string, to make sure that the dynamically + // allocated path in StringAppendV is handled correctly. + int n = 2048; + char* buf = new char[n+1]; + memset(buf, ' ', n-3); + memcpy(buf + n - 3, kInvalidCodePoint, 4); + value = StringPrintf("%.*s", n, buf); + // See GRTEv2 vs. GRTEv3 comment above. + EXPECT_TRUE(value.empty() || value == buf); + delete[] buf; + + setlocale(LC_CTYPE, old_locale); +} + +TEST(StringPrintfTest, NoMultibyte) { + // No multibyte handling, but the string contains funny chars. + char* old_locale = setlocale(LC_CTYPE, NULL); + setlocale(LC_CTYPE, "POSIX"); + string value = StringPrintf("%.*s", 3, "\375\067s"); + setlocale(LC_CTYPE, old_locale); + EXPECT_EQ("\375\067s", value); +} + +TEST(StringPrintfTest, DontOverwriteErrno) { + // Check that errno isn't overwritten unless we're printing + // something significantly larger than what people are normally + // printing in their badly written PLOG() statements. + errno = ECHILD; + string value = StringPrintf("Hello, %s!", "World"); + EXPECT_EQ(ECHILD, errno); +} + +TEST(StringPrintfTest, LargeBuf) { + // Check that the large buffer is handled correctly. + int n = 2048; + char* buf = new char[n+1]; + memset(buf, ' ', n); + buf[n] = 0; + string value = StringPrintf("%s", buf); + EXPECT_EQ(buf, value); + delete[] buf; +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid.cc new file mode 100644 index 000000000..0f6afe6dc --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid.cc @@ -0,0 +1,536 @@ +// Copyright 2005-2008 Google Inc. All Rights Reserved. +// Author: jrm@google.com (Jim Meehan) + +#include + +namespace google { +namespace protobuf { +namespace internal { + +// These four-byte entries compactly encode how many bytes 0..255 to delete +// in making a string replacement, how many bytes to add 0..255, and the offset +// 0..64k-1 of the replacement string in remap_string. +struct RemapEntry { + uint8 delete_bytes; + uint8 add_bytes; + uint16 bytes_offset; +}; + +// Exit type codes for state tables. All but the first get stuffed into +// signed one-byte entries. The first is only generated by executable code. +// To distinguish from next-state entries, these must be contiguous and +// all <= kExitNone +typedef enum { + kExitDstSpaceFull = 239, + kExitIllegalStructure, // 240 + kExitOK, // 241 + kExitReject, // ... + kExitReplace1, + kExitReplace2, + kExitReplace3, + kExitReplace21, + kExitReplace31, + kExitReplace32, + kExitReplaceOffset1, + kExitReplaceOffset2, + kExitReplace1S0, + kExitSpecial, + kExitDoAgain, + kExitRejectAlt, + kExitNone // 255 +} ExitReason; + + +// This struct represents one entire state table. The three initialized byte +// areas are state_table, remap_base, and remap_string. state0 and state0_size +// give the byte offset and length within state_table of the initial state -- +// table lookups are expected to start and end in this state, but for +// truncated UTF-8 strings, may end in a different state. These allow a quick +// test for that condition. entry_shift is 8 for tables subscripted by a full +// byte value and 6 for space-optimized tables subscripted by only six +// significant bits in UTF-8 continuation bytes. +typedef struct { + const uint32 state0; + const uint32 state0_size; + const uint32 total_size; + const int max_expand; + const int entry_shift; + const int bytes_per_entry; + const uint32 losub; + const uint32 hiadd; + const uint8* state_table; + const RemapEntry* remap_base; + const uint8* remap_string; + const uint8* fast_state; +} UTF8StateMachineObj; + +typedef UTF8StateMachineObj UTF8ScanObj; + +#define X__ (kExitIllegalStructure) +#define RJ_ (kExitReject) +#define S1_ (kExitReplace1) +#define S2_ (kExitReplace2) +#define S3_ (kExitReplace3) +#define S21 (kExitReplace21) +#define S31 (kExitReplace31) +#define S32 (kExitReplace32) +#define T1_ (kExitReplaceOffset1) +#define T2_ (kExitReplaceOffset2) +#define S11 (kExitReplace1S0) +#define SP_ (kExitSpecial) +#define D__ (kExitDoAgain) +#define RJA (kExitRejectAlt) + +// Entire table has 9 state blocks of 256 entries each +static const unsigned int utf8acceptnonsurrogates_STATE0 = 0; // state[0] +static const unsigned int utf8acceptnonsurrogates_STATE0_SIZE = 256; // =[1] +static const unsigned int utf8acceptnonsurrogates_TOTAL_SIZE = 2304; +static const unsigned int utf8acceptnonsurrogates_MAX_EXPAND_X4 = 0; +static const unsigned int utf8acceptnonsurrogates_SHIFT = 8; +static const unsigned int utf8acceptnonsurrogates_BYTES = 1; +static const unsigned int utf8acceptnonsurrogates_LOSUB = 0x20202020; +static const unsigned int utf8acceptnonsurrogates_HIADD = 0x00000000; + +static const uint8 utf8acceptnonsurrogates[] = { +// state[0] 0x000000 Byte 1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, 1, 1, 1, 1, 1, 1, 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, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 3, + 4, 5, 5, 5, 6, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[1] 0x000080 Byte 2 of 2 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[2] 0x000000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[3] 0x001000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[4] 0x000000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[5] 0x040000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[6] 0x100000 Byte 2 of 4 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[7] 0x00d000 Byte 2 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +// state[8] 0x00d800 Byte 3 of 3 +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, + +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, +RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, + +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, X__, +}; + +// Remap base[0] = (del, add, string_offset) +static const RemapEntry utf8acceptnonsurrogates_remap_base[] = { +{0, 0, 0} }; + +// Remap string[0] +static const unsigned char utf8acceptnonsurrogates_remap_string[] = { +0 }; + +static const unsigned char utf8acceptnonsurrogates_fast[256] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 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 UTF8ScanObj utf8acceptnonsurrogates_obj = { + utf8acceptnonsurrogates_STATE0, + utf8acceptnonsurrogates_STATE0_SIZE, + utf8acceptnonsurrogates_TOTAL_SIZE, + utf8acceptnonsurrogates_MAX_EXPAND_X4, + utf8acceptnonsurrogates_SHIFT, + utf8acceptnonsurrogates_BYTES, + utf8acceptnonsurrogates_LOSUB, + utf8acceptnonsurrogates_HIADD, + utf8acceptnonsurrogates, + utf8acceptnonsurrogates_remap_base, + utf8acceptnonsurrogates_remap_string, + utf8acceptnonsurrogates_fast +}; + + +#undef X__ +#undef RJ_ +#undef S1_ +#undef S2_ +#undef S3_ +#undef S21 +#undef S31 +#undef S32 +#undef T1_ +#undef T2_ +#undef S11 +#undef SP_ +#undef D__ +#undef RJA + +// Return true if current Tbl pointer is within state0 range +// Note that unsigned compare checks both ends of range simultaneously +static inline bool InStateZero(const UTF8ScanObj* st, const uint8* Tbl) { + const uint8* Tbl0 = &st->state_table[st->state0]; + return (static_cast(Tbl - Tbl0) < st->state0_size); +} + +// Scan a UTF-8 string based on state table. +// Always scan complete UTF-8 characters +// Set number of bytes scanned. Return reason for exiting +int UTF8GenericScan(const UTF8ScanObj* st, + const char * str, + int str_length, + int* bytes_consumed) { + *bytes_consumed = 0; + if (str_length == 0) return kExitOK; + + int eshift = st->entry_shift; + const uint8* isrc = reinterpret_cast(str); + const uint8* src = isrc; + const uint8* srclimit = isrc + str_length; + const uint8* srclimit8 = srclimit - 7; + const uint8* Tbl_0 = &st->state_table[st->state0]; + + DoAgain: + // Do state-table scan + int e = 0; + uint8 c; + const uint8* Tbl2 = &st->fast_state[0]; + const uint32 losub = st->losub; + const uint32 hiadd = st->hiadd; + // Check initial few bytes one at a time until 8-byte aligned + //---------------------------- + while ((((uintptr_t)src & 0x07) != 0) && + (src < srclimit) && + Tbl2[src[0]] == 0) { + src++; + } + if (((uintptr_t)src & 0x07) == 0) { + // Do fast for groups of 8 identity bytes. + // This covers a lot of 7-bit ASCII ~8x faster then the 1-byte loop, + // including slowing slightly on cr/lf/ht + //---------------------------- + while (src < srclimit8) { + uint32 s0123 = (reinterpret_cast(src))[0]; + uint32 s4567 = (reinterpret_cast(src))[1]; + src += 8; + // This is a fast range check for all bytes in [lowsub..0x80-hiadd) + uint32 temp = (s0123 - losub) | (s0123 + hiadd) | + (s4567 - losub) | (s4567 + hiadd); + if ((temp & 0x80808080) != 0) { + // We typically end up here on cr/lf/ht; src was incremented + int e0123 = (Tbl2[src[-8]] | Tbl2[src[-7]]) | + (Tbl2[src[-6]] | Tbl2[src[-5]]); + if (e0123 != 0) { + src -= 8; + break; + } // Exit on Non-interchange + e0123 = (Tbl2[src[-4]] | Tbl2[src[-3]]) | + (Tbl2[src[-2]] | Tbl2[src[-1]]); + if (e0123 != 0) { + src -= 4; + break; + } // Exit on Non-interchange + // Else OK, go around again + } + } + } + //---------------------------- + + // Byte-at-a-time scan + //---------------------------- + const uint8* Tbl = Tbl_0; + while (src < srclimit) { + c = *src; + e = Tbl[c]; + src++; + if (e >= kExitIllegalStructure) {break;} + Tbl = &Tbl_0[e << eshift]; + } + //---------------------------- + + + // Exit posibilities: + // Some exit code, !state0, back up over last char + // Some exit code, state0, back up one byte exactly + // source consumed, !state0, back up over partial char + // source consumed, state0, exit OK + // For illegal byte in state0, avoid backup up over PREVIOUS char + // For truncated last char, back up to beginning of it + + if (e >= kExitIllegalStructure) { + // Back up over exactly one byte of rejected/illegal UTF-8 character + src--; + // Back up more if needed + if (!InStateZero(st, Tbl)) { + do { + src--; + } while ((src > isrc) && ((src[0] & 0xc0) == 0x80)); + } + } else if (!InStateZero(st, Tbl)) { + // Back up over truncated UTF-8 character + e = kExitIllegalStructure; + do { + src--; + } while ((src > isrc) && ((src[0] & 0xc0) == 0x80)); + } else { + // Normal termination, source fully consumed + e = kExitOK; + } + + if (e == kExitDoAgain) { + // Loop back up to the fast scan + goto DoAgain; + } + + *bytes_consumed = src - isrc; + return e; +} + +int UTF8GenericScanFastAscii(const UTF8ScanObj* st, + const char * str, + int str_length, + int* bytes_consumed) { + *bytes_consumed = 0; + if (str_length == 0) return kExitOK; + + const uint8* isrc = reinterpret_cast(str); + const uint8* src = isrc; + const uint8* srclimit = isrc + str_length; + const uint8* srclimit8 = srclimit - 7; + int n; + int rest_consumed; + int exit_reason; + do { + // Check initial few bytes one at a time until 8-byte aligned + while ((((uintptr_t)src & 0x07) != 0) && + (src < srclimit) && (src[0] < 0x80)) { + src++; + } + if (((uintptr_t)src & 0x07) == 0) { + while ((src < srclimit8) && + (((reinterpret_cast(src)[0] | + reinterpret_cast(src)[1]) & 0x80808080) == 0)) { + src += 8; + } + } + while ((src < srclimit) && (src[0] < 0x80)) { + src++; + } + // Run state table on the rest + n = src - isrc; + exit_reason = UTF8GenericScan(st, str + n, str_length - n, &rest_consumed); + src += rest_consumed; + } while ( exit_reason == kExitDoAgain ); + + *bytes_consumed = src - isrc; + return exit_reason; +} + +// Hack: On some compilers the static tables are initialized at startup. +// We can't use them until they are initialized. However, some Protocol +// Buffer parsing happens at static init time and may try to validate +// UTF-8 strings. Since UTF-8 validation is only used for debugging +// anyway, we simply always return success if initialization hasn't +// occurred yet. +namespace { + +bool module_initialized_ = false; + +struct InitDetector { + InitDetector() { + module_initialized_ = true; + } +}; +InitDetector init_detector; + +} // namespace + +bool IsStructurallyValidUTF8(const char* buf, int len) { + if (!module_initialized_) return true; + + int bytes_consumed = 0; + UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, + buf, len, &bytes_consumed); + return (bytes_consumed == len); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid_unittest.cc new file mode 100644 index 000000000..90888885a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/structurally_valid_unittest.cc @@ -0,0 +1,40 @@ +// 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/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.cc new file mode 100644 index 000000000..917b3e9fb --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.cc @@ -0,0 +1,1211 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 // FLT_DIG and DBL_DIG +#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 { + +inline bool IsNaN(double value) { + // NaN is never equal to anything, even itself. + return value != value; +} + +// 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; + } +} + +// ---------------------------------------------------------------------- +// 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, + vector* result) { + back_insert_iterator< 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, + vector* result) { + 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 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')) + +inline int hex_digit_to_int(char c) { + /* Assume ASCII. */ + assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61); + assert(isxdigit(c)); + int x = static_cast(c); + if (x > '9') { + x += 9; + } + return x & 0xf; +} + +// 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, + 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, + vector *errors) { + scoped_array 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) { + scoped_array 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; +} + +int CEscapeString(const char* src, int src_len, char* dest, int dest_len) { + return CEscapeInternal(src, src_len, dest, dest_len, false, false); +} + +// ---------------------------------------------------------------------- +// CEscape() +// CHexEscape() +// Copies 'src' to result, 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 +// hexadecimal rather than octal sequences. +// +// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. +// ---------------------------------------------------------------------- +string CEscape(const string& src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + scoped_array dest(new char[dest_length]); + const int len = CEscapeInternal(src.data(), src.size(), + dest.get(), dest_length, false, false); + GOOGLE_DCHECK_GE(len, 0); + return string(dest.get(), len); +} + +namespace strings { + +string Utf8SafeCEscape(const string& src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + scoped_array 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 + scoped_array 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); +} + +// ---------------------------------------------------------------------- +// 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); +} + +static inline char* PlaceNum(char* p, int num, char prev_sep) { + *p-- = '0' + num % 10; + *p-- = '0' + num / 10; + *p-- = prev_sep; + return p; +} + +// ---------------------------------------------------------------------- +// 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) { + int 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 == numeric_limits::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -numeric_limits::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (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; +} + +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; +} + +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 == numeric_limits::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -numeric_limits::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (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+2, value); + + // Should never overflow; see above. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + } + + DelocalizeRadix(buffer); + return buffer; +} + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +string LocalizeRadix(const char* input, const char* radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = sprintf(temp, "%.1f", 1.5); + GOOGLE_CHECK_EQ(temp[0], '1'); + GOOGLE_CHECK_EQ(temp[size-1], '5'); + GOOGLE_CHECK_LE(size, 6); + + // Now replace the '.' in the input with it. + string result; + result.reserve(strlen(input) + size - 3); + result.append(input, radix_pos); + result.append(temp + 1, size - 2); + result.append(radix_pos + 1); + return result; +} + +double NoLocaleStrtod(const char* text, char** original_endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char* temp_endptr; + double result = strtod(text, &temp_endptr); + if (original_endptr != NULL) *original_endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + string localized = LocalizeRadix(text, temp_endptr); + const char* localized_cstr = localized.c_str(); + char* localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > + (temp_endptr - text)) { + // This attempt got further, so replacing the decimal must have helped. + // Update original_endptr to point at the right location. + if (original_endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(text); + // const_cast is necessary to match the strtod() interface. + *original_endptr = const_cast( + text + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.h new file mode 100644 index 000000000..a401c63a9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil.h @@ -0,0 +1,467 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + +#ifdef _MSC_VER +#define strtoll _strtoi64 +#define strtoull _strtoui64 +#elif defined(__DECCXX) && defined(__osf__) +// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit. +#define strtoll strtol +#define strtoull strtoul +#endif + +// ---------------------------------------------------------------------- +// ascii_isalnum() +// Check if an ASCII character is alphanumeric. We can't use ctype's +// isalnum() because it is affected by locale. This function is applied +// to identifiers in the protocol buffer language, not to natural-language +// strings, so locale should not be taken into account. +// ascii_isdigit() +// Like above, but only accepts digits. +// ---------------------------------------------------------------------- + +inline bool ascii_isalnum(char c) { + return ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + ('0' <= c && c <= '9'); +} + +inline bool ascii_isdigit(char c) { + return ('0' <= c && c <= '9'); +} + +// ---------------------------------------------------------------------- +// HasPrefixString() +// Check if a string begins with a given prefix. +// StripPrefixString() +// Given a string and a putative prefix, returns the string minus the +// prefix string if the prefix matches, otherwise the original +// string. +// ---------------------------------------------------------------------- +inline bool HasPrefixString(const string& str, + const string& prefix) { + return str.size() >= prefix.size() && + str.compare(0, prefix.size(), prefix) == 0; +} + +inline string StripPrefixString(const string& str, const string& prefix) { + if (HasPrefixString(str, prefix)) { + return str.substr(prefix.size()); + } else { + return str; + } +} + +// ---------------------------------------------------------------------- +// HasSuffixString() +// Return true if str ends in suffix. +// StripSuffixString() +// Given a string and a putative suffix, returns the string minus the +// suffix string if the suffix matches, otherwise the original +// string. +// ---------------------------------------------------------------------- +inline bool HasSuffixString(const string& str, + const string& suffix) { + return str.size() >= suffix.size() && + str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +inline string StripSuffixString(const string& str, const string& suffix) { + if (HasSuffixString(str, suffix)) { + return str.substr(0, str.size() - suffix.size()); + } else { + return str; + } +} + +// ---------------------------------------------------------------------- +// StripString +// 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. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove, + char replacewith); + +// ---------------------------------------------------------------------- +// LowerString() +// UpperString() +// Convert the characters in "s" to lowercase or uppercase. ASCII-only: +// these functions intentionally ignore locale because they are applied to +// identifiers used in the Protocol Buffer language, not to natural-language +// strings. +// ---------------------------------------------------------------------- + +inline void LowerString(string * s) { + string::iterator end = s->end(); + for (string::iterator i = s->begin(); i != end; ++i) { + // tolower() changes based on locale. We don't want this! + if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A'; + } +} + +inline void UpperString(string * s) { + string::iterator end = s->end(); + for (string::iterator i = s->begin(); i != end; ++i) { + // toupper() changes based on locale. We don't want this! + if ('a' <= *i && *i <= 'z') *i += 'A' - 'a'; + } +} + +// ---------------------------------------------------------------------- +// 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. RETURN a new string, regardless of whether the replacement +// happened or not. +// ---------------------------------------------------------------------- + +LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, + const string& newsub, bool replace_all); + +// ---------------------------------------------------------------------- +// SplitStringUsing() +// Split a string using a character delimiter. Append the components +// to 'result'. If there are consecutive delimiters, this function skips +// over all of them. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, + vector* res); + +// Split a string using one or more byte delimiters, presented +// as a nul-terminated c string. Append the components to 'result'. +// If there are consecutive delimiters, this function will return +// corresponding empty strings. If you want to drop the empty +// strings, try SplitStringUsing(). +// +// If "full" is the empty string, yields an empty string as the only value. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full, + const char* delim, + vector* result); + +// ---------------------------------------------------------------------- +// JoinStrings() +// These methods concatenate a vector of strings into a C++ string, using +// the C-string "delim" as a separator between components. There are two +// flavors of the function, one flavor returns the concatenated string, +// 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, + const char* delim, string* result); + +inline string JoinStrings(const vector& components, + const char* delim) { + string result; + JoinStrings(components, delim, &result); + return result; +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeSequences() +// Copies "source" to "dest", rewriting C-style escape sequences +// -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII +// equivalents. "dest" must be sufficiently large to hold all +// the characters in the rewritten string (i.e. at least as large +// as strlen(source) + 1 should be safe, since the replacements +// are always shorter than the original escaped sequences). It's +// safe for source and dest to be the same. RETURNS the length +// of dest. +// +// It allows hex sequences \xhh, or generally \xhhhhh with an +// arbitrary number of hex digits, but all of them together must +// specify a value of a single byte (e.g. \x0045 is equivalent +// to \x45, and \x1234 is erroneous). +// +// It also allows escape sequences of the form \uhhhh (exactly four +// hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight +// hex digits, upper or lower case) to specify a Unicode code +// point. The dest array will contain the UTF8-encoded version of +// that code-point (e.g., if source contains \u2019, then dest will +// contain the three bytes 0xE2, 0x80, and 0x99). +// +// 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 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); + +// ---------------------------------------------------------------------- +// 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. +// ---------------------------------------------------------------------- + +LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest); +LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest, + 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. +// +// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len, + char* dest, int dest_len); + +// ---------------------------------------------------------------------- +// 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. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string CEscape(const string& src); + +namespace strings { +// Like CEscape() but does not escape bytes with the upper bit set. +LIBPROTOBUF_EXPORT string Utf8SafeCEscape(const string& src); + +// Like CEscape() but uses hex (\x) escapes instead of octals. +LIBPROTOBUF_EXPORT string CHexEscape(const string& src); +} // namespace strings + +// ---------------------------------------------------------------------- +// strto32() +// strtou32() +// strto64() +// strtou64() +// Architecture-neutral plug compatible replacements for strtol() and +// strtoul(). Long's have different lengths on ILP-32 and LP-64 +// platforms, so using these is safer, from the point of view of +// overflow behavior, than using the standard libc functions. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int32 strto32_adaptor(const char *nptr, char **endptr, + int base); +LIBPROTOBUF_EXPORT uint32 strtou32_adaptor(const char *nptr, char **endptr, + int base); + +inline int32 strto32(const char *nptr, char **endptr, int base) { + if (sizeof(int32) == sizeof(long)) + return strtol(nptr, endptr, base); + else + return strto32_adaptor(nptr, endptr, base); +} + +inline uint32 strtou32(const char *nptr, char **endptr, int base) { + if (sizeof(uint32) == sizeof(unsigned long)) + return strtoul(nptr, endptr, base); + else + return strtou32_adaptor(nptr, endptr, base); +} + +// For now, long long is 64-bit on all the platforms we care about, so these +// functions can simply pass the call to strto[u]ll. +inline int64 strto64(const char *nptr, char **endptr, int base) { + GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long), + sizeof_int64_is_not_sizeof_long_long); + return strtoll(nptr, endptr, base); +} + +inline uint64 strtou64(const char *nptr, char **endptr, int base) { + GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long), + sizeof_uint64_is_not_sizeof_long_long); + return strtoull(nptr, endptr, base); +} + +// ---------------------------------------------------------------------- +// FastIntToBuffer() +// FastHexToBuffer() +// FastHex64ToBuffer() +// FastHex32ToBuffer() +// FastTimeToBuffer() +// These are intended for speed. FastIntToBuffer() assumes the +// integer is non-negative. FastHexToBuffer() puts output in +// hex rather than decimal. FastTimeToBuffer() puts the output +// into RFC822 format. +// +// FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format, +// padded to exactly 16 bytes (plus one byte for '\0') +// +// FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format, +// padded to exactly 8 bytes (plus one byte for '\0') +// +// All functions take the output buffer as an arg. +// They all return a pointer to the beginning of the output, +// which may not be the beginning of the input buffer. +// ---------------------------------------------------------------------- + +// Suggested buffer size for FastToBuffer functions. Also works with +// DoubleToBuffer() and FloatToBuffer(). +static const int kFastToBufferSize = 32; + +LIBPROTOBUF_EXPORT char* FastInt32ToBuffer(int32 i, char* buffer); +LIBPROTOBUF_EXPORT char* FastInt64ToBuffer(int64 i, char* buffer); +char* FastUInt32ToBuffer(uint32 i, char* buffer); // inline below +char* FastUInt64ToBuffer(uint64 i, char* buffer); // inline below +LIBPROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer); +LIBPROTOBUF_EXPORT char* FastHex64ToBuffer(uint64 i, char* buffer); +LIBPROTOBUF_EXPORT char* FastHex32ToBuffer(uint32 i, char* buffer); + +// at least 22 bytes long +inline char* FastIntToBuffer(int i, char* buffer) { + return (sizeof(i) == 4 ? + FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer)); +} +inline char* FastUIntToBuffer(unsigned int i, char* buffer) { + return (sizeof(i) == 4 ? + FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer)); +} +inline char* FastLongToBuffer(long i, char* buffer) { + return (sizeof(i) == 4 ? + FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer)); +} +inline char* FastULongToBuffer(unsigned long i, char* buffer) { + return (sizeof(i) == 4 ? + FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer)); +} + +// ---------------------------------------------------------------------- +// 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). +// ---------------------------------------------------------------------- + +LIBPROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32 i, char* buffer); +LIBPROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32 i, char* buffer); +LIBPROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64 i, char* buffer); +LIBPROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64 i, char* buffer); + +// Just define these in terms of the above. +inline char* FastUInt32ToBuffer(uint32 i, char* buffer) { + FastUInt32ToBufferLeft(i, buffer); + return buffer; +} +inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { + FastUInt64ToBufferLeft(i, buffer); + return buffer; +} + +// ---------------------------------------------------------------------- +// SimpleItoa() +// Description: converts an integer to a string. +// +// Return value: string +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string SimpleItoa(int i); +LIBPROTOBUF_EXPORT string SimpleItoa(unsigned int i); +LIBPROTOBUF_EXPORT string SimpleItoa(long i); +LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long i); +LIBPROTOBUF_EXPORT string SimpleItoa(long long i); +LIBPROTOBUF_EXPORT string SimpleItoa(unsigned long long i); + +// ---------------------------------------------------------------------- +// SimpleDtoa() +// SimpleFtoa() +// DoubleToBuffer() +// FloatToBuffer() +// Description: converts a double or float to a string which, if +// passed to NoLocaleStrtod(), will produce the exact same original double +// (except in case of NaN; all NaNs are considered the same value). +// We try to keep the string short but it's not guaranteed to be as +// short as possible. +// +// DoubleToBuffer() and FloatToBuffer() write the text to the given +// buffer and return it. The buffer must be at least +// kDoubleToBufferSize bytes for doubles and kFloatToBufferSize +// bytes for floats. kFastToBufferSize is also guaranteed to be large +// enough to hold either. +// +// Return value: string +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string SimpleDtoa(double value); +LIBPROTOBUF_EXPORT string SimpleFtoa(float value); + +LIBPROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer); +LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); + +// In practice, doubles should never need more than 24 bytes and floats +// should never need more than 14 (including null terminators), but we +// overestimate to be safe. +static const int kDoubleToBufferSize = 32; +static const int kFloatToBufferSize = 24; + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// Exactly like strtod(), except it always behaves as if in the "C" +// locale (i.e. decimal points must be '.'s). +// ---------------------------------------------------------------------- + +LIBPROTOBUF_EXPORT double NoLocaleStrtod(const char* text, char** endptr); + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil_unittest.cc new file mode 100644 index 000000000..b9c9253b0 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/strutil_unittest.cc @@ -0,0 +1,83 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include + +#include +#include +#include + +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, NoLocaleStrtod("1.5", NULL)); + EXPECT_EQ("1.5", SimpleDtoa(1.5)); + EXPECT_EQ("1.5", SimpleFtoa(1.5)); + + // Verify that the endptr is set correctly even if not all text was parsed. + const char* text = "1.5f"; + char* endptr; + EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); + EXPECT_EQ(3, endptr - text); + + 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, NoLocaleStrtod("1.5", NULL)); + EXPECT_EQ("1.5", SimpleDtoa(1.5)); + EXPECT_EQ("1.5", SimpleFtoa(1.5)); + EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); + EXPECT_EQ(3, endptr - text); + } + + // Return to original locale. + setlocale(LC_NUMERIC, old_locale.c_str()); +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.cc new file mode 100644 index 000000000..259245b3d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.cc @@ -0,0 +1,134 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace strings { + +using internal::SubstituteArg; + +// Returns the number of args in arg_array which were passed explicitly +// to Substitute(). +static int CountSubstituteArgs(const SubstituteArg* const* args_array) { + int count = 0; + while (args_array[count] != NULL && args_array[count]->size() != -1) { + ++count; + } + return count; +} + +string Substitute( + const char* format, + const SubstituteArg& arg0, const SubstituteArg& arg1, + const SubstituteArg& arg2, const SubstituteArg& arg3, + const SubstituteArg& arg4, const SubstituteArg& arg5, + const SubstituteArg& arg6, const SubstituteArg& arg7, + const SubstituteArg& arg8, const SubstituteArg& arg9) { + string result; + SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4, + arg5, arg6, arg7, arg8, arg9); + return result; +} + +void SubstituteAndAppend( + string* output, const char* format, + const SubstituteArg& arg0, const SubstituteArg& arg1, + const SubstituteArg& arg2, const SubstituteArg& arg3, + const SubstituteArg& arg4, const SubstituteArg& arg5, + const SubstituteArg& arg6, const SubstituteArg& arg7, + const SubstituteArg& arg8, const SubstituteArg& arg9) { + const SubstituteArg* const args_array[] = { + &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, NULL + }; + + // Determine total size needed. + int size = 0; + for (int i = 0; format[i] != '\0'; i++) { + if (format[i] == '$') { + if (ascii_isdigit(format[i+1])) { + int index = format[i+1] - '0'; + if (args_array[index]->size() == -1) { + GOOGLE_LOG(DFATAL) + << "strings::Substitute format string invalid: asked for \"$" + << index << "\", but only " << CountSubstituteArgs(args_array) + << " args were given. Full format string was: \"" + << CEscape(format) << "\"."; + return; + } + size += args_array[index]->size(); + ++i; // Skip next char. + } else if (format[i+1] == '$') { + ++size; + ++i; // Skip next char. + } else { + GOOGLE_LOG(DFATAL) + << "Invalid strings::Substitute() format string: \"" + << CEscape(format) << "\"."; + return; + } + } else { + ++size; + } + } + + if (size == 0) return; + + // Build the string. + int original_size = output->size(); + STLStringResizeUninitialized(output, original_size + size); + char* target = string_as_array(output) + original_size; + 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']; + memcpy(target, src->data(), src->size()); + target += src->size(); + ++i; // Skip next char. + } else if (format[i+1] == '$') { + *target++ = '$'; + ++i; // Skip next char. + } + } else { + *target++ = format[i]; + } + } + + GOOGLE_DCHECK_EQ(target - output->data(), output->size()); +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.h new file mode 100644 index 000000000..2581793b5 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/substitute.h @@ -0,0 +1,170 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// from google3/strings/substitute.h + +#include +#include +#include + +#ifndef GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ +#define GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ + +namespace google { +namespace protobuf { +namespace strings { + +// ---------------------------------------------------------------------- +// strings::Substitute() +// strings::SubstituteAndAppend() +// Kind of like StringPrintf, but different. +// +// Example: +// string GetMessage(string first_name, string last_name, int age) { +// return strings::Substitute("My name is $0 $1 and I am $2 years old.", +// first_name, last_name, age); +// } +// +// Differences from StringPrintf: +// * The format string does not identify the types of arguments. +// Instead, the magic of C++ deals with this for us. See below +// for a list of accepted types. +// * Substitutions in the format string are identified by a '$' +// followed by a digit. So, you can use arguments out-of-order and +// use the same argument multiple times. +// * It's much faster than StringPrintf. +// +// Supported types: +// * Strings (const char*, const string&) +// * Note that this means you do not have to add .c_str() to all of +// your strings. In fact, you shouldn't; it will be slower. +// * int32, int64, uint32, uint64: Formatted using SimpleItoa(). +// * float, double: Formatted using SimpleFtoa() and SimpleDtoa(). +// * bool: Printed as "true" or "false". +// +// SubstituteAndAppend() is like Substitute() but appends the result to +// *output. Example: +// +// string str; +// strings::SubstituteAndAppend(&str, +// "My name is $0 $1 and I am $2 years old.", +// first_name, last_name, age); +// +// Substitute() is significantly faster than StringPrintf(). For very +// large strings, it may be orders of magnitude faster. +// ---------------------------------------------------------------------- + +namespace internal { // Implementation details. + +class SubstituteArg { + public: + inline SubstituteArg(const char* value) + : text_(value), size_(strlen(text_)) {} + inline SubstituteArg(const string& value) + : text_(value.data()), size_(value.size()) {} + + // Indicates that no argument was given. + inline explicit SubstituteArg() + : text_(NULL), size_(-1) {} + + // Primitives + // We don't overload for signed and unsigned char because if people are + // explicitly declaring their chars as signed or unsigned then they are + // probably actually using them as 8-bit integers and would probably + // prefer an integer representation. But, we don't really know. So, we + // make the caller decide what to do. + inline SubstituteArg(char value) + : text_(scratch_), size_(1) { scratch_[0] = value; } + inline SubstituteArg(short value) + : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned short value) + : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(int value) + : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned int value) + : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(long value) + : text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned long value) + : text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(long long value) + : text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(unsigned long long value) + : text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(float value) + : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(double value) + : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {} + inline SubstituteArg(bool value) + : text_(value ? "true" : "false"), size_(strlen(text_)) {} + + inline const char* data() const { return text_; } + inline int size() const { return size_; } + + private: + const char* text_; + int size_; + char scratch_[kFastToBufferSize]; +}; + +} // namespace internal + +LIBPROTOBUF_EXPORT string Substitute( + const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); + +LIBPROTOBUF_EXPORT void SubstituteAndAppend( + string* output, const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); + +} // namespace strings +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util.h new file mode 100644 index 000000000..4f30ffa3b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util.h @@ -0,0 +1,138 @@ +// Copyright 2005 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. + +// ---- +// Author: lar@google.com (Laramie Leavitt) +// +// Template metaprogramming utility functions. +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// 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 +// 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 +// be included in the c++ standard. +// 2. It is not impossible that some of the boost libraries will be +// included in our own build in the future. +// Both of these outcomes means that we may be able to directly replace +// some of these with boost equivalents. +// +#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ +#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ + +namespace google { +namespace protobuf { +namespace internal { + +// Types small_ and big_ are guaranteed such that sizeof(small_) < +// sizeof(big_) +typedef char small_; + +struct big_ { + char dummy[2]; +}; + +// Identity metafunction. +template +struct identity_ { + typedef T type; +}; + +// integral_constant, defined in tr1, is a wrapper for an integer +// value. We don't really need this generality; we could get away +// with hardcoding the integer type to bool. We use the fully +// general integer_constant for compatibility with tr1. + +template +struct integral_constant { + static const T value = v; + typedef T value_type; + typedef integral_constant type; +}; + +template const T integral_constant::value; + + +// Abbreviations: true_type and false_type are structs that represent boolean +// true and false values. Also define the boost::mpl versions of those names, +// true_ and false_. +typedef integral_constant true_type; +typedef integral_constant false_type; +typedef true_type true_; +typedef false_type false_; + +// if_ is a templatized conditional statement. +// if_ is a compile time evaluation of cond. +// if_<>::type contains A if cond is true, B otherwise. +template +struct if_{ + typedef A type; +}; + +template +struct if_ { + typedef B type; +}; + + +// type_equals_ is a template type comparator, similar to Loki IsSameType. +// type_equals_::value is true iff "A" is the same type as "B". +// +// New code should prefer base::is_same, defined in base/type_traits.h. +// It is functionally identical, but is_same is the standard spelling. +template +struct type_equals_ : public false_ { +}; + +template +struct type_equals_ : public true_ { +}; + +// and_ is a template && operator. +// and_::value evaluates "A::value && B::value". +template +struct and_ : public integral_constant { +}; + +// or_ is a template || operator. +// or_::value evaluates "A::value || B::value". +template +struct or_ : public integral_constant { +}; + + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util_unittest.cc new file mode 100644 index 000000000..b1745e2bf --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/template_util_unittest.cc @@ -0,0 +1,130 @@ +// Copyright 2005 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. + +// ---- +// Author: lar@google.com (Laramie Leavitt) +// +// These tests are really compile time tests. +// If you try to step through this in a debugger +// you will not see any evaluations, merely that +// value is assigned true or false sequentially. + +#include + +#include +#include + +namespace GOOGLE_NAMESPACE = google::protobuf::internal; + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST(TemplateUtilTest, TestSize) { + EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_)); +} + +TEST(TemplateUtilTest, TestIntegralConstants) { + // test the built-in types. + EXPECT_TRUE(true_type::value); + EXPECT_FALSE(false_type::value); + + typedef integral_constant one_type; + EXPECT_EQ(1, one_type::value); +} + +TEST(TemplateUtilTest, TestTemplateIf) { + typedef if_::type if_true; + EXPECT_TRUE(if_true::value); + + typedef if_::type if_false; + EXPECT_FALSE(if_false::value); +} + +TEST(TemplateUtilTest, TestTemplateTypeEquals) { + // Check that the TemplateTypeEquals works correctly. + bool value = false; + + // Test the same type is true. + value = type_equals_::value; + EXPECT_TRUE(value); + + // Test different types are false. + value = type_equals_::value; + EXPECT_FALSE(value); + + // Test type aliasing. + typedef const int foo; + value = type_equals_::value; + EXPECT_TRUE(value); +} + +TEST(TemplateUtilTest, TestTemplateAndOr) { + // Check that the TemplateTypeEquals works correctly. + bool value = false; + + // Yes && Yes == true. + value = and_::value; + EXPECT_TRUE(value); + // Yes && No == false. + value = and_::value; + EXPECT_FALSE(value); + // No && Yes == false. + value = and_::value; + EXPECT_FALSE(value); + // No && No == false. + value = and_::value; + EXPECT_FALSE(value); + + // Yes || Yes == true. + value = or_::value; + EXPECT_TRUE(value); + // Yes || No == true. + value = or_::value; + EXPECT_TRUE(value); + // No || Yes == true. + value = or_::value; + EXPECT_TRUE(value); + // No || No == false. + value = or_::value; + EXPECT_FALSE(value); +} + +TEST(TemplateUtilTest, TestIdentity) { + EXPECT_TRUE( + (type_equals_::type, int>::value)); + EXPECT_TRUE( + (type_equals_::type, void>::value)); +} + +} // anonymous namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits.h new file mode 100644 index 000000000..e41f5e6f6 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits.h @@ -0,0 +1,336 @@ +// 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. + +// ---- +// Author: Matt Austern +// +// This code is compiled directly on many platforms, including client +// platforms like Windows, Mac, and embedded systems. Before making +// any changes here, make sure that you're not breaking any platforms. +// +// Define a small subset of tr1 type traits. The traits we define are: +// is_integral +// is_floating_point +// is_pointer +// is_enum +// is_reference +// is_pod +// has_trivial_constructor +// has_trivial_copy +// has_trivial_assign +// has_trivial_destructor +// remove_const +// remove_volatile +// remove_cv +// remove_reference +// add_reference +// remove_pointer +// is_same +// is_convertible +// We can add more type traits as required. + +#ifndef GOOGLE_PROTOBUF_TYPE_TRAITS_H_ +#define GOOGLE_PROTOBUF_TYPE_TRAITS_H_ + +#include // For pair + +#include // For true_type and false_type + +namespace google { +namespace protobuf { +namespace internal { + +template struct is_integral; +template struct is_floating_point; +template struct is_pointer; +// MSVC can't compile this correctly, and neither can gcc 3.3.5 (at least) +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +// is_enum uses is_convertible, which is not available on MSVC. +template struct is_enum; +#endif +template struct is_reference; +template struct is_pod; +template struct has_trivial_constructor; +template struct has_trivial_copy; +template struct has_trivial_assign; +template struct has_trivial_destructor; +template struct remove_const; +template struct remove_volatile; +template struct remove_cv; +template struct remove_reference; +template struct add_reference; +template struct remove_pointer; +template struct is_same; +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +template struct is_convertible; +#endif + +// is_integral is false except for the built-in integer types. A +// cv-qualified type is integral if and only if the underlying type is. +template struct is_integral : false_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#if defined(_MSC_VER) +// wchar_t is not by default a distinct type from unsigned short in +// Microsoft C. +// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx +template<> struct is_integral<__wchar_t> : true_type { }; +#else +template<> struct is_integral : true_type { }; +#endif +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#ifdef HAVE_LONG_LONG +template<> struct is_integral : true_type { }; +template<> struct is_integral : true_type { }; +#endif +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; +template struct is_integral : is_integral { }; + +// is_floating_point is false except for the built-in floating-point types. +// A cv-qualified type is integral if and only if the underlying type is. +template struct is_floating_point : false_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template<> struct is_floating_point : true_type { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; +template struct is_floating_point + : is_floating_point { }; + +// is_pointer is false except for pointer types. A cv-qualified type (e.g. +// "int* const", as opposed to "int const*") is cv-qualified if and only if +// the underlying type is. +template struct is_pointer : false_type { }; +template struct is_pointer : true_type { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; +template struct is_pointer : is_pointer { }; + +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + +namespace internal { + +template struct is_class_or_union { + template static small_ tester(void (U::*)()); + template static big_ tester(...); + static const bool value = sizeof(tester(0)) == sizeof(small_); +}; + +// is_convertible chokes if the first argument is an array. That's why +// we use add_reference here. +template struct is_enum_impl + : is_convertible::type, int> { }; + +template struct is_enum_impl : false_type { }; + +} // namespace internal + +// Specified by TR1 [4.5.1] primary type categories. + +// Implementation note: +// +// Each type is either void, integral, floating point, array, pointer, +// reference, member object pointer, member function pointer, enum, +// union or class. Out of these, only integral, floating point, reference, +// class and enum types are potentially convertible to int. Therefore, +// if a type is not a reference, integral, floating point or class and +// is convertible to int, it's a enum. Adding cv-qualification to a type +// does not change whether it's an enum. +// +// Is-convertible-to-int check is done only if all other checks pass, +// because it can't be used with some types (e.g. void or classes with +// inaccessible conversion operators). +template struct is_enum + : internal::is_enum_impl< + is_same::value || + is_integral::value || + is_floating_point::value || + is_reference::value || + internal::is_class_or_union::value, + T> { }; + +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; +template struct is_enum : is_enum { }; + +#endif + +// is_reference is false except for reference types. +template struct is_reference : false_type {}; +template struct is_reference : true_type {}; + + +// We can't get is_pod right without compiler help, so fail conservatively. +// We will assume it's false except for arithmetic types, enumerations, +// pointers and cv-qualified versions thereof. Note that std::pair +// is not a POD even if T and U are PODs. +template struct is_pod + : integral_constant::value || + is_floating_point::value || +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + // is_enum is not available on MSVC. + is_enum::value || +#endif + is_pointer::value)> { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; +template struct is_pod : is_pod { }; + + +// We can't get has_trivial_constructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// constructors. (3) array of a type with a trivial constructor. +// (4) const versions thereof. +template struct has_trivial_constructor : is_pod { }; +template struct has_trivial_constructor > + : integral_constant::value && + has_trivial_constructor::value)> { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; +template struct has_trivial_constructor + : has_trivial_constructor { }; + +// We can't get has_trivial_copy right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial copy constructor. +// (4) const versions thereof. +template struct has_trivial_copy : is_pod { }; +template struct has_trivial_copy > + : integral_constant::value && + has_trivial_copy::value)> { }; +template struct has_trivial_copy + : has_trivial_copy { }; +template struct has_trivial_copy : has_trivial_copy { }; + +// We can't get has_trivial_assign right without compiler help, so fail +// conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial copy +// constructors. (3) array of a type with a trivial assign constructor. +template struct has_trivial_assign : is_pod { }; +template struct has_trivial_assign > + : integral_constant::value && + has_trivial_assign::value)> { }; +template struct has_trivial_assign + : has_trivial_assign { }; + +// We can't get has_trivial_destructor right without compiler help, so +// fail conservatively. We will assume it's false except for: (1) types +// for which is_pod is true. (2) std::pair of types with trivial +// destructors. (3) array of a type with a trivial destructor. +// (4) const versions thereof. +template struct has_trivial_destructor : is_pod { }; +template struct has_trivial_destructor > + : integral_constant::value && + has_trivial_destructor::value)> { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; +template struct has_trivial_destructor + : has_trivial_destructor { }; + +// Specified by TR1 [4.7.1] +template struct remove_const { typedef T type; }; +template struct remove_const { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_volatile { typedef T type; }; +template struct remove_cv { + typedef typename remove_const::type>::type type; +}; + + +// Specified by TR1 [4.7.2] Reference modifications. +template struct remove_reference { typedef T type; }; +template struct remove_reference { typedef T type; }; + +template struct add_reference { typedef T& type; }; +template struct add_reference { typedef T& type; }; + +// Specified by TR1 [4.7.4] Pointer modifications. +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { typedef T type; }; +template struct remove_pointer { + typedef T type; }; + +// Specified by TR1 [4.6] Relationships between types +template struct is_same : public false_type { }; +template struct is_same : public true_type { }; + +// Specified by TR1 [4.6] Relationships between types +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) +namespace internal { + +// This class is an implementation detail for is_convertible, and you +// don't need to know how it works to use is_convertible. For those +// who care: we declare two different functions, one whose argument is +// of type To and one with a variadic argument list. We give them +// return types of different size, so we can use sizeof to trick the +// compiler into telling us which function it would have chosen if we +// had called it with an argument of type From. See Alexandrescu's +// _Modern C++ Design_ for more details on this sort of trick. + +template +struct ConvertHelper { + static small_ Test(To); + static big_ Test(...); + static From Create(); +}; +} // namespace internal + +// Inherits from true_type if From is convertible to To, false_type otherwise. +template +struct is_convertible + : integral_constant::Test( + internal::ConvertHelper::Create())) + == sizeof(small_)> { +}; +#endif + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TYPE_TRAITS_H_ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc new file mode 100644 index 000000000..7a8cbfb8b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/stubs/type_traits_unittest.cc @@ -0,0 +1,628 @@ +// 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. + +// ---- +// Author: Matt Austern + +#include + +#include // for exit() +#include +#include +#include + +#include +#include + +typedef int int32; +typedef long int64; + +using std::string; +using std::vector; +using std::pair; + + +// This assertion produces errors like "error: invalid use of +// incomplete type 'struct ::AssertTypesEq'" +// when it fails. +template struct AssertTypesEq; +template struct AssertTypesEq {}; +#define COMPILE_ASSERT_TYPES_EQ(T, U) static_cast(AssertTypesEq()) + +// A user-defined POD type. +struct A { + int n_; +}; + +// A user-defined non-POD type with a trivial copy constructor. +class B { + public: + explicit B(int n) : n_(n) { } + private: + int n_; +}; + +// Another user-defined non-POD type with a trivial copy constructor. +// We will explicitly declare C to have a trivial copy constructor +// by specializing has_trivial_copy. +class C { + public: + explicit C(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_copy : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial assignment operator. +// We will explicitly declare C to have a trivial assignment operator +// by specializing has_trivial_assign. +class D { + public: + explicit D(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_assign : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial constructor. +// We will explicitly declare E to have a trivial constructor +// by specializing has_trivial_constructor. +class E { + public: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_constructor : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +// Another user-defined non-POD type with a trivial destructor. +// We will explicitly declare E to have a trivial destructor +// by specializing has_trivial_destructor. +class F { + public: + explicit F(int n) : n_(n) { } + private: + int n_; +}; + +namespace google { +namespace protobuf { +namespace internal { +template<> struct has_trivial_destructor : true_type { }; +} // namespace internal +} // namespace protobuf +} // namespace google + +enum G {}; + +union H {}; + +class I { + public: + operator int() const; +}; + +class J { + private: + operator int() const; +}; + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +// A base class and a derived class that inherits from it, used for +// testing conversion type traits. +class Base { + public: + virtual ~Base() { } +}; + +class Derived : public Base { +}; + +TEST(TypeTraitsTest, TestIsInteger) { + // Verify that is_integral is true for all integer types. + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + + // Verify that is_integral is false for a few non-integer types. + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE((is_integral >::value)); + + // Verify that cv-qualified integral types are still integral, and + // cv-qualified non-integral types are still non-integral. + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_TRUE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); + EXPECT_FALSE(is_integral::value); +} + +TEST(TypeTraitsTest, TestIsFloating) { + // Verify that is_floating_point is true for all floating-point types. + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + + // Verify that is_floating_point is false for a few non-float types. + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE((is_floating_point >::value)); + + // Verify that cv-qualified floating point types are still floating, and + // cv-qualified non-floating types are still non-floating. + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_TRUE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); + EXPECT_FALSE(is_floating_point::value); +} + +TEST(TypeTraitsTest, TestIsPointer) { + // Verify that is_pointer is true for some pointer types. + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + + // Verify that is_pointer is false for some non-pointer types. + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer >::value); + EXPECT_FALSE(is_pointer::value); + + // A function pointer is a pointer, but a function type, or a function + // reference type, is not. + EXPECT_TRUE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + + // Verify that is_pointer is true for some cv-qualified pointer types, + // and false for some cv-qualified non-pointer types. + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_TRUE(is_pointer::value); + EXPECT_FALSE(is_pointer::value); + EXPECT_FALSE(is_pointer >::value); + EXPECT_FALSE(is_pointer::value); +} + +TEST(TypeTraitsTest, TestIsEnum) { +// is_enum isn't supported on MSVC or gcc 3.x +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + // Verify that is_enum is true for enum types. + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + EXPECT_TRUE(is_enum::value); + + // Verify that is_enum is false for a few non-enum types. + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); + EXPECT_FALSE(is_enum::value); +#endif +} + +TEST(TypeTraitsTest, TestIsReference) { + // Verifies that is_reference is true for all reference types. + typedef float& RefFloat; + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + EXPECT_TRUE(is_reference::value); + + + // Verifies that is_reference is false for all non-reference types. + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); + EXPECT_FALSE(is_reference::value); +} + +TEST(TypeTraitsTest, TestAddReference) { + COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int&, add_reference::type); + COMPILE_ASSERT_TYPES_EQ(volatile int&, + add_reference::type); + COMPILE_ASSERT_TYPES_EQ(const volatile int&, + add_reference::type); +} + +TEST(TypeTraitsTest, TestIsPod) { + // Verify that arithmetic types and pointers are marked as PODs. + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); + EXPECT_TRUE(is_pod::value); +#endif + + // Verify that some non-POD types are not marked as PODs. + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE((is_pod >::value)); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); + EXPECT_FALSE(is_pod::value); +} + +TEST(TypeTraitsTest, TestHasTrivialConstructor) { + // Verify that arithmetic types and pointers have trivial constructors. + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + EXPECT_TRUE(has_trivial_constructor::value); + + // Verify that pairs and arrays of such types have trivial + // constructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_constructor >::value)); + EXPECT_TRUE(has_trivial_constructor::value); + + // Verify that pairs of types without trivial constructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_constructor >::value)); + EXPECT_FALSE((has_trivial_constructor >::value)); + + // Verify that types without trivial constructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_constructor::value); + EXPECT_FALSE(has_trivial_constructor >::value); + + // Verify that E, which we have declared to have a trivial + // constructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_constructor::value); +} + +TEST(TypeTraitsTest, TestHasTrivialCopy) { + // Verify that arithmetic types and pointers have trivial copy + // constructors. + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + EXPECT_TRUE(has_trivial_copy::value); + + // Verify that pairs and arrays of such types have trivial + // copy constructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_copy >::value)); + EXPECT_TRUE(has_trivial_copy::value); + + // Verify that pairs of types without trivial copy constructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_copy >::value)); + EXPECT_FALSE((has_trivial_copy >::value)); + + // Verify that types without trivial copy constructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_copy::value); + EXPECT_FALSE(has_trivial_copy >::value); + + // Verify that C, which we have declared to have a trivial + // copy constructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_copy::value); +} + +TEST(TypeTraitsTest, TestHasTrivialAssign) { + // Verify that arithmetic types and pointers have trivial assignment + // operators. + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + EXPECT_TRUE(has_trivial_assign::value); + + // Verify that pairs and arrays of such types have trivial + // assignment operators. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_assign >::value)); + EXPECT_TRUE(has_trivial_assign::value); + + // Verify that pairs of types without trivial assignment operators + // are not marked as trivial. + EXPECT_FALSE((has_trivial_assign >::value)); + EXPECT_FALSE((has_trivial_assign >::value)); + + // Verify that types without trivial assignment operators are + // correctly marked as such. + EXPECT_FALSE(has_trivial_assign::value); + EXPECT_FALSE(has_trivial_assign >::value); + + // Verify that D, which we have declared to have a trivial + // assignment operator, is correctly marked as such. + EXPECT_TRUE(has_trivial_assign::value); +} + +TEST(TypeTraitsTest, TestHasTrivialDestructor) { + // Verify that arithmetic types and pointers have trivial destructors. + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + EXPECT_TRUE(has_trivial_destructor::value); + + // Verify that pairs and arrays of such types have trivial + // destructors. + typedef int int10[10]; + EXPECT_TRUE((has_trivial_destructor >::value)); + EXPECT_TRUE(has_trivial_destructor::value); + + // Verify that pairs of types without trivial destructors + // are not marked as trivial. + EXPECT_FALSE((has_trivial_destructor >::value)); + EXPECT_FALSE((has_trivial_destructor >::value)); + + // Verify that types without trivial destructors are + // correctly marked as such. + EXPECT_FALSE(has_trivial_destructor::value); + EXPECT_FALSE(has_trivial_destructor >::value); + + // Verify that F, which we have declared to have a trivial + // destructor, is correctly marked as such. + EXPECT_TRUE(has_trivial_destructor::value); +} + +// Tests remove_pointer. +TEST(TypeTraitsTest, TestRemovePointer) { + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(const int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_pointer::type); +} + +TEST(TypeTraitsTest, TestRemoveConst) { + COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_const::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(const int *, remove_const::type); + COMPILE_ASSERT_TYPES_EQ(volatile int, + remove_const::type); +} + +TEST(TypeTraitsTest, TestRemoveVolatile) { + COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_volatile::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(volatile int *, + remove_volatile::type); + COMPILE_ASSERT_TYPES_EQ(const int, + remove_volatile::type); +} + +TEST(TypeTraitsTest, TestRemoveCV) { + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int *, remove_cv::type); + // TR1 examples. + COMPILE_ASSERT_TYPES_EQ(const volatile int *, + remove_cv::type); + COMPILE_ASSERT_TYPES_EQ(int, + remove_cv::type); +} + +TEST(TypeTraitsTest, TestRemoveReference) { + COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(const int, remove_reference::type); + COMPILE_ASSERT_TYPES_EQ(int*, remove_reference::type); +} + +TEST(TypeTraitsTest, TestIsSame) { + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); + + EXPECT_TRUE((is_same::value)); + EXPECT_TRUE((is_same::value)); + EXPECT_FALSE((is_same::value)); + EXPECT_FALSE((is_same::value)); +} + +TEST(TypeTraitsTest, TestConvertible) { +#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3) + EXPECT_TRUE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); + + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); + EXPECT_TRUE((is_convertible::value)); + EXPECT_FALSE((is_convertible::value)); +#endif +} + +} // anonymous namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.cc new file mode 100644 index 000000000..a9666fe40 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.cc @@ -0,0 +1,3047 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { + +void TestUtil::SetAllFields(unittest::TestAllTypes* message) { + SetOptionalFields(message); + AddRepeatedFields1(message); + AddRepeatedFields2(message); + SetDefaultFields(message); +} + +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 +} + +// ------------------------------------------------------------------- + +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 +} + +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 +} + +// ------------------------------------------------------------------- + +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 +} + +// ------------------------------------------------------------------- + +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 +} + +// ------------------------------------------------------------------- + +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 ()); + +} + +// ------------------------------------------------------------------- + +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 ()); + +} + +// ------------------------------------------------------------------- + +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)); + +} + +// ------------------------------------------------------------------- + +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); +} + +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); +} + +// ------------------------------------------------------------------- + +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); +} + +// ------------------------------------------------------------------- + +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)); +} + +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)); +} + +// ------------------------------------------------------------------- + +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 ()); +} + +// ------------------------------------------------------------------- + +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. +// +// I gave up on the 80-char limit here. Sorry. + +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"); +} + +// ------------------------------------------------------------------- + +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"); +} + +// ------------------------------------------------------------------- + +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"); +} + +// ------------------------------------------------------------------- + +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)); +} + +// ------------------------------------------------------------------- + +void TestUtil::ExpectExtensionsClear( + const unittest::TestAllExtensions& message) { + string serialized; + ASSERT_TRUE(message.SerializeToString(&serialized)); + EXPECT_EQ("", serialized); + EXPECT_EQ(0, message.ByteSize()); + + // 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)); +} + +// ------------------------------------------------------------------- + +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)); +} + +// ------------------------------------------------------------------- + +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); +} + +// ------------------------------------------------------------------- + +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); +} + +// ------------------------------------------------------------------- + +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)); +} + +// ------------------------------------------------------------------- + +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 )); +} + +// ------------------------------------------------------------------- + +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)); +} + +// ------------------------------------------------------------------- + +void TestUtil::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); +} + +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)); +} + +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)); +} + +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()); +} + +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()); +} + +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)); +} + +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)); +} + +// =================================================================== + +TestUtil::ReflectionTester::ReflectionTester( + const Descriptor* base_descriptor) + : base_descriptor_(base_descriptor) { + + const DescriptorPool* pool = base_descriptor->file()->pool(); + + nested_b_ = + pool->FindFieldByName("protobuf_unittest.TestAllTypes.NestedMessage.bb"); + foreign_c_ = + pool->FindFieldByName("protobuf_unittest.ForeignMessage.c"); + import_d_ = + pool->FindFieldByName("protobuf_unittest_import.ImportMessage.d"); + import_e_ = + pool->FindFieldByName("protobuf_unittest_import.PublicImportMessage.e"); + nested_foo_ = + pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.FOO"); + nested_bar_ = + pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAR"); + nested_baz_ = + pool->FindEnumValueByName("protobuf_unittest.TestAllTypes.BAZ"); + foreign_foo_ = + pool->FindEnumValueByName("protobuf_unittest.FOREIGN_FOO"); + foreign_bar_ = + pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAR"); + foreign_baz_ = + pool->FindEnumValueByName("protobuf_unittest.FOREIGN_BAZ"); + import_foo_ = + pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_FOO"); + import_bar_ = + pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAR"); + import_baz_ = + pool->FindEnumValueByName("protobuf_unittest_import.IMPORT_BAZ"); + + if (base_descriptor_->name() == "TestAllExtensions") { + group_a_ = + pool->FindFieldByName("protobuf_unittest.OptionalGroup_extension.a"); + repeated_group_a_ = + pool->FindFieldByName("protobuf_unittest.RepeatedGroup_extension.a"); + } else { + group_a_ = + pool->FindFieldByName("protobuf_unittest.TestAllTypes.OptionalGroup.a"); + repeated_group_a_ = + pool->FindFieldByName("protobuf_unittest.TestAllTypes.RepeatedGroup.a"); + } + + EXPECT_TRUE(group_a_ != NULL); + EXPECT_TRUE(repeated_group_a_ != NULL); + EXPECT_TRUE(nested_b_ != NULL); + EXPECT_TRUE(foreign_c_ != NULL); + EXPECT_TRUE(import_d_ != NULL); + EXPECT_TRUE(import_e_ != NULL); + EXPECT_TRUE(nested_foo_ != NULL); + EXPECT_TRUE(nested_bar_ != NULL); + EXPECT_TRUE(nested_baz_ != NULL); + EXPECT_TRUE(foreign_foo_ != NULL); + EXPECT_TRUE(foreign_bar_ != NULL); + EXPECT_TRUE(foreign_baz_ != NULL); + EXPECT_TRUE(import_foo_ != NULL); + EXPECT_TRUE(import_bar_ != NULL); + EXPECT_TRUE(import_baz_ != NULL); +} + +// Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes. +const FieldDescriptor* TestUtil::ReflectionTester::F(const string& name) { + const FieldDescriptor* result = NULL; + 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 != NULL); + return result; +} + +// ------------------------------------------------------------------- + +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"); +} + +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_); +} + +// ------------------------------------------------------------------- + +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); +} + +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)); + +} + +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)); +} + +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)); +} + +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)); +} + +// ------------------------------------------------------------------- + +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)); +} + +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" ))); +} + +// ------------------------------------------------------------------- + +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"); +} + +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_); +} + +void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + vector output; + reflection->ListFields(*message, &output); + for (int i=0; iis_repeated()) continue; + + reflection->RemoveLast(message, field); + } +} + +void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection( + Message* message, bool expect_extensions_notnull) { + const Reflection* reflection = message->GetReflection(); + + vector output; + reflection->ListFields(*message, &output); + for (int i=0; iis_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 != NULL) << "ReleaseLast returned NULL for: " + << field->name(); + } + delete released; + } +} + +void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + + vector output; + reflection->ListFields(*message, &output); + for (int i=0; iis_repeated()) continue; + + reflection->SwapElements(message, field, 0, 1); + } +} + +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 == NULL); + break; + case NOT_NULL: + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + break; + case CAN_BE_NULL: + break; + } + delete released; + EXPECT_FALSE(reflection->HasField(*message, F(fields[i]))); + } +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.h new file mode 100644 index 000000000..455195734 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util.h @@ -0,0 +1,193 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace unittest = ::protobuf_unittest; +namespace unittest_import = protobuf_unittest_import; + +class TestUtil { + public: + // Set every field in the message to a unique value. + static void SetAllFields(unittest::TestAllTypes* message); + static void SetOptionalFields(unittest::TestAllTypes* message); + static void AddRepeatedFields1(unittest::TestAllTypes* message); + static void AddRepeatedFields2(unittest::TestAllTypes* message); + static void SetDefaultFields(unittest::TestAllTypes* message); + static void SetAllExtensions(unittest::TestAllExtensions* message); + static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message); + static void SetPackedFields(unittest::TestPackedTypes* message); + static void SetPackedExtensions(unittest::TestPackedExtensions* message); + static void SetUnpackedFields(unittest::TestUnpackedTypes* message); + + // Use the repeated versions of the set_*() accessors to modify all the + // repeated fields of the messsage (which should already have been + // initialized with Set*Fields()). Set*Fields() itself only tests + // the add_*() accessors. + static void ModifyRepeatedFields(unittest::TestAllTypes* message); + static void ModifyRepeatedExtensions(unittest::TestAllExtensions* message); + static void ModifyPackedFields(unittest::TestPackedTypes* message); + static void ModifyPackedExtensions(unittest::TestPackedExtensions* message); + + // Check that all fields have the values that they should have after + // Set*Fields() is called. + static void ExpectAllFieldsSet(const unittest::TestAllTypes& message); + static void ExpectAllExtensionsSet( + const unittest::TestAllExtensions& message); + static void ExpectPackedFieldsSet(const unittest::TestPackedTypes& message); + static void ExpectPackedExtensionsSet( + const unittest::TestPackedExtensions& message); + static void ExpectUnpackedFieldsSet( + const unittest::TestUnpackedTypes& message); + + // Expect that the message is modified as would be expected from + // Modify*Fields(). + static void ExpectRepeatedFieldsModified( + const unittest::TestAllTypes& message); + static void ExpectRepeatedExtensionsModified( + const unittest::TestAllExtensions& message); + static void ExpectPackedFieldsModified( + const unittest::TestPackedTypes& message); + static void ExpectPackedExtensionsModified( + const unittest::TestPackedExtensions& message); + + // Check that all fields have their default values. + static void ExpectClear(const unittest::TestAllTypes& message); + static void ExpectExtensionsClear(const unittest::TestAllExtensions& message); + static void ExpectPackedClear(const unittest::TestPackedTypes& message); + static void ExpectPackedExtensionsClear( + const unittest::TestPackedExtensions& message); + + // Check that the passed-in serialization is the canonical serialization we + // expect for a TestFieldOrderings message filled in by + // SetAllFieldsAndExtensions(). + static void ExpectAllFieldsAndExtensionsInOrder(const string& serialized); + + // Check that all repeated fields have had their last elements removed. + static void ExpectLastRepeatedsRemoved( + const unittest::TestAllTypes& message); + static void ExpectLastRepeatedExtensionsRemoved( + const unittest::TestAllExtensions& message); + static void ExpectLastRepeatedsReleased( + const unittest::TestAllTypes& message); + static void ExpectLastRepeatedExtensionsReleased( + const unittest::TestAllExtensions& message); + + // Check that all repeated fields have had their first and last elements + // swapped. + static void ExpectRepeatedsSwapped(const unittest::TestAllTypes& message); + static void ExpectRepeatedExtensionsSwapped( + const unittest::TestAllExtensions& message); + + // Like above, but use the reflection interface. + 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); + + enum MessageReleaseState { + IS_NULL, + CAN_BE_NULL, + NOT_NULL, + }; + void ExpectMessagesReleasedViaReflection( + Message* message, MessageReleaseState expected_release_state); + + 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); + }; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtil); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_TEST_UTIL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.cc new file mode 100644 index 000000000..9099292ab --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.cc @@ -0,0 +1,1548 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + + +#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 { + +void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* 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::TestAllTypesLite::BAZ ); + message->set_optional_foreign_enum(unittest::FOREIGN_LITE_BAZ ); + message->set_optional_import_enum (unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + 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::TestAllTypesLite::BAR ); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAR ); + message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAR); + + + // 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::TestAllTypesLite::BAZ ); + message->add_repeated_foreign_enum(unittest::FOREIGN_LITE_BAZ ); + message->add_repeated_import_enum (unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + 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::TestAllTypesLite::FOO ); + message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO ); + message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyRepeatedFields(unittest::TestAllTypesLite* 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::TestAllTypesLite::FOO ); + message->set_repeated_foreign_enum(1, unittest::FOREIGN_LITE_FOO ); + message->set_repeated_import_enum (1, unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectAllFieldsSet( + const unittest::TestAllTypesLite& 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 ()); + + + 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_EQ(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::TestAllTypesLite::BAZ , message.optional_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_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 ()); + + + 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_EQ(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::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_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_EQ(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::TestAllTypesLite::BAZ , message.repeated_nested_enum (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_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_EQ(false, message.default_bool ()); + EXPECT_EQ("415", message.default_string ()); + EXPECT_EQ("416", message.default_bytes ()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.default_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ()); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& 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 ()); + + + // 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_EQ(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()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.optional_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.optional_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_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 ()); + + + // 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_EQ(true , message.default_bool ()); + EXPECT_EQ("hello", message.default_string ()); + EXPECT_EQ("world", message.default_bytes ()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.default_nested_enum ()); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.default_foreign_enum()); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ()); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectRepeatedFieldsModified( + const unittest::TestAllTypesLite& 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 ()); + + + 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_EQ(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::TestAllTypesLite::BAR , message.repeated_nested_enum (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.repeated_foreign_enum(0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_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_EQ(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::TestAllTypesLite::FOO , message.repeated_nested_enum (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.repeated_foreign_enum(1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.repeated_import_enum (1)); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::SetPackedFields(unittest::TestPackedTypesLite* 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_LITE_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_LITE_BAZ); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyPackedFields(unittest::TestPackedTypesLite* 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_LITE_FOO); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedFieldsSet( + const unittest::TestPackedTypesLite& 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_EQ(true , message.packed_bool (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_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_EQ(false, message.packed_bool (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1)); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedClear( + const unittest::TestPackedTypesLite& 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 ()); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedFieldsModified( + const unittest::TestPackedTypesLite& 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_EQ(true , message.packed_bool (0)); + EXPECT_EQ(unittest::FOREIGN_LITE_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_EQ(true , message.packed_bool (1)); + EXPECT_EQ(unittest::FOREIGN_LITE_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. +// +// I gave up on the 80-char limit here. Sorry. + +void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { + message->SetExtension(unittest::optional_int32_extension_lite , 101); + message->SetExtension(unittest::optional_int64_extension_lite , 102); + message->SetExtension(unittest::optional_uint32_extension_lite , 103); + message->SetExtension(unittest::optional_uint64_extension_lite , 104); + message->SetExtension(unittest::optional_sint32_extension_lite , 105); + message->SetExtension(unittest::optional_sint64_extension_lite , 106); + message->SetExtension(unittest::optional_fixed32_extension_lite , 107); + message->SetExtension(unittest::optional_fixed64_extension_lite , 108); + message->SetExtension(unittest::optional_sfixed32_extension_lite, 109); + message->SetExtension(unittest::optional_sfixed64_extension_lite, 110); + message->SetExtension(unittest::optional_float_extension_lite , 111); + message->SetExtension(unittest::optional_double_extension_lite , 112); + message->SetExtension(unittest::optional_bool_extension_lite , true); + message->SetExtension(unittest::optional_string_extension_lite , "115"); + message->SetExtension(unittest::optional_bytes_extension_lite , "116"); + + message->MutableExtension(unittest::optionalgroup_extension_lite )->set_a(117); + message->MutableExtension(unittest::optional_nested_message_extension_lite )->set_bb(118); + message->MutableExtension(unittest::optional_foreign_message_extension_lite )->set_c(119); + message->MutableExtension(unittest::optional_import_message_extension_lite )->set_d(120); + message->MutableExtension(unittest::optional_public_import_message_extension_lite)->set_e(126); + message->MutableExtension(unittest::optional_lazy_message_extension_lite )->set_bb(127); + + message->SetExtension(unittest::optional_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); + message->SetExtension(unittest::optional_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); + message->SetExtension(unittest::optional_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->AddExtension(unittest::repeated_int32_extension_lite , 201); + message->AddExtension(unittest::repeated_int64_extension_lite , 202); + message->AddExtension(unittest::repeated_uint32_extension_lite , 203); + message->AddExtension(unittest::repeated_uint64_extension_lite , 204); + message->AddExtension(unittest::repeated_sint32_extension_lite , 205); + message->AddExtension(unittest::repeated_sint64_extension_lite , 206); + message->AddExtension(unittest::repeated_fixed32_extension_lite , 207); + message->AddExtension(unittest::repeated_fixed64_extension_lite , 208); + message->AddExtension(unittest::repeated_sfixed32_extension_lite, 209); + message->AddExtension(unittest::repeated_sfixed64_extension_lite, 210); + message->AddExtension(unittest::repeated_float_extension_lite , 211); + message->AddExtension(unittest::repeated_double_extension_lite , 212); + message->AddExtension(unittest::repeated_bool_extension_lite , true); + message->AddExtension(unittest::repeated_string_extension_lite , "215"); + message->AddExtension(unittest::repeated_bytes_extension_lite , "216"); + + message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(217); + message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(218); + message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(219); + message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(220); + message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(227); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAR ); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAR ); + message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAR); + + + // Add a second one of each field. + message->AddExtension(unittest::repeated_int32_extension_lite , 301); + message->AddExtension(unittest::repeated_int64_extension_lite , 302); + message->AddExtension(unittest::repeated_uint32_extension_lite , 303); + message->AddExtension(unittest::repeated_uint64_extension_lite , 304); + message->AddExtension(unittest::repeated_sint32_extension_lite , 305); + message->AddExtension(unittest::repeated_sint64_extension_lite , 306); + message->AddExtension(unittest::repeated_fixed32_extension_lite , 307); + message->AddExtension(unittest::repeated_fixed64_extension_lite , 308); + message->AddExtension(unittest::repeated_sfixed32_extension_lite, 309); + message->AddExtension(unittest::repeated_sfixed64_extension_lite, 310); + message->AddExtension(unittest::repeated_float_extension_lite , 311); + message->AddExtension(unittest::repeated_double_extension_lite , 312); + message->AddExtension(unittest::repeated_bool_extension_lite , false); + message->AddExtension(unittest::repeated_string_extension_lite , "315"); + message->AddExtension(unittest::repeated_bytes_extension_lite , "316"); + + message->AddExtension(unittest::repeatedgroup_extension_lite )->set_a(317); + message->AddExtension(unittest::repeated_nested_message_extension_lite )->set_bb(318); + message->AddExtension(unittest::repeated_foreign_message_extension_lite)->set_c(319); + message->AddExtension(unittest::repeated_import_message_extension_lite )->set_d(320); + message->AddExtension(unittest::repeated_lazy_message_extension_lite )->set_bb(327); + + message->AddExtension(unittest::repeated_nested_enum_extension_lite , unittest::TestAllTypesLite::BAZ ); + message->AddExtension(unittest::repeated_foreign_enum_extension_lite, unittest::FOREIGN_LITE_BAZ ); + message->AddExtension(unittest::repeated_import_enum_extension_lite , unittest_import::IMPORT_LITE_BAZ); + + + // ----------------------------------------------------------------- + + message->SetExtension(unittest::default_int32_extension_lite , 401); + message->SetExtension(unittest::default_int64_extension_lite , 402); + message->SetExtension(unittest::default_uint32_extension_lite , 403); + message->SetExtension(unittest::default_uint64_extension_lite , 404); + message->SetExtension(unittest::default_sint32_extension_lite , 405); + message->SetExtension(unittest::default_sint64_extension_lite , 406); + message->SetExtension(unittest::default_fixed32_extension_lite , 407); + message->SetExtension(unittest::default_fixed64_extension_lite , 408); + message->SetExtension(unittest::default_sfixed32_extension_lite, 409); + message->SetExtension(unittest::default_sfixed64_extension_lite, 410); + message->SetExtension(unittest::default_float_extension_lite , 411); + message->SetExtension(unittest::default_double_extension_lite , 412); + message->SetExtension(unittest::default_bool_extension_lite , false); + message->SetExtension(unittest::default_string_extension_lite , "415"); + message->SetExtension(unittest::default_bytes_extension_lite , "416"); + + message->SetExtension(unittest::default_nested_enum_extension_lite , unittest::TestAllTypesLite::FOO ); + message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO ); + message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyRepeatedExtensions( + unittest::TestAllExtensionsLite* message) { + message->SetExtension(unittest::repeated_int32_extension_lite , 1, 501); + message->SetExtension(unittest::repeated_int64_extension_lite , 1, 502); + message->SetExtension(unittest::repeated_uint32_extension_lite , 1, 503); + message->SetExtension(unittest::repeated_uint64_extension_lite , 1, 504); + message->SetExtension(unittest::repeated_sint32_extension_lite , 1, 505); + message->SetExtension(unittest::repeated_sint64_extension_lite , 1, 506); + message->SetExtension(unittest::repeated_fixed32_extension_lite , 1, 507); + message->SetExtension(unittest::repeated_fixed64_extension_lite , 1, 508); + message->SetExtension(unittest::repeated_sfixed32_extension_lite, 1, 509); + message->SetExtension(unittest::repeated_sfixed64_extension_lite, 1, 510); + message->SetExtension(unittest::repeated_float_extension_lite , 1, 511); + message->SetExtension(unittest::repeated_double_extension_lite , 1, 512); + message->SetExtension(unittest::repeated_bool_extension_lite , 1, true); + message->SetExtension(unittest::repeated_string_extension_lite , 1, "515"); + message->SetExtension(unittest::repeated_bytes_extension_lite , 1, "516"); + + message->MutableExtension(unittest::repeatedgroup_extension_lite , 1)->set_a(517); + message->MutableExtension(unittest::repeated_nested_message_extension_lite , 1)->set_bb(518); + message->MutableExtension(unittest::repeated_foreign_message_extension_lite, 1)->set_c(519); + message->MutableExtension(unittest::repeated_import_message_extension_lite , 1)->set_d(520); + message->MutableExtension(unittest::repeated_lazy_message_extension_lite , 1)->set_bb(527); + + message->SetExtension(unittest::repeated_nested_enum_extension_lite , 1, unittest::TestAllTypesLite::FOO ); + message->SetExtension(unittest::repeated_foreign_enum_extension_lite, 1, unittest::FOREIGN_LITE_FOO ); + message->SetExtension(unittest::repeated_import_enum_extension_lite , 1, unittest_import::IMPORT_LITE_FOO); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectAllExtensionsSet( + const unittest::TestAllExtensionsLite& message) { + EXPECT_TRUE(message.HasExtension(unittest::optional_int32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_int64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_uint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_float_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_double_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_bool_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_string_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); + + EXPECT_TRUE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_TRUE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_TRUE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); + EXPECT_TRUE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + EXPECT_TRUE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); + EXPECT_TRUE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); + + EXPECT_TRUE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::optional_import_enum_extension_lite )); + + + EXPECT_EQ(101 , message.GetExtension(unittest::optional_int32_extension_lite )); + EXPECT_EQ(102 , message.GetExtension(unittest::optional_int64_extension_lite )); + EXPECT_EQ(103 , message.GetExtension(unittest::optional_uint32_extension_lite )); + EXPECT_EQ(104 , message.GetExtension(unittest::optional_uint64_extension_lite )); + EXPECT_EQ(105 , message.GetExtension(unittest::optional_sint32_extension_lite )); + EXPECT_EQ(106 , message.GetExtension(unittest::optional_sint64_extension_lite )); + EXPECT_EQ(107 , message.GetExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_EQ(108 , message.GetExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_EQ(109 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(110 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(111 , message.GetExtension(unittest::optional_float_extension_lite )); + EXPECT_EQ(112 , message.GetExtension(unittest::optional_double_extension_lite )); + EXPECT_EQ(true , message.GetExtension(unittest::optional_bool_extension_lite )); + EXPECT_EQ("115", message.GetExtension(unittest::optional_string_extension_lite )); + EXPECT_EQ("116", message.GetExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_EQ(117, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(118, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(119, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); + EXPECT_EQ(120, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_EQ(126, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); + EXPECT_EQ(127, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::optional_import_enum_extension_lite )); + + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); + EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); + EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); + EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); + EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); + EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); + EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); + EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); + EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); + EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); + EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); + EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); + + EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); + EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); + EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); + EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); + + + EXPECT_EQ(301 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); + EXPECT_EQ(302 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); + EXPECT_EQ(303 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); + EXPECT_EQ(304 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); + EXPECT_EQ(305 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); + EXPECT_EQ(306 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); + EXPECT_EQ(307 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); + EXPECT_EQ(308 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); + EXPECT_EQ(309 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ(310 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(311 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); + EXPECT_EQ(312 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::repeated_bool_extension_lite , 1)); + EXPECT_EQ("315", message.GetExtension(unittest::repeated_string_extension_lite , 1)); + EXPECT_EQ("316", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); + + EXPECT_EQ(317, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); + EXPECT_EQ(318, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); + EXPECT_EQ(319, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); + EXPECT_EQ(320, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + EXPECT_EQ(327, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAZ , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAZ, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.HasExtension(unittest::default_int32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_int64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_uint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_uint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sint32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sint64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed32_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_float_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_double_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_bool_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_string_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_bytes_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_TRUE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::default_import_enum_extension_lite )); + + + EXPECT_EQ(401 , message.GetExtension(unittest::default_int32_extension_lite )); + EXPECT_EQ(402 , message.GetExtension(unittest::default_int64_extension_lite )); + EXPECT_EQ(403 , message.GetExtension(unittest::default_uint32_extension_lite )); + EXPECT_EQ(404 , message.GetExtension(unittest::default_uint64_extension_lite )); + EXPECT_EQ(405 , message.GetExtension(unittest::default_sint32_extension_lite )); + EXPECT_EQ(406 , message.GetExtension(unittest::default_sint64_extension_lite )); + EXPECT_EQ(407 , message.GetExtension(unittest::default_fixed32_extension_lite )); + EXPECT_EQ(408 , message.GetExtension(unittest::default_fixed64_extension_lite )); + EXPECT_EQ(409 , message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(410 , message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ(411 , message.GetExtension(unittest::default_float_extension_lite )); + EXPECT_EQ(412 , message.GetExtension(unittest::default_double_extension_lite )); + EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite )); + EXPECT_EQ("415", message.GetExtension(unittest::default_string_extension_lite )); + EXPECT_EQ("416", message.GetExtension(unittest::default_bytes_extension_lite )); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite )); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectExtensionsClear( + const unittest::TestAllExtensionsLite& message) { + string serialized; + ASSERT_TRUE(message.SerializeToString(&serialized)); + EXPECT_EQ("", serialized); + EXPECT_EQ(0, message.ByteSize()); + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.HasExtension(unittest::optional_int32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_int64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_uint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_float_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_double_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_bool_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_string_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_bytes_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::optionalgroup_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_message_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_public_import_message_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_lazy_message_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::optional_import_enum_extension_lite )); + + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0 , message.GetExtension(unittest::optional_int32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_int64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_uint64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sint64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed32_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_fixed64_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed32_extension_lite)); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_sfixed64_extension_lite)); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_float_extension_lite )); + EXPECT_EQ(0 , message.GetExtension(unittest::optional_double_extension_lite )); + EXPECT_EQ(false, message.GetExtension(unittest::optional_bool_extension_lite )); + EXPECT_EQ("" , message.GetExtension(unittest::optional_string_extension_lite )); + EXPECT_EQ("" , message.GetExtension(unittest::optional_bytes_extension_lite )); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.GetExtension(unittest::optionalgroup_extension_lite ).has_a()); + EXPECT_FALSE(message.GetExtension(unittest::optional_nested_message_extension_lite ).has_bb()); + EXPECT_FALSE(message.GetExtension(unittest::optional_foreign_message_extension_lite ).has_c()); + EXPECT_FALSE(message.GetExtension(unittest::optional_import_message_extension_lite ).has_d()); + EXPECT_FALSE(message.GetExtension(unittest::optional_public_import_message_extension_lite).has_e()); + EXPECT_FALSE(message.GetExtension(unittest::optional_lazy_message_extension_lite ).has_bb()); + + EXPECT_EQ(0, message.GetExtension(unittest::optionalgroup_extension_lite ).a()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_nested_message_extension_lite ).bb()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_foreign_message_extension_lite ).c()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_import_message_extension_lite ).d()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_public_import_message_extension_lite).e()); + EXPECT_EQ(0, message.GetExtension(unittest::optional_lazy_message_extension_lite ).bb()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::optional_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::optional_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::optional_import_enum_extension_lite )); + + + // Repeated fields are empty. + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_float_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_double_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_string_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + EXPECT_EQ(0, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.HasExtension(unittest::default_int32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_int64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_uint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_uint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sint32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sint64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed32_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_fixed64_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_float_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_double_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_bool_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_string_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_bytes_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_FALSE(message.HasExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::default_import_enum_extension_lite )); + + + // Fields with defaults have their default values (duh). + EXPECT_EQ( 41 , message.GetExtension(unittest::default_int32_extension_lite )); + EXPECT_EQ( 42 , message.GetExtension(unittest::default_int64_extension_lite )); + EXPECT_EQ( 43 , message.GetExtension(unittest::default_uint32_extension_lite )); + EXPECT_EQ( 44 , message.GetExtension(unittest::default_uint64_extension_lite )); + EXPECT_EQ(-45 , message.GetExtension(unittest::default_sint32_extension_lite )); + EXPECT_EQ( 46 , message.GetExtension(unittest::default_sint64_extension_lite )); + EXPECT_EQ( 47 , message.GetExtension(unittest::default_fixed32_extension_lite )); + EXPECT_EQ( 48 , message.GetExtension(unittest::default_fixed64_extension_lite )); + EXPECT_EQ( 49 , message.GetExtension(unittest::default_sfixed32_extension_lite)); + EXPECT_EQ(-50 , message.GetExtension(unittest::default_sfixed64_extension_lite)); + EXPECT_EQ( 51.5 , message.GetExtension(unittest::default_float_extension_lite )); + EXPECT_EQ( 52e3 , message.GetExtension(unittest::default_double_extension_lite )); + EXPECT_EQ(true , message.GetExtension(unittest::default_bool_extension_lite )); + EXPECT_EQ("hello", message.GetExtension(unittest::default_string_extension_lite )); + EXPECT_EQ("world", message.GetExtension(unittest::default_bytes_extension_lite )); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::default_nested_enum_extension_lite )); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::default_foreign_enum_extension_lite)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite )); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectRepeatedExtensionsModified( + const unittest::TestAllExtensionsLite& 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_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_string_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_bytes_extension_lite )); + + ASSERT_EQ(2, message.ExtensionSize(unittest::repeatedgroup_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_message_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_lazy_message_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_nested_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_foreign_enum_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::repeated_import_enum_extension_lite )); + + + EXPECT_EQ(201 , message.GetExtension(unittest::repeated_int32_extension_lite , 0)); + EXPECT_EQ(202 , message.GetExtension(unittest::repeated_int64_extension_lite , 0)); + EXPECT_EQ(203 , message.GetExtension(unittest::repeated_uint32_extension_lite , 0)); + EXPECT_EQ(204 , message.GetExtension(unittest::repeated_uint64_extension_lite , 0)); + EXPECT_EQ(205 , message.GetExtension(unittest::repeated_sint32_extension_lite , 0)); + EXPECT_EQ(206 , message.GetExtension(unittest::repeated_sint64_extension_lite , 0)); + EXPECT_EQ(207 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 0)); + EXPECT_EQ(208 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 0)); + EXPECT_EQ(209 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 0)); + EXPECT_EQ(210 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 0)); + EXPECT_EQ(211 , message.GetExtension(unittest::repeated_float_extension_lite , 0)); + EXPECT_EQ(212 , message.GetExtension(unittest::repeated_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 0)); + EXPECT_EQ("215", message.GetExtension(unittest::repeated_string_extension_lite , 0)); + EXPECT_EQ("216", message.GetExtension(unittest::repeated_bytes_extension_lite , 0)); + + EXPECT_EQ(217, message.GetExtension(unittest::repeatedgroup_extension_lite , 0).a()); + EXPECT_EQ(218, message.GetExtension(unittest::repeated_nested_message_extension_lite , 0).bb()); + EXPECT_EQ(219, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 0).c()); + EXPECT_EQ(220, message.GetExtension(unittest::repeated_import_message_extension_lite , 0).d()); + EXPECT_EQ(227, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 0).bb()); + + EXPECT_EQ(unittest::TestAllTypesLite::BAR , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 0)); + EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::repeated_import_enum_extension_lite , 0)); + + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501 , message.GetExtension(unittest::repeated_int32_extension_lite , 1)); + EXPECT_EQ(502 , message.GetExtension(unittest::repeated_int64_extension_lite , 1)); + EXPECT_EQ(503 , message.GetExtension(unittest::repeated_uint32_extension_lite , 1)); + EXPECT_EQ(504 , message.GetExtension(unittest::repeated_uint64_extension_lite , 1)); + EXPECT_EQ(505 , message.GetExtension(unittest::repeated_sint32_extension_lite , 1)); + EXPECT_EQ(506 , message.GetExtension(unittest::repeated_sint64_extension_lite , 1)); + EXPECT_EQ(507 , message.GetExtension(unittest::repeated_fixed32_extension_lite , 1)); + EXPECT_EQ(508 , message.GetExtension(unittest::repeated_fixed64_extension_lite , 1)); + EXPECT_EQ(509 , message.GetExtension(unittest::repeated_sfixed32_extension_lite, 1)); + EXPECT_EQ(510 , message.GetExtension(unittest::repeated_sfixed64_extension_lite, 1)); + EXPECT_EQ(511 , message.GetExtension(unittest::repeated_float_extension_lite , 1)); + EXPECT_EQ(512 , message.GetExtension(unittest::repeated_double_extension_lite , 1)); + EXPECT_EQ(true , message.GetExtension(unittest::repeated_bool_extension_lite , 1)); + EXPECT_EQ("515", message.GetExtension(unittest::repeated_string_extension_lite , 1)); + EXPECT_EQ("516", message.GetExtension(unittest::repeated_bytes_extension_lite , 1)); + + EXPECT_EQ(517, message.GetExtension(unittest::repeatedgroup_extension_lite , 1).a()); + EXPECT_EQ(518, message.GetExtension(unittest::repeated_nested_message_extension_lite , 1).bb()); + EXPECT_EQ(519, message.GetExtension(unittest::repeated_foreign_message_extension_lite, 1).c()); + EXPECT_EQ(520, message.GetExtension(unittest::repeated_import_message_extension_lite , 1).d()); + EXPECT_EQ(527, message.GetExtension(unittest::repeated_lazy_message_extension_lite , 1).bb()); + + EXPECT_EQ(unittest::TestAllTypesLite::FOO , message.GetExtension(unittest::repeated_nested_enum_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::repeated_foreign_enum_extension_lite, 1)); + EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::repeated_import_enum_extension_lite , 1)); + +} + +// ------------------------------------------------------------------- + +void TestUtilLite::SetPackedExtensions( + unittest::TestPackedExtensionsLite* message) { + message->AddExtension(unittest::packed_int32_extension_lite , 601); + message->AddExtension(unittest::packed_int64_extension_lite , 602); + message->AddExtension(unittest::packed_uint32_extension_lite , 603); + message->AddExtension(unittest::packed_uint64_extension_lite , 604); + message->AddExtension(unittest::packed_sint32_extension_lite , 605); + message->AddExtension(unittest::packed_sint64_extension_lite , 606); + message->AddExtension(unittest::packed_fixed32_extension_lite , 607); + message->AddExtension(unittest::packed_fixed64_extension_lite , 608); + message->AddExtension(unittest::packed_sfixed32_extension_lite, 609); + message->AddExtension(unittest::packed_sfixed64_extension_lite, 610); + message->AddExtension(unittest::packed_float_extension_lite , 611); + message->AddExtension(unittest::packed_double_extension_lite , 612); + message->AddExtension(unittest::packed_bool_extension_lite , true); + message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAR); + // add a second one of each field + message->AddExtension(unittest::packed_int32_extension_lite , 701); + message->AddExtension(unittest::packed_int64_extension_lite , 702); + message->AddExtension(unittest::packed_uint32_extension_lite , 703); + message->AddExtension(unittest::packed_uint64_extension_lite , 704); + message->AddExtension(unittest::packed_sint32_extension_lite , 705); + message->AddExtension(unittest::packed_sint64_extension_lite , 706); + message->AddExtension(unittest::packed_fixed32_extension_lite , 707); + message->AddExtension(unittest::packed_fixed64_extension_lite , 708); + message->AddExtension(unittest::packed_sfixed32_extension_lite, 709); + message->AddExtension(unittest::packed_sfixed64_extension_lite, 710); + message->AddExtension(unittest::packed_float_extension_lite , 711); + message->AddExtension(unittest::packed_double_extension_lite , 712); + message->AddExtension(unittest::packed_bool_extension_lite , false); + message->AddExtension(unittest::packed_enum_extension_lite, unittest::FOREIGN_LITE_BAZ); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ModifyPackedExtensions( + unittest::TestPackedExtensionsLite* message) { + message->SetExtension(unittest::packed_int32_extension_lite , 1, 801); + message->SetExtension(unittest::packed_int64_extension_lite , 1, 802); + message->SetExtension(unittest::packed_uint32_extension_lite , 1, 803); + message->SetExtension(unittest::packed_uint64_extension_lite , 1, 804); + message->SetExtension(unittest::packed_sint32_extension_lite , 1, 805); + message->SetExtension(unittest::packed_sint64_extension_lite , 1, 806); + message->SetExtension(unittest::packed_fixed32_extension_lite , 1, 807); + message->SetExtension(unittest::packed_fixed64_extension_lite , 1, 808); + message->SetExtension(unittest::packed_sfixed32_extension_lite, 1, 809); + message->SetExtension(unittest::packed_sfixed64_extension_lite, 1, 810); + message->SetExtension(unittest::packed_float_extension_lite , 1, 811); + message->SetExtension(unittest::packed_double_extension_lite , 1, 812); + message->SetExtension(unittest::packed_bool_extension_lite , 1, true); + message->SetExtension(unittest::packed_enum_extension_lite , 1, + unittest::FOREIGN_LITE_FOO); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsSet( + const unittest::TestPackedExtensionsLite& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); + + EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::packed_enum_extension_lite, 0)); + EXPECT_EQ(701 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); + EXPECT_EQ(702 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); + EXPECT_EQ(703 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); + EXPECT_EQ(704 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); + EXPECT_EQ(705 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); + EXPECT_EQ(706 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); + EXPECT_EQ(707 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); + EXPECT_EQ(708 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); + EXPECT_EQ(709 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(710 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(711 , message.GetExtension(unittest::packed_float_extension_lite , 1)); + EXPECT_EQ(712 , message.GetExtension(unittest::packed_double_extension_lite , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, + message.GetExtension(unittest::packed_enum_extension_lite, 1)); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsClear( + const unittest::TestPackedExtensionsLite& message) { + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_int64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_float_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_double_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_bool_extension_lite )); + EXPECT_EQ(0, message.ExtensionSize(unittest::packed_enum_extension_lite )); +} + +// ------------------------------------------------------------------- + +void TestUtilLite::ExpectPackedExtensionsModified( + const unittest::TestPackedExtensionsLite& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_int64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_uint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sint64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed32_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_fixed64_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed32_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_sfixed64_extension_lite)); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_float_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_double_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_bool_extension_lite )); + ASSERT_EQ(2, message.ExtensionSize(unittest::packed_enum_extension_lite )); + EXPECT_EQ(601 , message.GetExtension(unittest::packed_int32_extension_lite , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::packed_int64_extension_lite , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::packed_uint32_extension_lite , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::packed_uint64_extension_lite , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::packed_sint32_extension_lite , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::packed_sint64_extension_lite , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::packed_fixed32_extension_lite , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::packed_fixed64_extension_lite , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::packed_float_extension_lite , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::packed_double_extension_lite , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 0)); + EXPECT_EQ(unittest::FOREIGN_LITE_BAR, + message.GetExtension(unittest::packed_enum_extension_lite, 0)); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(801 , message.GetExtension(unittest::packed_int32_extension_lite , 1)); + EXPECT_EQ(802 , message.GetExtension(unittest::packed_int64_extension_lite , 1)); + EXPECT_EQ(803 , message.GetExtension(unittest::packed_uint32_extension_lite , 1)); + EXPECT_EQ(804 , message.GetExtension(unittest::packed_uint64_extension_lite , 1)); + EXPECT_EQ(805 , message.GetExtension(unittest::packed_sint32_extension_lite , 1)); + EXPECT_EQ(806 , message.GetExtension(unittest::packed_sint64_extension_lite , 1)); + EXPECT_EQ(807 , message.GetExtension(unittest::packed_fixed32_extension_lite , 1)); + EXPECT_EQ(808 , message.GetExtension(unittest::packed_fixed64_extension_lite , 1)); + EXPECT_EQ(809 , message.GetExtension(unittest::packed_sfixed32_extension_lite, 1)); + EXPECT_EQ(810 , message.GetExtension(unittest::packed_sfixed64_extension_lite, 1)); + EXPECT_EQ(811 , message.GetExtension(unittest::packed_float_extension_lite , 1)); + EXPECT_EQ(812 , message.GetExtension(unittest::packed_double_extension_lite , 1)); + EXPECT_EQ(true , message.GetExtension(unittest::packed_bool_extension_lite , 1)); + EXPECT_EQ(unittest::FOREIGN_LITE_FOO, + message.GetExtension(unittest::packed_enum_extension_lite, 1)); +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.h new file mode 100644 index 000000000..ca35aaa47 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/test_util_lite.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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_LITE_H__ +#define GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ + +#include + +namespace google { +namespace protobuf { + +namespace unittest = protobuf_unittest; +namespace unittest_import = protobuf_unittest_import; + +class TestUtilLite { + public: + // Set every field in the message to a unique value. + static void SetAllFields(unittest::TestAllTypesLite* message); + static void SetAllExtensions(unittest::TestAllExtensionsLite* message); + static void SetPackedFields(unittest::TestPackedTypesLite* message); + 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 + // initialized with Set*Fields()). Set*Fields() itself only tests + // the add_*() accessors. + static void ModifyRepeatedFields(unittest::TestAllTypesLite* message); + static void ModifyRepeatedExtensions( + unittest::TestAllExtensionsLite* message); + static void ModifyPackedFields(unittest::TestPackedTypesLite* message); + static void ModifyPackedExtensions( + unittest::TestPackedExtensionsLite* message); + + // Check that all fields have the values that they should have after + // Set*Fields() is called. + static void ExpectAllFieldsSet(const unittest::TestAllTypesLite& message); + static void ExpectAllExtensionsSet( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedFieldsSet( + const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsSet( + const unittest::TestPackedExtensionsLite& message); + + // Expect that the message is modified as would be expected from + // Modify*Fields(). + static void ExpectRepeatedFieldsModified( + const unittest::TestAllTypesLite& message); + static void ExpectRepeatedExtensionsModified( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedFieldsModified( + const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsModified( + const unittest::TestPackedExtensionsLite& message); + + // Check that all fields have their default values. + static void ExpectClear(const unittest::TestAllTypesLite& message); + static void ExpectExtensionsClear( + const unittest::TestAllExtensionsLite& message); + static void ExpectPackedClear(const unittest::TestPackedTypesLite& message); + static void ExpectPackedExtensionsClear( + const unittest::TestPackedExtensionsLite& message); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtilLite); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.cc new file mode 100644 index 000000000..e224781db --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.cc @@ -0,0 +1,176 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// emulates google3/file/base/file.cc + +#include +#include +#include +#include +#ifdef _MSC_VER +#define WIN32_LEAN_AND_MEAN // yeah, right +#include // Find*File(). :( +#include +#include +#else +#include +#include +#endif +#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 +#endif +#endif + +bool File::Exists(const string& name) { + return access(name.c_str(), F_OK) == 0; +} + +bool File::ReadFileToString(const string& name, string* output) { + char buffer[1024]; + FILE* file = fopen(name.c_str(), "rb"); + if (file == NULL) return false; + + while (true) { + size_t n = fread(buffer, 1, sizeof(buffer), file); + if (n <= 0) break; + output->append(buffer, n); + } + + int error = ferror(file); + if (fclose(file) != 0) return false; + return error == 0; +} + +void File::ReadFileToStringOrDie(const string& name, string* output) { + GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; +} + +void File::WriteStringToFileOrDie(const string& contents, const string& name) { + FILE* file = fopen(name.c_str(), "wb"); + GOOGLE_CHECK(file != NULL) + << "fopen(" << name << ", \"wb\"): " << strerror(errno); + GOOGLE_CHECK_EQ(fwrite(contents.data(), 1, contents.size(), file), + contents.size()) + << "fwrite(" << name << "): " << strerror(errno); + GOOGLE_CHECK(fclose(file) == 0) + << "fclose(" << name << "): " << strerror(errno); +} + +bool File::CreateDir(const string& name, int mode) { + return mkdir(name.c_str(), mode) == 0; +} + +bool File::RecursivelyCreateDir(const string& path, int mode) { + if (CreateDir(path, mode)) return true; + + if (Exists(path)) return false; + + // Try creating the parent. + string::size_type slashpos = path.find_last_of('/'); + if (slashpos == string::npos) { + // No parent given. + return false; + } + + return RecursivelyCreateDir(path.substr(0, slashpos), mode) && + CreateDir(path, mode); +} + +void File::DeleteRecursively(const string& name, + void* dummy1, void* dummy2) { + // 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); + if (find_handle == INVALID_HANDLE_VALUE) { + // Just delete it, whatever it is. + DeleteFile(name.c_str()); + RemoveDirectory(name.c_str()); + return; + } + + do { + string entry_name = find_data.cFileName; + if (entry_name != "." && entry_name != "..") { + string path = name + "/" + entry_name; + if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + DeleteRecursively(path, NULL, NULL); + RemoveDirectory(path.c_str()); + } else { + DeleteFile(path.c_str()); + } + } + } while(FindNextFile(find_handle, &find_data)); + FindClose(find_handle); + + RemoveDirectory(name.c_str()); +#else + // Use opendir()! Yay! + // lstat = Don't follow symbolic links. + struct stat stats; + if (lstat(name.c_str(), &stats) != 0) return; + + if (S_ISDIR(stats.st_mode)) { + DIR* dir = opendir(name.c_str()); + if (dir != NULL) { + while (true) { + struct dirent* entry = readdir(dir); + if (entry == NULL) break; + string entry_name = entry->d_name; + if (entry_name != "." && entry_name != "..") { + DeleteRecursively(name + "/" + entry_name, NULL, NULL); + } + } + } + + closedir(dir); + rmdir(name.c_str()); + + } else if (S_ISREG(stats.st_mode)) { + remove(name.c_str()); + } +#endif +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.h new file mode 100644 index 000000000..a6b1c7641 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/file.h @@ -0,0 +1,83 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// emulates google3/file/base/file.h + +#ifndef GOOGLE_PROTOBUF_TESTING_FILE_H__ +#define GOOGLE_PROTOBUF_TESTING_FILE_H__ + +#include + +namespace google { +namespace protobuf { + +const int DEFAULT_FILE_MODE = 0777; + +// Protocol buffer code only uses a couple static methods of File, and only +// in tests. +class File { + public: + // Check if the file exists. + static bool Exists(const string& name); + + // Read an entire file to a string. Return true if successful, false + // otherwise. + static bool ReadFileToString(const string& name, string* output); + + // Same as above, but crash on failure. + static void ReadFileToStringOrDie(const string& name, string* output); + + // Create a file and write a string to it. + static void WriteStringToFileOrDie(const string& contents, + const string& name); + + // Create a directory. + static bool CreateDir(const string& name, int mode); + + // Create a directory and all parent directories if necessary. + static bool RecursivelyCreateDir(const string& path, int mode); + + // If "name" is a file, we delete it. If it is a directory, we + // call DeleteRecursively() for each file or directory (other than + // dot and double-dot) within it, and then delete the directory itself. + // The "dummy" parameters have a meaning in the original version of this + // method but they are not used anywhere in protocol buffers. + static void DeleteRecursively(const string& name, + void* dummy1, void* dummy2); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(File); +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TESTING_FILE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.cc new file mode 100644 index 000000000..a8da6b1d1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.cc @@ -0,0 +1,255 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// emulates google3/testing/base/public/googletest.cc + +#include +#include +#include +#include +#include +#include +#include +#ifdef _MSC_VER +#include +#include +#else +#include +#endif +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +#ifdef _WIN32 +#define mkdir(name, mode) mkdir(name) +#endif + +#ifndef O_BINARY +#ifdef _O_BINARY +#define O_BINARY _O_BINARY +#else +#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. +#endif +#endif + +string TestSourceDir() { +#ifdef _MSC_VER + // Look for the "src" directory. + string prefix = "."; + + while (!File::Exists(prefix + "/src/google/protobuf")) { + if (!File::Exists(prefix)) { + GOOGLE_LOG(FATAL) + << "Could not find protobuf source code. Please run tests from " + "somewhere within the protobuf source package."; + } + prefix += "/.."; + } + return prefix + "/src"; +#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 +} + +namespace { + +string GetTemporaryDirectoryName() { + // 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 + // 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); + } +#endif // _WIN32 + return result; +} + +// Creates a temporary directory on demand and deletes it when the process +// quits. +class TempDirDeleter { + public: + TempDirDeleter() {} + ~TempDirDeleter() { + if (!name_.empty()) { + File::DeleteRecursively(name_, NULL, NULL); + } + } + + string GetTempDir() { + if (name_.empty()) { + name_ = GetTemporaryDirectoryName(); + GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno); + + // Stick a file in the directory that tells people what this is, in case + // we abort and don't get a chance to delete it. + File::WriteStringToFileOrDie("", name_ + "/TEMP_DIR_FOR_PROTOBUF_TESTS"); + } + return name_; + } + + private: + string name_; +}; + +TempDirDeleter temp_dir_deleter_; + +} // namespace + +string TestTempDir() { + return temp_dir_deleter_.GetTempDir(); +} + +// TODO(kenton): Share duplicated code below. Too busy/lazy for now. + +static string stdout_capture_filename_; +static string stderr_capture_filename_; +static int original_stdout_ = -1; +static int original_stderr_ = -1; + +void CaptureTestStdout() { + GOOGLE_CHECK_EQ(original_stdout_, -1) << "Already capturing."; + + stdout_capture_filename_ = TestTempDir() + "/captured_stdout"; + + int fd = open(stdout_capture_filename_.c_str(), + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777); + GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno); + + original_stdout_ = dup(1); + close(1); + dup2(fd, 1); + close(fd); +} + +void CaptureTestStderr() { + GOOGLE_CHECK_EQ(original_stderr_, -1) << "Already capturing."; + + stderr_capture_filename_ = TestTempDir() + "/captured_stderr"; + + int fd = open(stderr_capture_filename_.c_str(), + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0777); + GOOGLE_CHECK(fd >= 0) << "open: " << strerror(errno); + + original_stderr_ = dup(2); + close(2); + dup2(fd, 2); + close(fd); +} + +string GetCapturedTestStdout() { + GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing."; + + close(1); + dup2(original_stdout_, 1); + original_stdout_ = -1; + + string result; + File::ReadFileToStringOrDie(stdout_capture_filename_, &result); + + remove(stdout_capture_filename_.c_str()); + + return result; +} + +string GetCapturedTestStderr() { + GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing."; + + close(2); + dup2(original_stderr_, 2); + original_stderr_ = -1; + + string result; + File::ReadFileToStringOrDie(stderr_capture_filename_, &result); + + remove(stderr_capture_filename_.c_str()); + + return result; +} + +ScopedMemoryLog* ScopedMemoryLog::active_log_ = NULL; + +ScopedMemoryLog::ScopedMemoryLog() { + GOOGLE_CHECK(active_log_ == NULL); + active_log_ = this; + old_handler_ = SetLogHandler(&HandleLog); +} + +ScopedMemoryLog::~ScopedMemoryLog() { + SetLogHandler(old_handler_); + active_log_ = NULL; +} + +const vector& ScopedMemoryLog::GetMessages(LogLevel level) { + GOOGLE_CHECK(level == ERROR || + level == WARNING); + return messages_[level]; +} + +void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, + int line, const string& message) { + GOOGLE_CHECK(active_log_ != NULL); + if (level == ERROR || level == WARNING) { + active_log_->messages_[level].push_back(message); + } +} + +namespace { + +// Force shutdown at process exit so that we can test for memory leaks. To +// actually check for leaks, I suggest using the heap checker included with +// google-perftools. Set it to "draconian" mode to ensure that every last +// call to malloc() has a corresponding free(). +struct ForceShutdown { + ~ForceShutdown() { + ShutdownProtobufLibrary(); + } +} force_shutdown; + +} // namespace + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.h new file mode 100644 index 000000000..003be1060 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/googletest.h @@ -0,0 +1,102 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// emulates google3/testing/base/public/googletest.h + +#ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__ +#define GOOGLE_PROTOBUF_GOOGLETEST_H__ + +#include +#include +#include + +// Disable death tests if we use exceptions in CHECK(). +#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) +#define PROTOBUF_HAS_DEATH_TEST +#endif + +namespace google { +namespace protobuf { + +// When running unittests, get the directory containing the source code. +string TestSourceDir(); + +// When running unittests, get a directory where temporary files may be +// placed. +string TestTempDir(); + +// Capture all text written to stdout or stderr. +void CaptureTestStdout(); +void CaptureTestStderr(); + +// Stop capturing stdout or stderr and return the text captured. +string GetCapturedTestStdout(); +string GetCapturedTestStderr(); + +// For use with ScopedMemoryLog::GetMessages(). Inside Google the LogLevel +// constants don't have the LOGLEVEL_ prefix, so the code that used +// ScopedMemoryLog refers to LOGLEVEL_ERROR as just ERROR. +#undef ERROR // defend against promiscuous windows.h +static const LogLevel ERROR = LOGLEVEL_ERROR; +static const LogLevel WARNING = LOGLEVEL_WARNING; + +// Receives copies of all LOG(ERROR) messages while in scope. Sample usage: +// { +// ScopedMemoryLog log; // constructor registers object as a log sink +// SomeRoutineThatMayLogMessages(); +// const vector& warnings = log.GetMessages(ERROR); +// } // destructor unregisters object as a log sink +// This is a dummy implementation which covers only what is used by protocol +// buffer unit tests. +class ScopedMemoryLog { + public: + ScopedMemoryLog(); + virtual ~ScopedMemoryLog(); + + // Fetches all messages with the given severity level. + const vector& GetMessages(LogLevel error); + + private: + map > messages_; + LogHandler* old_handler_; + + static void HandleLog(LogLevel level, const char* filename, int line, + const string& message); + + static ScopedMemoryLog* active_log_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedMemoryLog); +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_GOOGLETEST_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgunzip.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgunzip.cc new file mode 100644 index 000000000..a6197854b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgunzip.cc @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2009 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: brianolson@google.com (Brian Olson) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Test program to verify that GzipInputStream is compatible with command line +// gunzip or java.util.zip.GzipInputStream +// +// Reads gzip stream on standard input and writes decompressed data to standard +// output. + +#include "config.h" + +#include +#include +#include +#include + +#include +#include + +using google::protobuf::io::FileInputStream; +using google::protobuf::io::GzipInputStream; + +int main(int argc, const char** argv) { + FileInputStream fin(STDIN_FILENO); + GzipInputStream in(&fin); + + while (true) { + const void* inptr; + int inlen; + bool ok; + ok = in.Next(&inptr, &inlen); + if (!ok) { + break; + } + if (inlen > 0) { + int err = write(STDOUT_FILENO, inptr, inlen); + assert(err == inlen); + } + } + + return 0; +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgzip.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgzip.cc new file mode 100644 index 000000000..9133275c8 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/testing/zcgzip.cc @@ -0,0 +1,79 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2009 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: brianolson@google.com (Brian Olson) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Test program to verify that GzipOutputStream is compatible with command line +// gzip or java.util.zip.GzipOutputStream +// +// Reads data on standard input and writes compressed gzip stream to standard +// output. + +#include "config.h" + +#include +#include +#include + +#include +#include + +using google::protobuf::io::FileOutputStream; +using google::protobuf::io::GzipOutputStream; + +int main(int argc, const char** argv) { + FileOutputStream fout(STDOUT_FILENO); + GzipOutputStream out(&fout); + int readlen; + + while (true) { + void* outptr; + int outlen; + bool ok; + do { + ok = out.Next(&outptr, &outlen); + if (!ok) { + break; + } + } while (outlen <= 0); + readlen = read(STDIN_FILENO, outptr, outlen); + if (readlen <= 0) { + out.BackUp(outlen); + break; + } + if (readlen < outlen) { + out.BackUp(outlen - readlen); + } + } + + return 0; +} diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.cc new file mode 100644 index 000000000..cabb99ed9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.cc @@ -0,0 +1,1521 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: jschorr@google.com (Joseph Schorr) +// 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 + +namespace google { +namespace protobuf { + +string Message::DebugString() const { + string debug_string; + + TextFormat::PrintToString(*this, &debug_string); + + return debug_string; +} + +string Message::ShortDebugString() const { + string debug_string; + + TextFormat::Printer printer; + printer.SetSingleLineMode(true); + + printer.PrintToString(*this, &debug_string); + // Single line mode currently might have an extra space at the end. + if (debug_string.size() > 0 && + debug_string[debug_string.size() - 1] == ' ') { + debug_string.resize(debug_string.size() - 1); + } + + return debug_string; +} + +string Message::Utf8DebugString() const { + string debug_string; + + TextFormat::Printer printer; + printer.SetUseUtf8StringEscaping(true); + + printer.PrintToString(*this, &debug_string); + + return debug_string; +} + +void Message::PrintDebugString() const { + printf("%s", DebugString().c_str()); +} + + +// =========================================================================== +// Implementation of the parse information tree class. +TextFormat::ParseInfoTree::ParseInfoTree() { } + +TextFormat::ParseInfoTree::~ParseInfoTree() { + // Remove any nested information trees, as they are owned by this tree. + for (NestedMap::iterator it = nested_.begin(); it != nested_.end(); ++it) { + STLDeleteElements(&(it->second)); + } +} + +void TextFormat::ParseInfoTree::RecordLocation( + const FieldDescriptor* field, + TextFormat::ParseLocation location) { + locations_[field].push_back(location); +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( + const FieldDescriptor* field) { + // Owned by us in the map. + TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); + vector* trees = &nested_[field]; + GOOGLE_CHECK(trees); + trees->push_back(instance); + return instance; +} + +void CheckFieldIndex(const FieldDescriptor* field, int index) { + if (field == NULL) { return; } + + if (field->is_repeated() && index == -1) { + GOOGLE_LOG(DFATAL) << "Index must be in range of repeated field values. " + << "Field: " << field->name(); + } else if (!field->is_repeated() && index != -1) { + GOOGLE_LOG(DFATAL) << "Index must be -1 for singular fields." + << "Field: " << field->name(); + } +} + +TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { index = 0; } + + const vector* locations = + FindOrNull(locations_, field); + if (locations == NULL || index >= locations->size()) { + return TextFormat::ParseLocation(); + } + + return (*locations)[index]; +} + +TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( + const FieldDescriptor* field, int index) const { + CheckFieldIndex(field, index); + if (index == -1) { index = 0; } + + const vector* trees = FindOrNull(nested_, field); + if (trees == NULL || index >= trees->size()) { + return NULL; + } + + return (*trees)[index]; +} + + +// =========================================================================== +// Internal class for parsing an ASCII representation of a Protocol Message. +// This class makes use of the Protocol Message compiler's tokenizer found +// in //google/protobuf/io/tokenizer.h. Note that class's Parse +// method is *not* thread-safe and should only be used in a single thread at +// a time. + +// Makes code slightly more readable. The meaning of "DO(foo)" is +// "Execute foo and fail if it fails.", where failure is indicated by +// returning false. Borrowed from parser.cc (Thanks Kenton!). +#define DO(STATEMENT) if (STATEMENT) {} else return false + +class TextFormat::Parser::ParserImpl { + public: + + // Determines if repeated values for a non-repeated field are + // permitted, e.g., the string "foo: 1 foo: 2" for a + // required/optional field named "foo". + enum SingularOverwritePolicy { + ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained + FORBID_SINGULAR_OVERWRITES = 1, // an error is issued + }; + + ParserImpl(const Descriptor* root_message_type, + io::ZeroCopyInputStream* input_stream, + io::ErrorCollector* error_collector, + TextFormat::Finder* finder, + ParseInfoTree* parse_info_tree, + SingularOverwritePolicy singular_overwrite_policy, + bool allow_unknown_field) + : error_collector_(error_collector), + finder_(finder), + parse_info_tree_(parse_info_tree), + tokenizer_error_collector_(this), + tokenizer_(input_stream, &tokenizer_error_collector_), + root_message_type_(root_message_type), + singular_overwrite_policy_(singular_overwrite_policy), + allow_unknown_field_(allow_unknown_field), + had_errors_(false) { + // For backwards-compatibility with proto1, we need to allow the 'f' suffix + // for floats. + tokenizer_.set_allow_f_after_float(true); + + // '#' starts a comment. + tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); + + // Consume the starting token. + tokenizer_.Next(); + } + ~ParserImpl() { } + + // Parses the ASCII representation specified in input and saves the + // information into the output pointer (a Message). Returns + // false if an error occurs (an error will also be logged to + // GOOGLE_LOG(ERROR)). + bool Parse(Message* output) { + // Consume fields until we cannot do so anymore. + while(true) { + if (LookingAtType(io::Tokenizer::TYPE_END)) { + return !had_errors_; + } + + DO(ConsumeField(output)); + } + } + + bool ParseField(const FieldDescriptor* field, Message* output) { + bool suc; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + suc = ConsumeFieldMessage(output, output->GetReflection(), field); + } else { + suc = ConsumeFieldValue(output, output->GetReflection(), field); + } + return suc && LookingAtType(io::Tokenizer::TYPE_END); + } + + void ReportError(int line, int col, const string& message) { + had_errors_ = true; + if (error_collector_ == NULL) { + if (line >= 0) { + GOOGLE_LOG(ERROR) << "Error parsing text-format " + << root_message_type_->full_name() + << ": " << (line + 1) << ":" + << (col + 1) << ": " << message; + } else { + GOOGLE_LOG(ERROR) << "Error parsing text-format " + << root_message_type_->full_name() + << ": " << message; + } + } else { + error_collector_->AddError(line, col, message); + } + } + + void ReportWarning(int line, int col, const string& message) { + if (error_collector_ == NULL) { + if (line >= 0) { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() + << ": " << (line + 1) << ":" + << (col + 1) << ": " << message; + } else { + GOOGLE_LOG(WARNING) << "Warning parsing text-format " + << root_message_type_->full_name() + << ": " << message; + } + } else { + error_collector_->AddWarning(line, col, message); + } + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl); + + // Reports an error with the given message with information indicating + // the position (as derived from the current token). + void ReportError(const string& message) { + ReportError(tokenizer_.current().line, tokenizer_.current().column, + message); + } + + // Reports a warning with the given message with information indicating + // the position (as derived from the current token). + void ReportWarning(const string& message) { + ReportWarning(tokenizer_.current().line, tokenizer_.current().column, + 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) { + while (!LookingAt(">") && !LookingAt("}")) { + DO(ConsumeField(message)); + } + + // Confirm that we have a valid ending delimeter. + DO(Consume(delimeter)); + + return true; + } + + // Consumes the current field (as returned by the tokenizer) on the + // passed in message. + bool ConsumeField(Message* message) { + const Reflection* reflection = message->GetReflection(); + const Descriptor* descriptor = message->GetDescriptor(); + + string field_name; + + const FieldDescriptor* field = NULL; + int start_line = tokenizer_.current().line; + int start_column = tokenizer_.current().column; + + if (TryConsume("[")) { + // Extension. + DO(ConsumeIdentifier(&field_name)); + while (TryConsume(".")) { + string part; + DO(ConsumeIdentifier(&part)); + field_name += "."; + field_name += part; + } + DO(Consume("]")); + + field = (finder_ != NULL + ? finder_->FindExtension(message, field_name) + : reflection->FindKnownExtensionByName(field_name)); + + if (field == NULL) { + if (!allow_unknown_field_) { + ReportError("Extension \"" + field_name + "\" is not defined or " + "is not an extension of \"" + + descriptor->full_name() + "\"."); + return false; + } else { + ReportWarning("Extension \"" + field_name + "\" is not defined or " + "is not an extension of \"" + + descriptor->full_name() + "\"."); + } + } + } else { + DO(ConsumeIdentifier(&field_name)); + + field = descriptor->FindFieldByName(field_name); + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their field + // names. + if (field == NULL) { + string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByName(lower_field_name); + // If the case-insensitive match worked but the field is NOT a group, + if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { + field = NULL; + } + } + // Again, special-case group names as described above. + if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP + && field->message_type()->name() != field_name) { + field = NULL; + } + + if (field == NULL) { + if (!allow_unknown_field_) { + ReportError("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + return false; + } else { + ReportWarning("Message type \"" + descriptor->full_name() + + "\" has no field named \"" + field_name + "\"."); + } + } + } + + // Skips unknown field. + if (field == NULL) { + GOOGLE_CHECK(allow_unknown_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. + // 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("<")) { + return SkipFieldValue(); + } else { + return SkipFieldMessage(); + } + } + + // Fail if the field is not repeated and it has already been specified. + if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) && + !field->is_repeated() && reflection->HasField(*message, field)) { + ReportError("Non-repeated field \"" + field_name + + "\" is specified multiple times."); + return false; + } + + // Perform special handling for embedded message types. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // ':' is optional here. + TryConsume(":"); + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(Consume(":")); + if (field->is_repeated() && TryConsume("[")) { + // Short repeated format, e.g. "foo: [1, 2, 3]" + while (true) { + DO(ConsumeFieldValue(message, reflection, field)); + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } + } + + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + + if (field->options().deprecated()) { + ReportWarning("text format contains deprecated field \"" + + field_name + "\""); + } + + // If a parse info tree exists, add the location for the parsed + // field. + if (parse_info_tree_ != NULL) { + RecordLocation(parse_info_tree_, field, + ParseLocation(start_line, start_column)); + } + + return true; + } + + // 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; + } + DO(Consume("]")); + } else { + 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. + // 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("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + return true; + } + + bool ConsumeFieldMessage(Message* message, + const Reflection* reflection, + const FieldDescriptor* field) { + + // If the parse information tree is not NULL, create a nested one + // for the nested message. + ParseInfoTree* parent = parse_info_tree_; + if (parent != NULL) { + parse_info_tree_ = CreateNested(parent, field); + } + + string delimeter; + if (TryConsume("<")) { + delimeter = ">"; + } else { + DO(Consume("{")); + delimeter = "}"; + } + + if (field->is_repeated()) { + DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); + } else { + DO(ConsumeMessage(reflection->MutableMessage(message, field), + delimeter)); + } + + // Reset the parse information tree. + parse_info_tree_ = parent; + return true; + } + + // Skips the whole body of a message including the begining delimeter and + // the ending delimeter. + bool SkipFieldMessage() { + string delimeter; + if (TryConsume("<")) { + delimeter = ">"; + } else { + DO(Consume("{")); + delimeter = "}"; + } + while (!LookingAt(">") && !LookingAt("}")) { + DO(SkipField()); + } + DO(Consume(delimeter)); + return true; + } + + bool ConsumeFieldValue(Message* message, + const Reflection* reflection, + const FieldDescriptor* field) { + +// Define an easy to use macro for setting fields. This macro checks +// to see if the field is repeated (in which case we need to use the Add +// methods or not (in which case we need to use the Set methods). +#define SET_FIELD(CPPTYPE, VALUE) \ + if (field->is_repeated()) { \ + reflection->Add##CPPTYPE(message, field, VALUE); \ + } else { \ + reflection->Set##CPPTYPE(message, field, VALUE); \ + } \ + + switch(field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + int64 value; + DO(ConsumeSignedInteger(&value, kint32max)); + SET_FIELD(Int32, static_cast(value)); + break; + } + + case FieldDescriptor::CPPTYPE_UINT32: { + uint64 value; + DO(ConsumeUnsignedInteger(&value, kuint32max)); + SET_FIELD(UInt32, static_cast(value)); + break; + } + + case FieldDescriptor::CPPTYPE_INT64: { + int64 value; + DO(ConsumeSignedInteger(&value, kint64max)); + SET_FIELD(Int64, value); + break; + } + + case FieldDescriptor::CPPTYPE_UINT64: { + uint64 value; + DO(ConsumeUnsignedInteger(&value, kuint64max)); + SET_FIELD(UInt64, value); + break; + } + + case FieldDescriptor::CPPTYPE_FLOAT: { + double value; + DO(ConsumeDouble(&value)); + SET_FIELD(Float, static_cast(value)); + break; + } + + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value; + DO(ConsumeDouble(&value)); + SET_FIELD(Double, value); + break; + } + + case FieldDescriptor::CPPTYPE_STRING: { + string value; + DO(ConsumeString(&value)); + SET_FIELD(String, value); + break; + } + + case FieldDescriptor::CPPTYPE_BOOL: { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + uint64 value; + DO(ConsumeUnsignedInteger(&value, 1)); + SET_FIELD(Bool, value); + } else { + string value; + DO(ConsumeIdentifier(&value)); + if (value == "true" || value == "t") { + SET_FIELD(Bool, true); + } else if (value == "false" || value == "f") { + SET_FIELD(Bool, false); + } else { + ReportError("Invalid value for boolean field \"" + field->name() + + "\". Value: \"" + value + "\"."); + return false; + } + } + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: { + string value; + const EnumDescriptor* enum_type = field->enum_type(); + const EnumValueDescriptor* enum_value = NULL; + + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&value)); + // Find the enumeration value. + enum_value = enum_type->FindValueByName(value); + + } else if (LookingAt("-") || + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + int64 int_value; + DO(ConsumeSignedInteger(&int_value, kint32max)); + value = SimpleItoa(int_value); // for error reporting + enum_value = enum_type->FindValueByNumber(int_value); + } else { + ReportError("Expected integer or identifier."); + return false; + } + + if (enum_value == NULL) { + ReportError("Unknown enumeration value of \"" + value + "\" for " + "field \"" + field->name() + "\"."); + return false; + } + + SET_FIELD(Enum, enum_value); + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: { + // We should never get here. Put here instead of a default + // so that if new types are added, we get a nice compiler warning. + GOOGLE_LOG(FATAL) << "Reached an unintended state: CPPTYPE_MESSAGE"; + break; + } + } +#undef SET_FIELD + return true; + } + + bool SkipFieldValue() { + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + tokenizer_.Next(); + } + return true; + } + // Possible field values other than string: + // 12345 => TYPE_INTEGER + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Divides them into two group, one with TYPE_SYMBOL + // and the other without: + // Group one: + // 12345 => TYPE_INTEGER + // 1.2345 => TYPE_FLOAT + // inf => TYPE_IDENTIFIER + // TYPE_INTEGER => TYPE_IDENTIFIER + // Group two: + // -12345 => TYPE_SYMBOL + TYPE_INTEGER + // -1.2345 => TYPE_SYMBOL + TYPE_FLOAT + // -inf => TYPE_SYMBOL + TYPE_IDENTIFIER + // As we can see, the field value consists of an optional '-' and one of + // TYPE_INTEGER, TYPE_FLOAT and TYPE_IDENTIFIER. + bool has_minus = TryConsume("-"); + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER) && + !LookingAtType(io::Tokenizer::TYPE_FLOAT) && + !LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + return false; + } + // Combination of '-' and TYPE_IDENTIFIER may result in an invalid field + // value while other combinations all generate valid values. + // We check if the value of this combination is valid here. + // TYPE_IDENTIFIER after a '-' should be one of the float values listed + // below: + // inf, inff, infinity, nan + if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + string text = tokenizer_.current().text; + LowerString(&text); + if (text != "inf" && + text != "infinity" && + text != "nan") { + ReportError("Invalid float number: " + text); + return false; + } + } + tokenizer_.Next(); + return true; + } + + // Returns true if the current token's text is equal to that specified. + bool LookingAt(const string& text) { + return tokenizer_.current().text == text; + } + + // Returns true if the current token's type is equal to that specified. + bool LookingAtType(io::Tokenizer::TokenType token_type) { + return tokenizer_.current().type == token_type; + } + + // Consumes an identifier and saves its value in the identifier parameter. + // Returns false if the token is not of type IDENTFIER. + bool ConsumeIdentifier(string* identifier) { + if (!LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + ReportError("Expected identifier."); + return false; + } + + *identifier = tokenizer_.current().text; + + tokenizer_.Next(); + 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."); + return false; + } + + text->clear(); + while (LookingAtType(io::Tokenizer::TYPE_STRING)) { + io::Tokenizer::ParseStringAppend(tokenizer_.current().text, text); + + tokenizer_.Next(); + } + + return true; + } + + // Consumes a uint64 and saves its value in the value parameter. + // 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."); + return false; + } + + if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, + max_value, value)) { + ReportError("Integer out of range."); + return false; + } + + tokenizer_.Next(); + return true; + } + + // Consumes an int64 and saves its value in the value parameter. + // Note that since the tokenizer does not support negative numbers, + // we actually may consume an additional token (for the minus sign) in this + // method. Returns false if the token is not an integer + // (signed or otherwise). + bool ConsumeSignedInteger(int64* value, uint64 max_value) { + bool negative = false; + + if (TryConsume("-")) { + negative = true; + // Two's complement always allows one more negative integer than + // positive. + ++max_value; + } + + uint64 unsigned_value; + + DO(ConsumeUnsignedInteger(&unsigned_value, max_value)); + + *value = static_cast(unsigned_value); + + if (negative) { + *value = -*value; + } + + return true; + } + + // Consumes a double and saves its value in the value parameter. + // Note that since the tokenizer does not support negative numbers, + // we actually may consume an additional token (for the minus sign) in this + // method. Returns false if the token is not a double + // (signed or otherwise). + bool ConsumeDouble(double* value) { + bool negative = false; + + if (TryConsume("-")) { + negative = true; + } + + // A double can actually be an integer, according to the tokenizer. + // Therefore, we must check both cases here. + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + // We have found an integer value for the double. + uint64 integer_value; + DO(ConsumeUnsignedInteger(&integer_value, kuint64max)); + + *value = static_cast(integer_value); + } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { + // We have found a float value for the double. + *value = io::Tokenizer::ParseFloat(tokenizer_.current().text); + + // Mark the current token as consumed. + tokenizer_.Next(); + } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + string text = tokenizer_.current().text; + LowerString(&text); + if (text == "inf" || + text == "infinity") { + *value = std::numeric_limits::infinity(); + tokenizer_.Next(); + } else if (text == "nan") { + *value = std::numeric_limits::quiet_NaN(); + tokenizer_.Next(); + } else { + ReportError("Expected double."); + return false; + } + } else { + ReportError("Expected double."); + return false; + } + + if (negative) { + *value = -*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. + bool Consume(const string& value) { + const string& current_value = tokenizer_.current().text; + + if (current_value != value) { + ReportError("Expected \"" + value + "\", found \"" + current_value + + "\"."); + return false; + } + + tokenizer_.Next(); + + return true; + } + + // Attempts to consume the supplied value. Returns false if a the + // token found does not match the value specified. + bool TryConsume(const string& value) { + if (tokenizer_.current().text == value) { + tokenizer_.Next(); + return true; + } else { + return false; + } + } + + // An internal instance of the Tokenizer's error collector, used to + // collect any base-level parse errors and feed them to the ParserImpl. + class ParserErrorCollector : public io::ErrorCollector { + public: + explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) : + parser_(parser) { } + + virtual ~ParserErrorCollector() { }; + + virtual void AddError(int line, int column, const string& message) { + parser_->ReportError(line, column, message); + } + + virtual void AddWarning(int line, int column, const string& message) { + parser_->ReportWarning(line, column, message); + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector); + TextFormat::Parser::ParserImpl* parser_; + }; + + io::ErrorCollector* error_collector_; + TextFormat::Finder* finder_; + ParseInfoTree* parse_info_tree_; + ParserErrorCollector tokenizer_error_collector_; + io::Tokenizer tokenizer_; + const Descriptor* root_message_type_; + SingularOverwritePolicy singular_overwrite_policy_; + bool allow_unknown_field_; + bool had_errors_; +}; + +#undef DO + +// =========================================================================== +// Internal class for writing text to the io::ZeroCopyOutputStream. Adapted +// from the Printer found in //google/protobuf/io/printer.h +class TextFormat::Printer::TextGenerator { + public: + explicit TextGenerator(io::ZeroCopyOutputStream* output, + int initial_indent_level) + : output_(output), + buffer_(NULL), + buffer_size_(0), + at_start_of_line_(true), + failed_(false), + indent_(""), + initial_indent_level_(initial_indent_level) { + indent_.resize(initial_indent_level_ * 2, ' '); + } + + ~TextGenerator() { + // Only BackUp() if we're sure we've successfully called Next() at least + // once. + if (!failed_ && buffer_size_ > 0) { + output_->BackUp(buffer_size_); + } + } + + // 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_ += " "; + } + + // 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) { + GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; + return; + } + + indent_.resize(indent_.size() - 2); + } + + // 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. + 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 + // crash in this case because this is an I/O failure, not a programming + // error.) + bool failed() const { return failed_; } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator); + + void Write(const char* data, int 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()); + if (failed_) return; + } + + while (size > buffer_size_) { + // Data exceeds space in the buffer. Copy what we can and request a + // new buffer. + memcpy(buffer_, data, buffer_size_); + data += buffer_size_; + size -= buffer_size_; + void* void_buffer; + 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; + } + + io::ZeroCopyOutputStream* const output_; + char* buffer_; + int buffer_size_; + bool at_start_of_line_; + bool failed_; + + string indent_; + int initial_indent_level_; +}; + +// =========================================================================== + +TextFormat::Finder::~Finder() { +} + +TextFormat::Parser::Parser() + : error_collector_(NULL), + finder_(NULL), + parse_info_tree_(NULL), + allow_partial_(false), + allow_unknown_field_(false) { +} + +TextFormat::Parser::~Parser() {} + +bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, + Message* output) { + output->Clear(); + ParserImpl parser(output->GetDescriptor(), input, error_collector_, + finder_, parse_info_tree_, + ParserImpl::FORBID_SINGULAR_OVERWRITES, + allow_unknown_field_); + return MergeUsingImpl(input, output, &parser); +} + +bool TextFormat::Parser::ParseFromString(const string& input, + Message* output) { + io::ArrayInputStream input_stream(input.data(), input.size()); + return Parse(&input_stream, output); +} + +bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, + Message* output) { + ParserImpl parser(output->GetDescriptor(), input, error_collector_, + finder_, parse_info_tree_, + ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_unknown_field_); + return MergeUsingImpl(input, output, &parser); +} + +bool TextFormat::Parser::MergeFromString(const string& input, + Message* output) { + io::ArrayInputStream input_stream(input.data(), input.size()); + 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; + output->FindInitializationErrors(&missing_fields); + parser_impl->ReportError(-1, 0, "Message missing required fields: " + + JoinStrings(missing_fields, ", ")); + return false; + } + return true; +} + +bool TextFormat::Parser::ParseFieldValueFromString( + const string& input, + const FieldDescriptor* field, + Message* output) { + io::ArrayInputStream input_stream(input.data(), input.size()); + ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, + finder_, parse_info_tree_, + ParserImpl::ALLOW_SINGULAR_OVERWRITES, + allow_unknown_field_); + return parser.ParseField(field, output); +} + +/* static */ bool TextFormat::Parse(io::ZeroCopyInputStream* input, + Message* output) { + return Parser().Parse(input, output); +} + +/* static */ bool TextFormat::Merge(io::ZeroCopyInputStream* input, + Message* output) { + return Parser().Merge(input, output); +} + +/* static */ bool TextFormat::ParseFromString(const string& input, + Message* output) { + return Parser().ParseFromString(input, output); +} + +/* static */ bool TextFormat::MergeFromString(const string& input, + Message* output) { + return Parser().MergeFromString(input, output); +} + +// =========================================================================== + +TextFormat::Printer::Printer() + : initial_indent_level_(0), + single_line_mode_(false), + use_short_repeated_primitives_(false), + utf8_string_escaping_(false) {} + +TextFormat::Printer::~Printer() {} + +bool TextFormat::Printer::PrintToString(const Message& message, + string* output) const { + GOOGLE_DCHECK(output) << "output specified is NULL"; + + output->clear(); + io::StringOutputStream output_stream(output); + + bool result = Print(message, &output_stream); + + return result; +} + +bool TextFormat::Printer::PrintUnknownFieldsToString( + const UnknownFieldSet& unknown_fields, + string* output) const { + GOOGLE_DCHECK(output) << "output specified is NULL"; + + output->clear(); + io::StringOutputStream output_stream(output); + return PrintUnknownFields(unknown_fields, &output_stream); +} + +bool TextFormat::Printer::Print(const Message& message, + io::ZeroCopyOutputStream* output) const { + TextGenerator generator(output, initial_indent_level_); + + Print(message, generator); + + // Output false if the generator failed internally. + return !generator.failed(); +} + +bool TextFormat::Printer::PrintUnknownFields( + const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output) const { + TextGenerator generator(output, initial_indent_level_); + + PrintUnknownFields(unknown_fields, generator); + + // Output false if the generator failed internally. + return !generator.failed(); +} + +void TextFormat::Printer::Print(const Message& message, + TextGenerator& generator) const { + const Reflection* reflection = message.GetReflection(); + vector fields; + reflection->ListFields(message, &fields); + for (int i = 0; i < fields.size(); i++) { + PrintField(message, reflection, fields[i], generator); + } + PrintUnknownFields(reflection->GetUnknownFields(message), generator); +} + +void TextFormat::Printer::PrintFieldValueToString( + const Message& message, + 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); +} + +void TextFormat::Printer::PrintField(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) const { + if (use_short_repeated_primitives_ && + field->is_repeated() && + field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + PrintShortRepeatedField(message, reflection, field, generator); + return; + } + + int count = 0; + + if (field->is_repeated()) { + count = reflection->FieldSize(message, field); + } else if (reflection->HasField(message, field)) { + count = 1; + } + + for (int j = 0; j < count; ++j) { + PrintFieldName(message, reflection, field, generator); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (single_line_mode_) { + generator.Print(" { "); + } else { + generator.Print(" {\n"); + generator.Indent(); + } + } else { + generator.Print(": "); + } + + // Write the field value. + int field_index = j; + if (!field->is_repeated()) { + field_index = -1; + } + + PrintFieldValue(message, reflection, field, field_index, generator); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (single_line_mode_) { + generator.Print("} "); + } else { + generator.Outdent(); + generator.Print("}\n"); + } + } else { + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); + } + } + } +} + +void TextFormat::Printer::PrintShortRepeatedField( + 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(": ["); + for (int i = 0; i < size; i++) { + if (i > 0) generator.Print(", "); + PrintFieldValue(message, reflection, field, i, generator); + } + if (single_line_mode_) { + generator.Print("] "); + } else { + generator.Print("]\n"); + } +} + +void TextFormat::Printer::PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) const { + if (field->is_extension()) { + generator.Print("["); + // 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.Print(field->message_type()->full_name()); + } else { + generator.Print(field->full_name()); + } + generator.Print("]"); + } else { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + generator.Print(field->message_type()->name()); + } else { + generator.Print(field->name()); + } + } +} + +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"; + + switch (field->cpp_type()) { +#define OUTPUT_FIELD(CPPTYPE, METHOD, TO_STRING) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + generator.Print(TO_STRING(field->is_repeated() ? \ + reflection->GetRepeated##METHOD(message, field, index) : \ + reflection->Get##METHOD(message, field))); \ + break; \ + + OUTPUT_FIELD( INT32, Int32, SimpleItoa); + OUTPUT_FIELD( INT64, Int64, SimpleItoa); + OUTPUT_FIELD(UINT32, UInt32, SimpleItoa); + OUTPUT_FIELD(UINT64, UInt64, SimpleItoa); + OUTPUT_FIELD( FLOAT, Float, SimpleFtoa); + OUTPUT_FIELD(DOUBLE, Double, SimpleDtoa); +#undef OUTPUT_FIELD + + case FieldDescriptor::CPPTYPE_STRING: { + string scratch; + const string& value = field->is_repeated() ? + reflection->GetRepeatedStringReference( + message, field, index, &scratch) : + reflection->GetStringReference(message, field, &scratch); + + generator.Print("\""); + if (utf8_string_escaping_) { + generator.Print(strings::Utf8SafeCEscape(value)); + } else { + generator.Print(CEscape(value)); + } + generator.Print("\""); + + break; + } + + case FieldDescriptor::CPPTYPE_BOOL: + if (field->is_repeated()) { + generator.Print(reflection->GetRepeatedBool(message, field, index) + ? "true" : "false"); + } else { + generator.Print(reflection->GetBool(message, field) + ? "true" : "false"); + } + break; + + case FieldDescriptor::CPPTYPE_ENUM: + generator.Print(field->is_repeated() ? + reflection->GetRepeatedEnum(message, field, index)->name() : + reflection->GetEnum(message, field)->name()); + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: + Print(field->is_repeated() ? + reflection->GetRepeatedMessage(message, field, index) : + reflection->GetMessage(message, field), + generator); + break; + } +} + +/* static */ bool TextFormat::Print(const Message& message, + io::ZeroCopyOutputStream* output) { + return Printer().Print(message, output); +} + +/* static */ bool TextFormat::PrintUnknownFields( + const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output) { + return Printer().PrintUnknownFields(unknown_fields, output); +} + +/* static */ bool TextFormat::PrintToString( + const Message& message, string* output) { + return Printer().PrintToString(message, output); +} + +/* static */ bool TextFormat::PrintUnknownFieldsToString( + const UnknownFieldSet& unknown_fields, string* output) { + return Printer().PrintUnknownFieldsToString(unknown_fields, output); +} + +/* static */ void TextFormat::PrintFieldValueToString( + const Message& message, + const FieldDescriptor* field, + int index, + string* output) { + return Printer().PrintFieldValueToString(message, field, index, output); +} + +/* static */ bool TextFormat::ParseFieldValueFromString( + const string& input, + const FieldDescriptor* field, + Message* message) { + return Parser().ParseFieldValueFromString(input, field, message); +} + +// Prints an integer as hex with a fixed number of digits dependent on the +// integer type. +template +static string PaddedHex(IntType value) { + string result; + result.reserve(sizeof(value) * 2); + for (int i = sizeof(value) * 2 - 1; i >= 0; i--) { + result.push_back(int_to_hex_digit(value >> (i*4) & 0x0F)); + } + return result; +} + +void TextFormat::Printer::PrintUnknownFields( + 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())); + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); + } + break; + case UnknownField::TYPE_FIXED32: { + generator.Print(field_number); + generator.Print(": 0x"); + char buffer[kFastToBufferSize]; + generator.Print(FastHex32ToBuffer(field.fixed32(), buffer)); + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); + } + break; + } + case UnknownField::TYPE_FIXED64: { + generator.Print(field_number); + generator.Print(": 0x"); + char buffer[kFastToBufferSize]; + generator.Print(FastHex64ToBuffer(field.fixed64(), buffer)); + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); + } + break; + } + case UnknownField::TYPE_LENGTH_DELIMITED: { + generator.Print(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(" { "); + } else { + generator.Print(" {\n"); + generator.Indent(); + } + PrintUnknownFields(embedded_unknown_fields, generator); + if (single_line_mode_) { + generator.Print("} "); + } else { + generator.Outdent(); + generator.Print("}\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("\""); + if (single_line_mode_) { + generator.Print(" "); + } else { + generator.Print("\n"); + } + } + break; + } + case UnknownField::TYPE_GROUP: + generator.Print(field_number); + if (single_line_mode_) { + generator.Print(" { "); + } else { + generator.Print(" {\n"); + generator.Indent(); + } + PrintUnknownFields(field.group(), generator); + if (single_line_mode_) { + generator.Print("} "); + } else { + generator.Outdent(); + generator.Print("}\n"); + } + break; + } + } +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.h new file mode 100644 index 000000000..01f3ffb08 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format.h @@ -0,0 +1,369 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Utilities for printing and parsing protocol messages in a human-readable, +// text-based format. + +#ifndef GOOGLE_PROTOBUF_TEXT_FORMAT_H__ +#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace io { + class ErrorCollector; // tokenizer.h +} + +// This class implements protocol buffer text format. Printing and parsing +// protocol messages in text format is useful for debugging and human editing +// of messages. +// +// This class is really a namespace that contains only static methods. +class LIBPROTOBUF_EXPORT TextFormat { + public: + // Outputs a textual representation of the given message to the given + // output stream. + 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. + static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output); + + // Like Print(), but outputs directly to a string. + static bool PrintToString(const Message& message, string* output); + + // Like PrintUnknownFields(), but outputs directly to a string. + static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, + string* output); + + // Outputs a textual representation of the value of the field supplied on + // the message supplied. For non-repeated fields, an index of -1 must + // be supplied. Note that this method will print the default value for a + // field if it is not set. + static void PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, + int index, + string* output); + + // Class for those users which require more fine-grained control over how + // a protobuffer message is printed out. + class LIBPROTOBUF_EXPORT Printer { + public: + Printer(); + ~Printer(); + + // Like TextFormat::Print + bool Print(const Message& message, io::ZeroCopyOutputStream* output) const; + // Like TextFormat::PrintUnknownFields + bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, + io::ZeroCopyOutputStream* output) const; + // Like TextFormat::PrintToString + bool PrintToString(const Message& message, string* output) const; + // Like TextFormat::PrintUnknownFieldsToString + bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, + string* output) const; + // Like TextFormat::PrintFieldValueToString + void PrintFieldValueToString(const Message& message, + const FieldDescriptor* field, + int index, + string* output) const; + + // Adjust the initial indent level of all output. Each indent level is + // equal to two spaces. + void SetInitialIndentLevel(int indent_level) { + initial_indent_level_ = indent_level; + } + + // If printing in single line mode, then the entire message will be output + // on a single line with no line breaks. + void SetSingleLineMode(bool single_line_mode) { + single_line_mode_ = single_line_mode; + } + + // Set true to print repeated primitives in a format like: + // field_name: [1, 2, 3, 4] + // instead of printing each value on its own line. Short format applies + // only to primitive values -- i.e. everything except strings and + // sub-messages/groups. + void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) { + use_short_repeated_primitives_ = use_short_repeated_primitives; + } + + // 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. + void SetUseUtf8StringEscaping(bool as_utf8) { + utf8_string_escaping_ = as_utf8; + } + + private: + // Forward declaration of an internal class used to print the text + // output to the OutputStream (see text_format.cc for implementation). + class TextGenerator; + + // Internal Print method, used for writing to the OutputStream via + // the TextGenerator class. + void Print(const Message& message, + TextGenerator& generator) const; + + // Print a single field. + void PrintField(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + 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; + + // 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, + const FieldDescriptor* field, + 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; + + // 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; + + int initial_indent_level_; + + bool single_line_mode_; + + bool use_short_repeated_primitives_; + + bool utf8_string_escaping_; + }; + + // Parses a text-format protocol message from the given input stream to + // the given message object. This function parses the format written + // by Print(). + static bool Parse(io::ZeroCopyInputStream* input, Message* output); + // Like Parse(), but reads directly from a string. + static bool ParseFromString(const string& input, Message* output); + + // Like Parse(), but the data is merged into the given message, as if + // using Message::MergeFrom(). + static bool Merge(io::ZeroCopyInputStream* input, Message* output); + // Like Merge(), but reads directly from a string. + static bool MergeFromString(const string& input, Message* output); + + // Parse the given text as a single field value and store it into the + // given field of the given message. If the field is a repeated field, + // the new value will be added to the end + static bool ParseFieldValueFromString(const string& input, + 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; + int column; + + ParseLocation() : line(-1), column(-1) {} + ParseLocation(int line_param, int column_param) + : line(line_param), column(column_param) {} + }; + + // Data structure which is populated with the locations of each field + // value parsed from the text. + class LIBPROTOBUF_EXPORT ParseInfoTree { + public: + ParseInfoTree(); + ~ParseInfoTree(); + + // Returns the parse location for index-th value of the field in the parsed + // text. If none exists, returns a location with line = -1. Index should be + // -1 for not-repeated fields. + ParseLocation GetLocation(const FieldDescriptor* field, int index) const; + + // Returns the parse info tree for the given field, which must be a message + // type. The nested information tree is owned by the root tree and will be + // deleted when it is deleted. + ParseInfoTree* GetTreeForNested(const FieldDescriptor* field, + int index) const; + + private: + // Allow the text format parser to record information into the tree. + friend class TextFormat; + + // Records the starting location of a single value for a field. + void RecordLocation(const FieldDescriptor* field, ParseLocation location); + + // Create and records a nested tree for a nested message field. + ParseInfoTree* CreateNested(const FieldDescriptor* field); + + // Defines the map from the index-th field descriptor to its parse location. + typedef map > LocationMap; + + // Defines the map from the index-th field descriptor to the nested parse + // info tree. + typedef map > NestedMap; + + LocationMap locations_; + NestedMap nested_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParseInfoTree); + }; + + // For more control over parsing, use this class. + class LIBPROTOBUF_EXPORT Parser { + public: + Parser(); + ~Parser(); + + // Like TextFormat::Parse(). + bool Parse(io::ZeroCopyInputStream* input, Message* output); + // Like TextFormat::ParseFromString(). + bool ParseFromString(const string& input, Message* output); + // Like TextFormat::Merge(). + bool Merge(io::ZeroCopyInputStream* input, Message* output); + // Like TextFormat::MergeFromString(). + bool MergeFromString(const string& input, Message* output); + + // Set where to report parse errors. If NULL (the default), errors will + // be printed to stderr. + void RecordErrorsTo(io::ErrorCollector* error_collector) { + error_collector_ = error_collector; + } + + // Set how parser finds extensions. If NULL (the default), the + // parser will use the standard Reflection object associated with + // the message being parsed. + void SetFinder(Finder* finder) { + finder_ = finder; + } + + // Sets where location information about the parse will be written. If NULL + // (the default), then no location will be written. + void WriteLocationsTo(ParseInfoTree* tree) { + parse_info_tree_ = tree; + } + + // Normally parsing fails if, after parsing, output->IsInitialized() + // returns false. Call AllowPartialMessage(true) to skip this check. + void AllowPartialMessage(bool allow) { + allow_partial_ = allow; + } + + // Like TextFormat::ParseFieldValueFromString + bool ParseFieldValueFromString(const string& input, + const FieldDescriptor* field, + Message* output); + + + private: + // Forward declaration of an internal class used to parse text + // representations (see text_format.cc for implementation). + class ParserImpl; + + // Like TextFormat::Merge(). The provided implementation is used + // to do the parsing. + bool MergeUsingImpl(io::ZeroCopyInputStream* input, + Message* output, + ParserImpl* parser_impl); + + io::ErrorCollector* error_collector_; + Finder* finder_; + ParseInfoTree* parse_info_tree_; + bool allow_partial_; + bool allow_unknown_field_; + }; + + private: + // Hack: ParseInfoTree declares TextFormat as a friend which should extend + // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some + // old compilers (e.g. GCC 3.4.6) don't implement this correctly. We provide + // helpers for ParserImpl to call methods of ParseInfoTree. + static inline void RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocation location); + static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree, + const FieldDescriptor* field); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat); +}; + +inline void TextFormat::RecordLocation(ParseInfoTree* info_tree, + const FieldDescriptor* field, + ParseLocation location) { + info_tree->RecordLocation(field, location); +} + +inline TextFormat::ParseInfoTree* TextFormat::CreateNested( + ParseInfoTree* info_tree, const FieldDescriptor* field) { + return info_tree->CreateNested(field); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_TEXT_FORMAT_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format_unittest.cc new file mode 100644 index 000000000..304fb8440 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/text_format_unittest.cc @@ -0,0 +1,1248 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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: jschorr@google.com (Joseph Schorr) +// 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 + +namespace google { +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 " + "slashes \\ and multiple spaces"; + +// A representation of the above string with all the characters escaped. +const string kEscapeTestStringEscaped = + "\"\\\"A string with \\' characters \\n and \\r newlines " + "and \\t tabs and \\001 slashes \\\\ and multiple spaces\""; + +class TextFormatTest : public testing::Test { + public: + static void SetUpTestCase() { + File::ReadFileToStringOrDie( + TestSourceDir() + + "/google/protobuf/testdata/text_format_unittest_data.txt", + &static_proto_debug_string_); + } + + TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {} + + protected: + // Debug string read from text_format_unittest_data.txt. + const string proto_debug_string_; + unittest::TestAllTypes proto_; + + private: + static string static_proto_debug_string_; +}; +string TextFormatTest::static_proto_debug_string_; + +class TextFormatExtensionsTest : public testing::Test { + public: + static void SetUpTestCase() { + File::ReadFileToStringOrDie( + TestSourceDir() + + "/google/protobuf/testdata/" + "text_format_unittest_extensions_data.txt", + &static_proto_debug_string_); + } + + TextFormatExtensionsTest() + : proto_debug_string_(static_proto_debug_string_) {} + + protected: + // Debug string read from text_format_unittest_data.txt. + const string proto_debug_string_; + unittest::TestAllExtensions proto_; + + private: + static string static_proto_debug_string_; +}; +string TextFormatExtensionsTest::static_proto_debug_string_; + + +TEST_F(TextFormatTest, Basic) { + TestUtil::SetAllFields(&proto_); + EXPECT_EQ(proto_debug_string_, proto_.DebugString()); +} + +TEST_F(TextFormatExtensionsTest, Extensions) { + TestUtil::SetAllExtensions(&proto_); + EXPECT_EQ(proto_debug_string_, proto_.DebugString()); +} + +TEST_F(TextFormatTest, ShortDebugString) { + proto_.set_optional_int32(1); + proto_.set_optional_string("hello"); + proto_.mutable_optional_nested_message()->set_bb(2); + proto_.mutable_optional_foreign_message(); + + EXPECT_EQ("optional_int32: 1 optional_string: \"hello\" " + "optional_nested_message { bb: 2 } " + "optional_foreign_message { }", + proto_.ShortDebugString()); +} + +TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { + proto_.set_optional_int32(123); + proto_.add_repeated_int32(456); + proto_.add_repeated_int32(789); + proto_.add_repeated_string("foo"); + proto_.add_repeated_string("bar"); + proto_.add_repeated_nested_message()->set_bb(2); + proto_.add_repeated_nested_message()->set_bb(3); + proto_.add_repeated_nested_enum(unittest::TestAllTypes::FOO); + proto_.add_repeated_nested_enum(unittest::TestAllTypes::BAR); + + TextFormat::Printer printer; + printer.SetUseShortRepeatedPrimitives(true); + string text; + 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); + + // Try in single-line mode. + printer.SetSingleLineMode(true); + printer.PrintToString(proto_, &text); + + EXPECT_EQ("optional_int32: 123 " + "repeated_int32: [456, 789] " + "repeated_string: \"foo\" " + "repeated_string: \"bar\" " + "repeated_nested_message { bb: 2 } " + "repeated_nested_message { bb: 3 } " + "repeated_nested_enum: [FOO, BAR] ", + text); +} + + +TEST_F(TextFormatTest, StringEscape) { + // Set the string value to test. + proto_.set_optional_string(kEscapeTestString); + + // Get the DebugString from the proto. + string debug_string = proto_.DebugString(); + string utf8_debug_string = proto_.Utf8DebugString(); + + // Hardcode a correct value to test against. + string correct_string = "optional_string: " + + kEscapeTestStringEscaped + + "\n"; + + // Compare. + EXPECT_EQ(correct_string, debug_string); + // UTF-8 string is the same as non-UTF-8 because + // the protocol buffer contains no UTF-8 text. + EXPECT_EQ(correct_string, utf8_debug_string); + + string expected_short_debug_string = "optional_string: " + + kEscapeTestStringEscaped; + EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString()); +} + +TEST_F(TextFormatTest, Utf8DebugString) { + // Set the string value to test. + proto_.set_optional_string("\350\260\267\346\255\214"); + + // Get the DebugString from the proto. + string debug_string = proto_.DebugString(); + string utf8_debug_string = proto_.Utf8DebugString(); + + // Hardcode a correct value to test against. + string correct_utf8_string = "optional_string: " + "\"\350\260\267\346\255\214\"" + "\n"; + string correct_string = "optional_string: " + "\"\\350\\260\\267\\346\\255\\214\"" + "\n"; + + // Compare. + EXPECT_EQ(correct_utf8_string, utf8_debug_string); + EXPECT_EQ(correct_string, debug_string); +} + +TEST_F(TextFormatTest, PrintUnknownFields) { + // Test printing of unknown fields in a message. + + unittest::TestEmptyMessage message; + UnknownFieldSet* unknown_fields = message.mutable_unknown_fields(); + + unknown_fields->AddVarint(5, 1); + unknown_fields->AddFixed32(5, 2); + unknown_fields->AddFixed64(5, 3); + unknown_fields->AddLengthDelimited(5, "4"); + unknown_fields->AddGroup(5)->AddVarint(10, 5); + + unknown_fields->AddVarint(8, 1); + unknown_fields->AddVarint(8, 2); + unknown_fields->AddVarint(8, 3); + + EXPECT_EQ( + "5: 1\n" + "5: 0x00000002\n" + "5: 0x0000000000000003\n" + "5: \"4\"\n" + "5 {\n" + " 10: 5\n" + "}\n" + "8: 1\n" + "8: 2\n" + "8: 3\n", + message.DebugString()); +} + +TEST_F(TextFormatTest, PrintUnknownMessage) { + // Test heuristic printing of messages in an UnknownFieldSet. + + protobuf_unittest::TestAllTypes message; + + // Cases which should not be interpreted as sub-messages. + + // 'a' is a valid FIXED64 tag, so for the string to be parseable as a message + // it should be followed by 8 bytes. Since this string only has two + // subsequent bytes, it should be treated as a string. + message.add_repeated_string("abc"); + + // 'd' happens to be a valid ENDGROUP tag. So, + // UnknownFieldSet::MergeFromCodedStream() will successfully parse "def", but + // the ConsumedEntireMessage() check should fail. + message.add_repeated_string("def"); + + // A zero-length string should never be interpreted as a message even though + // it is technically valid as one. + message.add_repeated_string(""); + + // Case which should be interpreted as a sub-message. + + // An actual nested message with content should always be interpreted as a + // nested message. + message.add_repeated_nested_message()->set_bb(123); + + string data; + message.SerializeToString(&data); + + string text; + UnknownFieldSet unknown_fields; + EXPECT_TRUE(unknown_fields.ParseFromString(data)); + EXPECT_TRUE(TextFormat::PrintUnknownFieldsToString(unknown_fields, &text)); + EXPECT_EQ( + "44: \"abc\"\n" + "44: \"def\"\n" + "44: \"\"\n" + "48 {\n" + " 1: 123\n" + "}\n", + text); +} + +TEST_F(TextFormatTest, PrintMessageWithIndent) { + // Test adding an initial indent to printing. + + protobuf_unittest::TestAllTypes message; + + message.add_repeated_string("abc"); + message.add_repeated_string("def"); + message.add_repeated_nested_message()->set_bb(123); + + string text; + TextFormat::Printer printer; + printer.SetInitialIndentLevel(1); + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + " repeated_string: \"abc\"\n" + " repeated_string: \"def\"\n" + " repeated_nested_message {\n" + " bb: 123\n" + " }\n", + text); +} + +TEST_F(TextFormatTest, PrintMessageSingleLine) { + // Test printing a message on a single line. + + protobuf_unittest::TestAllTypes message; + + message.add_repeated_string("abc"); + message.add_repeated_string("def"); + message.add_repeated_nested_message()->set_bb(123); + + string text; + TextFormat::Printer printer; + printer.SetInitialIndentLevel(1); + printer.SetSingleLineMode(true); + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + " repeated_string: \"abc\" repeated_string: \"def\" " + "repeated_nested_message { bb: 123 } ", + text); +} + +TEST_F(TextFormatTest, PrintBufferTooSmall) { + // Test printing a message to a buffer that is too small. + + protobuf_unittest::TestAllTypes message; + + message.add_repeated_string("abc"); + message.add_repeated_string("def"); + + char buffer[1] = ""; + io::ArrayOutputStream output_stream(buffer, 1); + EXPECT_FALSE(TextFormat::Print(message, &output_stream)); + EXPECT_EQ(buffer[0], 'r'); + EXPECT_EQ(output_stream.ByteCount(), 1); +} + +TEST_F(TextFormatTest, ParseBasic) { + io::ArrayInputStream input_stream(proto_debug_string_.data(), + proto_debug_string_.size()); + TextFormat::Parse(&input_stream, &proto_); + TestUtil::ExpectAllFieldsSet(proto_); +} + +TEST_F(TextFormatExtensionsTest, ParseExtensions) { + io::ArrayInputStream input_stream(proto_debug_string_.data(), + proto_debug_string_.size()); + TextFormat::Parse(&input_stream, &proto_); + TestUtil::ExpectAllExtensionsSet(proto_); +} + +TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { + // Create a parse string with a numerical value for an enum field. + string parse_string = strings::Substitute("optional_nested_enum: $0", + unittest::TestAllTypes::BAZ); + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + EXPECT_TRUE(proto_.has_optional_nested_enum()); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum()); +} + +TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) { + ASSERT_LT(unittest::SPARSE_E, 0); + string parse_string = strings::Substitute("sparse_enum: $0", + unittest::SPARSE_E); + unittest::SparseEnumMessage proto; + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto)); + EXPECT_TRUE(proto.has_sparse_enum()); + EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum()); +} + +TEST_F(TextFormatTest, ParseStringEscape) { + // Create a parse string with escpaed characters in it. + string parse_string = "optional_string: " + + kEscapeTestStringEscaped + + "\n"; + + io::ArrayInputStream input_stream(parse_string.data(), + parse_string.size()); + TextFormat::Parse(&input_stream, &proto_); + + // Compare. + EXPECT_EQ(kEscapeTestString, proto_.optional_string()); +} + +TEST_F(TextFormatTest, ParseConcatenatedString) { + // Create a parse string with multiple parts on one line. + string parse_string = "optional_string: \"foo\" \"bar\"\n"; + + io::ArrayInputStream input_stream1(parse_string.data(), + parse_string.size()); + TextFormat::Parse(&input_stream1, &proto_); + + // Compare. + EXPECT_EQ("foobar", proto_.optional_string()); + + // Create a parse string with multiple parts on seperate lines. + parse_string = "optional_string: \"foo\"\n" + "\"bar\"\n"; + + io::ArrayInputStream input_stream2(parse_string.data(), + parse_string.size()); + TextFormat::Parse(&input_stream2, &proto_); + + // Compare. + EXPECT_EQ("foobar", proto_.optional_string()); +} + +TEST_F(TextFormatTest, ParseFloatWithSuffix) { + // Test that we can parse a floating-point value with 'f' appended to the + // end. This is needed for backwards-compatibility with proto1. + + // Have it parse a float with the 'f' suffix. + string parse_string = "optional_float: 1.0f\n"; + + io::ArrayInputStream input_stream(parse_string.data(), + parse_string.size()); + + TextFormat::Parse(&input_stream, &proto_); + + // Compare. + EXPECT_EQ(1.0, proto_.optional_float()); +} + +TEST_F(TextFormatTest, ParseShortRepeatedForm) { + string parse_string = + // 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"; + + 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)); +} + +TEST_F(TextFormatTest, Comments) { + // Test that comments are ignored. + + string parse_string = "optional_int32: 1 # a comment\n" + "optional_int64: 2 # another comment"; + + io::ArrayInputStream input_stream(parse_string.data(), + parse_string.size()); + + TextFormat::Parse(&input_stream, &proto_); + + // Compare. + EXPECT_EQ(1, proto_.optional_int32()); + EXPECT_EQ(2, proto_.optional_int64()); +} + +TEST_F(TextFormatTest, OptionalColon) { + // Test that we can place a ':' after the field name of a nested message, + // even though we don't have to. + + string parse_string = "optional_nested_message: { bb: 1}\n"; + + io::ArrayInputStream input_stream(parse_string.data(), + parse_string.size()); + + TextFormat::Parse(&input_stream, &proto_); + + // Compare. + EXPECT_TRUE(proto_.has_optional_nested_message()); + EXPECT_EQ(1, proto_.optional_nested_message().bb()); +} + +// Some platforms (e.g. Windows) insist on padding the exponent to three +// digits when one or two would be just fine. +static string RemoveRedundantZeros(string text) { + text = StringReplace(text, "e+0", "e+", true); + text = StringReplace(text, "e-0", "e-", true); + return text; +} + +TEST_F(TextFormatTest, PrintExotic) { + unittest::TestAllTypes message; + + // Note: In C, a negative integer literal is actually the unary negation + // operator being applied to a positive integer literal, and + // 9223372036854775808 is outside the range of int64. However, it is not + // outside the range of uint64. Confusingly, this means that everything + // works if we make the literal unsigned, even though we are negating it. + message.add_repeated_int64(-GOOGLE_ULONGLONG(9223372036854775808)); + message.add_repeated_uint64(GOOGLE_ULONGLONG(18446744073709551615)); + message.add_repeated_double(123.456); + message.add_repeated_double(1.23e21); + message.add_repeated_double(1.23e-18); + message.add_repeated_double(std::numeric_limits::infinity()); + message.add_repeated_double(-std::numeric_limits::infinity()); + message.add_repeated_double(std::numeric_limits::quiet_NaN()); + message.add_repeated_string(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12)); + + // Fun story: We used to use 1.23e22 instead of 1.23e21 above, but this + // seemed to trigger an odd case on MinGW/GCC 3.4.5 where GCC's parsing of + // the value differed from strtod()'s parsing. That is to say, the + // following assertion fails on MinGW: + // assert(1.23e22 == strtod("1.23e22", NULL)); + // As a result, SimpleDtoa() would print the value as + // "1.2300000000000001e+22" to make sure strtod() produce the exact same + // result. Our goal is to test runtime parsing, not compile-time parsing, + // so this wasn't our problem. It was found that using 1.23e21 did not + // have this problem, so we switched to that instead. + + EXPECT_EQ( + "repeated_int64: -9223372036854775808\n" + "repeated_uint64: 18446744073709551615\n" + "repeated_double: 123.456\n" + "repeated_double: 1.23e+21\n" + "repeated_double: 1.23e-18\n" + "repeated_double: inf\n" + "repeated_double: -inf\n" + "repeated_double: nan\n" + "repeated_string: \"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\'\\\"\"\n", + RemoveRedundantZeros(message.DebugString())); +} + +TEST_F(TextFormatTest, PrintFloatPrecision) { + unittest::TestAllTypes message; + + message.add_repeated_float(1.2); + message.add_repeated_float(1.23); + message.add_repeated_float(1.234); + message.add_repeated_float(1.2345); + message.add_repeated_float(1.23456); + message.add_repeated_float(1.2e10); + message.add_repeated_float(1.23e10); + message.add_repeated_float(1.234e10); + message.add_repeated_float(1.2345e10); + message.add_repeated_float(1.23456e10); + message.add_repeated_double(1.2); + message.add_repeated_double(1.23); + message.add_repeated_double(1.234); + message.add_repeated_double(1.2345); + message.add_repeated_double(1.23456); + message.add_repeated_double(1.234567); + message.add_repeated_double(1.2345678); + message.add_repeated_double(1.23456789); + message.add_repeated_double(1.234567898); + message.add_repeated_double(1.2345678987); + message.add_repeated_double(1.23456789876); + message.add_repeated_double(1.234567898765); + message.add_repeated_double(1.2345678987654); + message.add_repeated_double(1.23456789876543); + message.add_repeated_double(1.2e100); + message.add_repeated_double(1.23e100); + message.add_repeated_double(1.234e100); + message.add_repeated_double(1.2345e100); + message.add_repeated_double(1.23456e100); + message.add_repeated_double(1.234567e100); + message.add_repeated_double(1.2345678e100); + message.add_repeated_double(1.23456789e100); + message.add_repeated_double(1.234567898e100); + message.add_repeated_double(1.2345678987e100); + message.add_repeated_double(1.23456789876e100); + message.add_repeated_double(1.234567898765e100); + message.add_repeated_double(1.2345678987654e100); + message.add_repeated_double(1.23456789876543e100); + + EXPECT_EQ( + "repeated_float: 1.2\n" + "repeated_float: 1.23\n" + "repeated_float: 1.234\n" + "repeated_float: 1.2345\n" + "repeated_float: 1.23456\n" + "repeated_float: 1.2e+10\n" + "repeated_float: 1.23e+10\n" + "repeated_float: 1.234e+10\n" + "repeated_float: 1.2345e+10\n" + "repeated_float: 1.23456e+10\n" + "repeated_double: 1.2\n" + "repeated_double: 1.23\n" + "repeated_double: 1.234\n" + "repeated_double: 1.2345\n" + "repeated_double: 1.23456\n" + "repeated_double: 1.234567\n" + "repeated_double: 1.2345678\n" + "repeated_double: 1.23456789\n" + "repeated_double: 1.234567898\n" + "repeated_double: 1.2345678987\n" + "repeated_double: 1.23456789876\n" + "repeated_double: 1.234567898765\n" + "repeated_double: 1.2345678987654\n" + "repeated_double: 1.23456789876543\n" + "repeated_double: 1.2e+100\n" + "repeated_double: 1.23e+100\n" + "repeated_double: 1.234e+100\n" + "repeated_double: 1.2345e+100\n" + "repeated_double: 1.23456e+100\n" + "repeated_double: 1.234567e+100\n" + "repeated_double: 1.2345678e+100\n" + "repeated_double: 1.23456789e+100\n" + "repeated_double: 1.234567898e+100\n" + "repeated_double: 1.2345678987e+100\n" + "repeated_double: 1.23456789876e+100\n" + "repeated_double: 1.234567898765e+100\n" + "repeated_double: 1.2345678987654e+100\n" + "repeated_double: 1.23456789876543e+100\n", + RemoveRedundantZeros(message.DebugString())); +} + + +TEST_F(TextFormatTest, AllowPartial) { + unittest::TestRequired message; + TextFormat::Parser parser; + parser.AllowPartialMessage(true); + EXPECT_TRUE(parser.ParseFromString("a: 1", &message)); + EXPECT_EQ(1, message.a()); + EXPECT_FALSE(message.has_b()); + EXPECT_FALSE(message.has_c()); +} + +TEST_F(TextFormatTest, ParseExotic) { + unittest::TestAllTypes message; + ASSERT_TRUE(TextFormat::ParseFromString( + "repeated_int32: -1\n" + "repeated_int32: -2147483648\n" + "repeated_int64: -1\n" + "repeated_int64: -9223372036854775808\n" + "repeated_uint32: 4294967295\n" + "repeated_uint32: 2147483648\n" + "repeated_uint64: 18446744073709551615\n" + "repeated_uint64: 9223372036854775808\n" + "repeated_double: 123.0\n" + "repeated_double: 123.5\n" + "repeated_double: 0.125\n" + "repeated_double: 1.23E17\n" + "repeated_double: 1.235E+22\n" + "repeated_double: 1.235e-18\n" + "repeated_double: 123.456789\n" + "repeated_double: inf\n" + "repeated_double: Infinity\n" + "repeated_double: -inf\n" + "repeated_double: -Infinity\n" + "repeated_double: nan\n" + "repeated_double: NaN\n" + "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\"\n", + &message)); + + ASSERT_EQ(2, message.repeated_int32_size()); + EXPECT_EQ(-1, message.repeated_int32(0)); + // Note: In C, a negative integer literal is actually the unary negation + // operator being applied to a positive integer literal, and 2147483648 is + // outside the range of int32. However, it is not outside the range of + // uint32. Confusingly, this means that everything works if we make the + // literal unsigned, even though we are negating it. + EXPECT_EQ(-2147483648u, message.repeated_int32(1)); + + ASSERT_EQ(2, message.repeated_int64_size()); + EXPECT_EQ(-1, message.repeated_int64(0)); + // Note: In C, a negative integer literal is actually the unary negation + // operator being applied to a positive integer literal, and + // 9223372036854775808 is outside the range of int64. However, it is not + // outside the range of uint64. Confusingly, this means that everything + // works if we make the literal unsigned, even though we are negating it. + EXPECT_EQ(-GOOGLE_ULONGLONG(9223372036854775808), message.repeated_int64(1)); + + ASSERT_EQ(2, message.repeated_uint32_size()); + EXPECT_EQ(4294967295u, message.repeated_uint32(0)); + EXPECT_EQ(2147483648u, message.repeated_uint32(1)); + + ASSERT_EQ(2, message.repeated_uint64_size()); + EXPECT_EQ(GOOGLE_ULONGLONG(18446744073709551615), message.repeated_uint64(0)); + EXPECT_EQ(GOOGLE_ULONGLONG(9223372036854775808), message.repeated_uint64(1)); + + ASSERT_EQ(13, message.repeated_double_size()); + EXPECT_EQ(123.0 , message.repeated_double(0)); + EXPECT_EQ(123.5 , message.repeated_double(1)); + EXPECT_EQ(0.125 , message.repeated_double(2)); + EXPECT_EQ(1.23E17 , message.repeated_double(3)); + 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))); + + // Note: Since these string literals have \0's in them, we must explicitly + // pass their sizes to string's constructor. + ASSERT_EQ(1, message.repeated_string_size()); + EXPECT_EQ(string("\000\001\a\b\f\n\r\t\v\\\'\"", 12), + message.repeated_string(0)); +} + +class TextFormatParserTest : public testing::Test { + protected: + void ExpectFailure(const string& input, const string& message, int line, + int col) { + scoped_ptr proto(new unittest::TestAllTypes); + ExpectFailure(input, message, line, col, proto.get()); + } + + void ExpectFailure(const string& input, const string& message, int line, + int col, Message* proto) { + ExpectMessage(input, message, line, col, proto, false); + } + + void ExpectMessage(const string& input, const string& message, int line, + int col, Message* proto, bool expected_result) { + TextFormat::Parser parser; + MockErrorCollector error_collector; + parser.RecordErrorsTo(&error_collector); + EXPECT_EQ(parser.ParseFromString(input, proto), expected_result); + EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n", + error_collector.text_); + } + + void ExpectSuccessAndTree(const string& input, Message* proto, + TextFormat::ParseInfoTree* info_tree) { + TextFormat::Parser parser; + MockErrorCollector error_collector; + parser.RecordErrorsTo(&error_collector); + parser.WriteLocationsTo(info_tree); + + EXPECT_TRUE(parser.ParseFromString(input, proto)); + } + + void ExpectLocation(TextFormat::ParseInfoTree* tree, + const Descriptor* d, const string& field_name, + int index, int line, int column) { + TextFormat::ParseLocation location = tree->GetLocation( + d->FindFieldByName(field_name), index); + EXPECT_EQ(line, location.line); + EXPECT_EQ(column, location.column); + } + + // An error collector which simply concatenates all its errors into a big + // block of text which can be checked. + class MockErrorCollector : public io::ErrorCollector { + public: + MockErrorCollector() {} + ~MockErrorCollector() {} + + string text_; + + // implements ErrorCollector ------------------------------------- + void AddError(int line, int column, const string& message) { + strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", + line + 1, column + 1, message); + } + + void AddWarning(int line, int column, const string& message) { + AddError(line, column, "WARNING:" + message); + } + }; +}; + +TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { + scoped_ptr message(new unittest::TestAllTypes); + const Descriptor* d = message->GetDescriptor(); + + string stringData = + "optional_int32: 1\n" + "optional_int64: 2\n" + " optional_double: 2.4\n" + "repeated_int32: 5\n" + "repeated_int32: 10\n" + "optional_nested_message <\n" + " bb: 78\n" + ">\n" + "repeated_nested_message <\n" + " bb: 79\n" + ">\n" + "repeated_nested_message <\n" + " bb: 80\n" + ">"; + + + TextFormat::ParseInfoTree tree; + ExpectSuccessAndTree(stringData, message.get(), &tree); + + // Verify that the tree has the correct positions. + ExpectLocation(&tree, d, "optional_int32", -1, 0, 0); + ExpectLocation(&tree, d, "optional_int64", -1, 1, 0); + ExpectLocation(&tree, d, "optional_double", -1, 2, 2); + + ExpectLocation(&tree, d, "repeated_int32", 0, 3, 0); + ExpectLocation(&tree, d, "repeated_int32", 1, 4, 0); + + ExpectLocation(&tree, d, "optional_nested_message", -1, 5, 0); + ExpectLocation(&tree, d, "repeated_nested_message", 0, 8, 0); + ExpectLocation(&tree, d, "repeated_nested_message", 1, 11, 0); + + // Check for fields not set. For an invalid field, the location returned + // should be -1, -1. + ExpectLocation(&tree, d, "repeated_int64", 0, -1, -1); + ExpectLocation(&tree, d, "repeated_int32", 6, -1, -1); + ExpectLocation(&tree, d, "some_unknown_field", -1, -1, -1); + + // Verify inside the nested message. + const FieldDescriptor* nested_field = + d->FindFieldByName("optional_nested_message"); + + TextFormat::ParseInfoTree* nested_tree = + tree.GetTreeForNested(nested_field, -1); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 6, 2); + + // Verify inside another nested message. + nested_field = d->FindFieldByName("repeated_nested_message"); + nested_tree = tree.GetTreeForNested(nested_field, 0); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 9, 2); + + nested_tree = tree.GetTreeForNested(nested_field, 1); + ExpectLocation(nested_tree, nested_field->message_type(), "bb", -1, 12, 2); + + // Verify a NULL tree for an unknown nested field. + TextFormat::ParseInfoTree* unknown_nested_tree = + tree.GetTreeForNested(nested_field, 2); + + EXPECT_EQ(NULL, unknown_nested_tree); +} + +TEST_F(TextFormatParserTest, ParseFieldValueFromString) { + scoped_ptr message(new unittest::TestAllTypes); + const Descriptor* d = message->GetDescriptor(); + +#define EXPECT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_BOOL_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_TRUE(message->optional_##name() == value); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_FLOAT_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_FLOAT_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_DOUBLE_FIELD(name, value, valuestring) \ + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); \ + EXPECT_DOUBLE_EQ(value, message->optional_##name()); \ + EXPECT_TRUE(message->has_optional_##name()); + +#define EXPECT_INVALID(name, valuestring) \ + EXPECT_FALSE(TextFormat::ParseFieldValueFromString( \ + valuestring, d->FindFieldByName("optional_" #name), message.get())); + + // int32 + EXPECT_FIELD(int32, 1, "1"); + EXPECT_FIELD(int32, -1, "-1"); + EXPECT_FIELD(int32, 0x1234, "0x1234"); + EXPECT_INVALID(int32, "a"); + EXPECT_INVALID(int32, "999999999999999999999999999999999999"); + EXPECT_INVALID(int32, "1,2"); + + // int64 + EXPECT_FIELD(int64, 1, "1"); + EXPECT_FIELD(int64, -1, "-1"); + EXPECT_FIELD(int64, 0x1234567812345678LL, "0x1234567812345678"); + EXPECT_INVALID(int64, "a"); + EXPECT_INVALID(int64, "999999999999999999999999999999999999"); + EXPECT_INVALID(int64, "1,2"); + + // uint64 + EXPECT_FIELD(uint64, 1, "1"); + EXPECT_FIELD(uint64, 0xf234567812345678ULL, "0xf234567812345678"); + EXPECT_INVALID(uint64, "-1"); + EXPECT_INVALID(uint64, "a"); + EXPECT_INVALID(uint64, "999999999999999999999999999999999999"); + EXPECT_INVALID(uint64, "1,2"); + + // fixed32 + EXPECT_FIELD(fixed32, 1, "1"); + EXPECT_FIELD(fixed32, 0x12345678, "0x12345678"); + EXPECT_INVALID(fixed32, "-1"); + EXPECT_INVALID(fixed32, "a"); + EXPECT_INVALID(fixed32, "999999999999999999999999999999999999"); + EXPECT_INVALID(fixed32, "1,2"); + + // fixed64 + EXPECT_FIELD(fixed64, 1, "1"); + EXPECT_FIELD(fixed64, 0x1234567812345678ULL, "0x1234567812345678"); + EXPECT_INVALID(fixed64, "-1"); + EXPECT_INVALID(fixed64, "a"); + EXPECT_INVALID(fixed64, "999999999999999999999999999999999999"); + EXPECT_INVALID(fixed64, "1,2"); + + // bool + EXPECT_BOOL_FIELD(bool, true, "true"); + EXPECT_BOOL_FIELD(bool, false, "false"); + EXPECT_BOOL_FIELD(bool, true, "1"); + EXPECT_BOOL_FIELD(bool, true, "t"); + EXPECT_BOOL_FIELD(bool, false, "0"); + EXPECT_BOOL_FIELD(bool, false, "f"); + EXPECT_INVALID(bool, "2"); + EXPECT_INVALID(bool, "-0"); + EXPECT_INVALID(bool, "on"); + EXPECT_INVALID(bool, "a"); + EXPECT_INVALID(bool, "True"); + + // float + EXPECT_FIELD(float, 1, "1"); + EXPECT_FLOAT_FIELD(float, 1.5, "1.5"); + EXPECT_FLOAT_FIELD(float, 1.5e3, "1.5e3"); + EXPECT_FLOAT_FIELD(float, -4.55, "-4.55"); + EXPECT_INVALID(float, "a"); + EXPECT_INVALID(float, "1,2"); + + // double + EXPECT_FIELD(double, 1, "1"); + EXPECT_FIELD(double, -1, "-1"); + EXPECT_DOUBLE_FIELD(double, 2.3, "2.3"); + EXPECT_DOUBLE_FIELD(double, 3e5, "3e5"); + EXPECT_INVALID(double, "a"); + EXPECT_INVALID(double, "1,2"); + + // string + EXPECT_FIELD(string, "hello", "\"hello\""); + EXPECT_FIELD(string, "-1.87", "'-1.87'"); + EXPECT_INVALID(string, "hello"); // without quote for value + + // enum + EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR"); + EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ, + SimpleItoa(unittest::TestAllTypes::BAZ)); + EXPECT_INVALID(nested_enum, "FOOBAR"); + + // message + EXPECT_TRUE(TextFormat::ParseFieldValueFromString( + "", d->FindFieldByName("optional_nested_message"), message.get())); + EXPECT_EQ(12, message->optional_nested_message().bb()); \ + EXPECT_TRUE(message->has_optional_nested_message()); + EXPECT_INVALID(nested_message, "any"); + +#undef EXPECT_FIELD +#undef EXPECT_BOOL_FIELD +#undef EXPECT_FLOAT_FIELD +#undef EXPECT_DOUBLE_FIELD +#undef EXPECT_INVALID +} + + +TEST_F(TextFormatParserTest, InvalidToken) { + ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.", + 2, 1); + + ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20); + ExpectFailure("\"some string\"", "Expected identifier.", 1, 1); +} + +TEST_F(TextFormatParserTest, InvalidFieldName) { + ExpectFailure( + "invalid_field: somevalue\n", + "Message type \"protobuf_unittest.TestAllTypes\" has no field named " + "\"invalid_field\".", + 1, 14); +} + +TEST_F(TextFormatParserTest, InvalidCapitalization) { + // We require that group names be exactly as they appear in the .proto. + ExpectFailure( + "optionalgroup {\na: 15\n}\n", + "Message type \"protobuf_unittest.TestAllTypes\" has no field named " + "\"optionalgroup\".", + 1, 15); + ExpectFailure( + "OPTIONALgroup {\na: 15\n}\n", + "Message type \"protobuf_unittest.TestAllTypes\" has no field named " + "\"OPTIONALgroup\".", + 1, 15); + ExpectFailure( + "Optional_Double: 10.0\n", + "Message type \"protobuf_unittest.TestAllTypes\" has no field named " + "\"Optional_Double\".", + 1, 16); +} + +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 {\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 {\n \n}\n", "Expected \":\", found \"{\".", + 1, 16); + ExpectFailure("optional_int32: 0x80000000\n", + "Integer out of range.", 1, 17); + ExpectFailure("optional_int64: 0x8000000000000000\n", + "Integer out of range.", 1, 17); + ExpectFailure("optional_int32: -0x80000001\n", + "Integer out of range.", 1, 18); + ExpectFailure("optional_int64: -0x8000000000000001\n", + "Integer out of range.", 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 {\n \n}\n", "Expected \":\", found \"{\".", + 1, 17); + ExpectFailure("optional_uint32: 0x100000000\n", + "Integer out of range.", 1, 18); + ExpectFailure("optional_uint64: 0x10000000000000000\n", + "Integer out of range.", 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: meh\n", + "Invalid value for boolean field \"optional_bool\". Value: \"meh\".", + 2, 1); + + ExpectFailure("optional_bool {\n \n}\n", "Expected \":\", found \"{\".", + 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 {\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); + + // Valid token, but enum value is not defined. + ExpectFailure("optional_nested_enum: 5\n", + "Unknown enumeration value of \"5\" for field " + "\"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: !\n", + "Expected integer or identifier.", 1, 23); + + ExpectFailure( + "optional_nested_enum: grah\n", + "Unknown enumeration value of \"grah\" for field " + "\"optional_nested_enum\".", 2, 1); + + ExpectFailure( + "optional_nested_enum {\n \n}\n", + "Expected \":\", found \"{\".", 1, 22); +} + +TEST_F(TextFormatParserTest, MessageDelimeters) { + // Non-matching delimeters. + ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".", + 3, 1); + + // Invalid delimeters. + ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".", + 1, 15); + + // Unending message. + ExpectFailure("optional_nested_message {\n \nbb: 118\n", + "Expected identifier.", + 4, 1); +} + +TEST_F(TextFormatParserTest, UnknownExtension) { + // Non-matching delimeters. + ExpectFailure("[blahblah]: 123", + "Extension \"blahblah\" is not defined or is not an " + "extension of \"protobuf_unittest.TestAllTypes\".", + 1, 11); +} + +TEST_F(TextFormatParserTest, MissingRequired) { + unittest::TestRequired message; + ExpectFailure("a: 1", + "Message missing required fields: b, c", + 0, 1, &message); +} + +TEST_F(TextFormatParserTest, ParseDuplicateRequired) { + unittest::TestRequired message; + ExpectFailure("a: 1 b: 2 c: 3 a: 1", + "Non-repeated field \"a\" is specified multiple times.", + 1, 17, &message); +} + +TEST_F(TextFormatParserTest, ParseDuplicateOptional) { + unittest::ForeignMessage message; + ExpectFailure("c: 1 c: 2", + "Non-repeated field \"c\" is specified multiple times.", + 1, 7, &message); +} + +TEST_F(TextFormatParserTest, MergeDuplicateRequired) { + unittest::TestRequired message; + TextFormat::Parser parser; + EXPECT_TRUE(parser.MergeFromString("a: 1 b: 2 c: 3 a: 4", &message)); + EXPECT_EQ(4, message.a()); +} + +TEST_F(TextFormatParserTest, MergeDuplicateOptional) { + unittest::ForeignMessage message; + TextFormat::Parser parser; + EXPECT_TRUE(parser.MergeFromString("c: 1 c: 2", &message)); + EXPECT_EQ(2, message.c()); +} + +TEST_F(TextFormatParserTest, ExplicitDelimiters) { + unittest::TestRequired message; + EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message)); + EXPECT_EQ(1, message.a()); + EXPECT_EQ(2, message.b()); + EXPECT_EQ(3, message.c()); +} + +TEST_F(TextFormatParserTest, PrintErrorsToStderr) { + vector errors; + + { + ScopedMemoryLog log; + unittest::TestAllTypes proto; + EXPECT_FALSE(TextFormat::ParseFromString("no_such_field: 1", &proto)); + errors = log.GetMessages(ERROR); + } + + ASSERT_EQ(1, errors.size()); + EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: " + "1:14: Message type \"protobuf_unittest.TestAllTypes\" has no field " + "named \"no_such_field\".", + errors[0]); +} + +TEST_F(TextFormatParserTest, FailsOnTokenizationError) { + vector errors; + + { + ScopedMemoryLog log; + unittest::TestAllTypes proto; + EXPECT_FALSE(TextFormat::ParseFromString("\020", &proto)); + errors = log.GetMessages(ERROR); + } + + ASSERT_EQ(1, errors.size()); + EXPECT_EQ("Error parsing text-format protobuf_unittest.TestAllTypes: " + "1:1: Invalid control characters encountered in text.", + errors[0]); +} + +TEST_F(TextFormatParserTest, ParseDeprecatedField) { + unittest::TestDeprecatedFields message; + ExpectMessage("deprecated_int32: 42", + "WARNING:text format contains deprecated field " + "\"deprecated_int32\"", 1, 21, &message, true); +} + +class TextFormatMessageSetTest : public testing::Test { + protected: + static const char proto_debug_string_[]; +}; +const char TextFormatMessageSetTest::proto_debug_string_[] = +"message_set {\n" +" [protobuf_unittest.TestMessageSetExtension1] {\n" +" i: 23\n" +" }\n" +" [protobuf_unittest.TestMessageSetExtension2] {\n" +" str: \"foo\"\n" +" }\n" +"}\n"; + + +TEST_F(TextFormatMessageSetTest, Serialize) { + protobuf_unittest::TestMessageSetContainer proto; + protobuf_unittest::TestMessageSetExtension1* item_a = + proto.mutable_message_set()->MutableExtension( + protobuf_unittest::TestMessageSetExtension1::message_set_extension); + item_a->set_i(23); + protobuf_unittest::TestMessageSetExtension2* item_b = + proto.mutable_message_set()->MutableExtension( + protobuf_unittest::TestMessageSetExtension2::message_set_extension); + item_b->set_str("foo"); + EXPECT_EQ(proto_debug_string_, proto.DebugString()); +} + +TEST_F(TextFormatMessageSetTest, Deserialize) { + protobuf_unittest::TestMessageSetContainer proto; + ASSERT_TRUE(TextFormat::ParseFromString(proto_debug_string_, &proto)); + EXPECT_EQ(23, proto.message_set().GetExtension( + protobuf_unittest::TestMessageSetExtension1::message_set_extension).i()); + EXPECT_EQ("foo", proto.message_set().GetExtension( + protobuf_unittest::TestMessageSetExtension2::message_set_extension).str()); + + // Ensure that these are the only entries present. + vector descriptors; + proto.message_set().GetReflection()->ListFields( + proto.message_set(), &descriptors); + EXPECT_EQ(2, descriptors.size()); +} + + +} // namespace text_format_unittest +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.cc new file mode 100644 index 000000000..841433d5d --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.cc @@ -0,0 +1,266 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include + +namespace google { +namespace protobuf { + +UnknownFieldSet::UnknownFieldSet() + : fields_(NULL) {} + +UnknownFieldSet::~UnknownFieldSet() { + Clear(); + delete fields_; +} + +void UnknownFieldSet::ClearFallback() { + GOOGLE_DCHECK(fields_ != NULL); + for (int i = 0; i < fields_->size(); i++) { + (*fields_)[i].Delete(); + } + fields_->clear(); +} + +void UnknownFieldSet::ClearAndFreeMemory() { + if (fields_ != NULL) { + Clear(); + delete fields_; + fields_ = NULL; + } +} + +void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { + for (int i = 0; i < other.field_count(); i++) { + AddField(other.field(i)); + } +} + +int UnknownFieldSet::SpaceUsedExcludingSelf() const { + if (fields_ == NULL) return 0; + + int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size(); + for (int i = 0; i < fields_->size(); i++) { + const UnknownField& field = (*fields_)[i]; + switch (field.type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + total_size += sizeof(*field.length_delimited_.string_value_) + + internal::StringSpaceUsedExcludingSelf( + *field.length_delimited_.string_value_); + break; + case UnknownField::TYPE_GROUP: + total_size += field.group_->SpaceUsed(); + break; + default: + break; + } + } + return total_size; +} + +int UnknownFieldSet::SpaceUsed() const { + return sizeof(*this) + SpaceUsedExcludingSelf(); +} + +void UnknownFieldSet::AddVarint(int number, uint64 value) { + if (fields_ == NULL) fields_ = new vector; + UnknownField field; + field.number_ = number; + field.type_ = UnknownField::TYPE_VARINT; + field.varint_ = value; + fields_->push_back(field); +} + +void UnknownFieldSet::AddFixed32(int number, uint32 value) { + if (fields_ == NULL) fields_ = new vector; + UnknownField field; + field.number_ = number; + field.type_ = UnknownField::TYPE_FIXED32; + field.fixed32_ = value; + fields_->push_back(field); +} + +void UnknownFieldSet::AddFixed64(int number, uint64 value) { + if (fields_ == NULL) fields_ = new vector; + UnknownField field; + field.number_ = number; + field.type_ = UnknownField::TYPE_FIXED64; + field.fixed64_ = value; + fields_->push_back(field); +} + +string* UnknownFieldSet::AddLengthDelimited(int number) { + if (fields_ == NULL) fields_ = new vector; + UnknownField field; + field.number_ = number; + field.type_ = UnknownField::TYPE_LENGTH_DELIMITED; + field.length_delimited_.string_value_ = new string; + fields_->push_back(field); + return field.length_delimited_.string_value_; +} + + +UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { + if (fields_ == NULL) fields_ = new vector; + UnknownField field; + field.number_ = number; + field.type_ = UnknownField::TYPE_GROUP; + field.group_ = new UnknownFieldSet; + fields_->push_back(field); + return field.group_; +} + +void UnknownFieldSet::AddField(const UnknownField& field) { + if (fields_ == NULL) fields_ = new vector; + fields_->push_back(field); + fields_->back().DeepCopy(); +} + +void UnknownFieldSet::DeleteSubrange(int start, int num) { + GOOGLE_DCHECK(fields_ != NULL); + // Delete the specified fields. + for (int i = 0; i < num; ++i) { + (*fields_)[i + start].Delete(); + } + // Slide down the remaining fields. + for (int i = start + num; i < fields_->size(); ++i) { + (*fields_)[i - num] = (*fields_)[i]; + } + // Pop off the # of deleted fields. + for (int i = 0; i < num; ++i) { + fields_->pop_back(); + } +} + +void UnknownFieldSet::DeleteByNumber(int number) { + if (fields_ == NULL) return; + int left = 0; // The number of fields left after deletion. + for (int i = 0; i < fields_->size(); ++i) { + UnknownField* field = &(*fields_)[i]; + if (field->number() == number) { + field->Delete(); + } else { + if (i != left) { + (*fields_)[left] = (*fields_)[i]; + } + ++left; + } + } + fields_->resize(left); +} + +bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { + + UnknownFieldSet other; + if (internal::WireFormat::SkipMessage(input, &other) && + input->ConsumedEntireMessage()) { + MergeFrom(other); + return true; + } else { + return false; + } +} + +bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { + Clear(); + return MergeFromCodedStream(input); +} + +bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { + io::CodedInputStream coded_input(input); + return ParseFromCodedStream(&coded_input) && + coded_input.ConsumedEntireMessage(); +} + +bool UnknownFieldSet::ParseFromArray(const void* data, int size) { + io::ArrayInputStream input(data, size); + return ParseFromZeroCopyStream(&input); +} + +void UnknownField::Delete() { + switch (type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + delete length_delimited_.string_value_; + break; + case UnknownField::TYPE_GROUP: + delete group_; + break; + default: + break; + } +} + +void UnknownField::DeepCopy() { + switch (type()) { + case UnknownField::TYPE_LENGTH_DELIMITED: + length_delimited_.string_value_ = new string( + *length_delimited_.string_value_); + break; + case UnknownField::TYPE_GROUP: { + UnknownFieldSet* group = new UnknownFieldSet; + group->MergeFrom(*group_); + group_ = group; + break; + } + default: + break; + } +} + + +void UnknownField::SerializeLengthDelimitedNoTag( + io::CodedOutputStream* output) const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + const string& data = *length_delimited_.string_value_; + output->WriteVarint32(data.size()); + output->WriteString(data); +} + +uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + const string& data = *length_delimited_.string_value_; + target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); + target = io::CodedOutputStream::WriteStringToArray(data, target); + return target; +} + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.h new file mode 100644 index 000000000..825bba83a --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set.h @@ -0,0 +1,311 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. +// +// Contains classes used to keep track of unrecognized fields seen while +// parsing a protocol message. + +#ifndef GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ +#define GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ + +#include +#include +#include +#include +// TODO(jasonh): some people seem to rely on protobufs to include this for them! + +namespace google { +namespace protobuf { + namespace io { + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h + class ZeroCopyInputStream; // zero_copy_stream.h + } + namespace internal { + class WireFormat; // wire_format.h + class UnknownFieldSetFieldSkipperUsingCord; + // extension_set_heavy.cc + } + +class Message; // message.h +class UnknownField; // below + +// An UnknownFieldSet contains fields that were encountered while parsing a +// message but were not defined by its type. Keeping track of these can be +// useful, especially in that they may be written if the message is serialized +// again without being cleared in between. This means that software which +// simply receives messages and forwards them to other servers does not need +// to be updated every time a new field is added to the message definition. +// +// To get the UnknownFieldSet attached to any message, call +// Reflection::GetUnknownFields(). +// +// This class is necessarily tied to the protocol buffer wire format, unlike +// the Reflection interface which is independent of any serialization scheme. +class LIBPROTOBUF_EXPORT UnknownFieldSet { + public: + UnknownFieldSet(); + ~UnknownFieldSet(); + + // Remove all fields. + inline void Clear(); + + // Remove all fields and deallocate internal data objects + void ClearAndFreeMemory(); + + // Is this set empty? + inline bool empty() const; + + // Merge the contents of some other UnknownFieldSet with this one. + void MergeFrom(const UnknownFieldSet& other); + + // Swaps the contents of some other UnknownFieldSet with this one. + inline void Swap(UnknownFieldSet* x); + + // Computes (an estimate of) the total number of bytes currently used for + // storing the unknown fields in memory. Does NOT include + // sizeof(*this) in the calculation. + int SpaceUsedExcludingSelf() const; + + // Version of SpaceUsed() including sizeof(*this). + int SpaceUsed() const; + + // Returns the number of fields present in the UnknownFieldSet. + inline int field_count() const; + // Get a field in the set, where 0 <= index < field_count(). The fields + // appear in the order in which they were added. + inline const UnknownField& field(int index) const; + // Get a mutable pointer to a field in the set, where + // 0 <= index < field_count(). The fields appear in the order in which + // they were added. + inline UnknownField* mutable_field(int index); + + // Adding fields --------------------------------------------------- + + void AddVarint(int number, uint64 value); + void AddFixed32(int number, uint32 value); + void AddFixed64(int number, uint64 value); + void AddLengthDelimited(int number, const string& value); + string* AddLengthDelimited(int number); + UnknownFieldSet* AddGroup(int number); + + // Adds an unknown field from another set. + void AddField(const UnknownField& field); + + // Delete fields with indices in the range [start .. start+num-1]. + // Caution: implementation moves all fields with indices [start+num .. ]. + void DeleteSubrange(int start, int num); + + // Delete all fields with a specific field number. The order of left fields + // is preserved. + // Caution: implementation moves all fields after the first deleted field. + void DeleteByNumber(int number); + + // Parsing helpers ------------------------------------------------- + // These work exactly like the similarly-named methods of Message. + + bool MergeFromCodedStream(io::CodedInputStream* input); + bool ParseFromCodedStream(io::CodedInputStream* input); + bool ParseFromZeroCopyStream(io::ZeroCopyInputStream* input); + bool ParseFromArray(const void* data, int size); + inline bool ParseFromString(const string& data) { + return ParseFromArray(data.data(), data.size()); + } + + private: + + void ClearFallback(); + + vector* fields_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet); +}; + +// Represents one field in an UnknownFieldSet. +class LIBPROTOBUF_EXPORT UnknownField { + public: + enum Type { + TYPE_VARINT, + TYPE_FIXED32, + TYPE_FIXED64, + TYPE_LENGTH_DELIMITED, + TYPE_GROUP + }; + + // The field's tag number, as seen on the wire. + inline int number() const; + + // The field type. + inline Type type() const; + + // Accessors ------------------------------------------------------- + // Each method works only for UnknownFields of the corresponding type. + + inline uint64 varint() const; + inline uint32 fixed32() const; + inline uint64 fixed64() const; + inline const string& length_delimited() const; + inline const UnknownFieldSet& group() const; + + inline void set_varint(uint64 value); + inline void set_fixed32(uint32 value); + inline void set_fixed64(uint64 value); + inline void set_length_delimited(const string& value); + inline string* mutable_length_delimited(); + inline UnknownFieldSet* mutable_group(); + + // Serialization API. + // These methods can take advantage of the underlying implementation and may + // archieve a better performance than using getters to retrieve the data and + // do the serialization yourself. + void SerializeLengthDelimitedNoTag(io::CodedOutputStream* output) const; + uint8* SerializeLengthDelimitedNoTagToArray(uint8* target) const; + + inline int GetLengthDelimitedSize() const; + + private: + friend class UnknownFieldSet; + + // If this UnknownField contains a pointer, delete it. + void Delete(); + + // Make a deep copy of any pointers in this UnknownField. + void DeepCopy(); + + + unsigned int number_ : 29; + unsigned int type_ : 3; + union { + uint64 varint_; + uint32 fixed32_; + uint64 fixed64_; + mutable union { + string* string_value_; + } length_delimited_; + UnknownFieldSet* group_; + }; +}; + +// =================================================================== +// inline implementations + +inline void UnknownFieldSet::Clear() { + if (fields_ != NULL) { + ClearFallback(); + } +} + +inline bool UnknownFieldSet::empty() const { + return fields_ == NULL || fields_->empty(); +} + +inline void UnknownFieldSet::Swap(UnknownFieldSet* x) { + std::swap(fields_, x->fields_); +} + +inline int UnknownFieldSet::field_count() const { + return (fields_ == NULL) ? 0 : fields_->size(); +} +inline const UnknownField& UnknownFieldSet::field(int index) const { + return (*fields_)[index]; +} +inline UnknownField* UnknownFieldSet::mutable_field(int index) { + return &(*fields_)[index]; +} + +inline void UnknownFieldSet::AddLengthDelimited( + int number, const string& value) { + AddLengthDelimited(number)->assign(value); +} + + +inline int UnknownField::number() const { return number_; } +inline UnknownField::Type UnknownField::type() const { + return static_cast(type_); +} + +inline uint64 UnknownField::varint () const { + assert(type_ == TYPE_VARINT); + return varint_; +} +inline uint32 UnknownField::fixed32() const { + assert(type_ == TYPE_FIXED32); + return fixed32_; +} +inline uint64 UnknownField::fixed64() const { + assert(type_ == TYPE_FIXED64); + return fixed64_; +} +inline const string& UnknownField::length_delimited() const { + assert(type_ == TYPE_LENGTH_DELIMITED); + return *length_delimited_.string_value_; +} +inline const UnknownFieldSet& UnknownField::group() const { + assert(type_ == TYPE_GROUP); + return *group_; +} + +inline void UnknownField::set_varint(uint64 value) { + assert(type_ == TYPE_VARINT); + varint_ = value; +} +inline void UnknownField::set_fixed32(uint32 value) { + assert(type_ == TYPE_FIXED32); + fixed32_ = value; +} +inline void UnknownField::set_fixed64(uint64 value) { + assert(type_ == TYPE_FIXED64); + fixed64_ = value; +} +inline void UnknownField::set_length_delimited(const string& value) { + assert(type_ == TYPE_LENGTH_DELIMITED); + length_delimited_.string_value_->assign(value); +} +inline string* UnknownField::mutable_length_delimited() { + assert(type_ == TYPE_LENGTH_DELIMITED); + return length_delimited_.string_value_; +} +inline UnknownFieldSet* UnknownField::mutable_group() { + assert(type_ == TYPE_GROUP); + return group_; +} + +inline int UnknownField::GetLengthDelimitedSize() const { + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + return length_delimited_.string_value_->size(); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set_unittest.cc new file mode 100644 index 000000000..c6b8769f3 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/unknown_field_set_unittest.cc @@ -0,0 +1,594 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 test is testing a lot more than just the UnknownFieldSet class. It +// tests handling of unknown fields throughout the system. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using internal::WireFormat; + +class UnknownFieldSetTest : public testing::Test { + protected: + virtual void SetUp() { + descriptor_ = unittest::TestAllTypes::descriptor(); + TestUtil::SetAllFields(&all_fields_); + all_fields_.SerializeToString(&all_fields_data_); + ASSERT_TRUE(empty_message_.ParseFromString(all_fields_data_)); + unknown_fields_ = empty_message_.mutable_unknown_fields(); + } + + const UnknownField* GetField(const string& name) { + const FieldDescriptor* field = descriptor_->FindFieldByName(name); + if (field == NULL) return NULL; + for (int i = 0; i < unknown_fields_->field_count(); i++) { + if (unknown_fields_->field(i).number() == field->number()) { + return &unknown_fields_->field(i); + } + } + return NULL; + } + + // Constructs a protocol buffer which contains fields with all the same + // numbers as all_fields_data_ except that each field is some other wire + // type. + string GetBizarroData() { + unittest::TestEmptyMessage bizarro_message; + UnknownFieldSet* bizarro_unknown_fields = + bizarro_message.mutable_unknown_fields(); + for (int i = 0; i < unknown_fields_->field_count(); i++) { + const UnknownField& unknown_field = unknown_fields_->field(i); + if (unknown_field.type() == UnknownField::TYPE_VARINT) { + bizarro_unknown_fields->AddFixed32(unknown_field.number(), 1); + } else { + bizarro_unknown_fields->AddVarint(unknown_field.number(), 1); + } + } + + string data; + EXPECT_TRUE(bizarro_message.SerializeToString(&data)); + return data; + } + + const Descriptor* descriptor_; + unittest::TestAllTypes all_fields_; + string all_fields_data_; + + // An empty message that has been parsed from all_fields_data_. So, it has + // unknown fields of every type. + unittest::TestEmptyMessage empty_message_; + UnknownFieldSet* unknown_fields_; +}; + +namespace { + +TEST_F(UnknownFieldSetTest, AllFieldsPresent) { + // All fields of TestAllTypes should be present, in numeric order (because + // that's the order we parsed them in). Fields that are not valid field + // numbers of TestAllTypes should NOT be present. + + int pos = 0; + + for (int i = 0; i < 1000; i++) { + const FieldDescriptor* field = descriptor_->FindFieldByNumber(i); + if (field != NULL) { + ASSERT_LT(pos, unknown_fields_->field_count()); + EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + if (field->is_repeated()) { + // Should have a second instance. + ASSERT_LT(pos, unknown_fields_->field_count()); + EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + } + } + } + EXPECT_EQ(unknown_fields_->field_count(), pos); +} + +TEST_F(UnknownFieldSetTest, Varint) { + const UnknownField* field = GetField("optional_int32"); + ASSERT_TRUE(field != NULL); + + ASSERT_EQ(UnknownField::TYPE_VARINT, field->type()); + EXPECT_EQ(all_fields_.optional_int32(), field->varint()); +} + +TEST_F(UnknownFieldSetTest, Fixed32) { + const UnknownField* field = GetField("optional_fixed32"); + ASSERT_TRUE(field != NULL); + + ASSERT_EQ(UnknownField::TYPE_FIXED32, field->type()); + EXPECT_EQ(all_fields_.optional_fixed32(), field->fixed32()); +} + +TEST_F(UnknownFieldSetTest, Fixed64) { + const UnknownField* field = GetField("optional_fixed64"); + ASSERT_TRUE(field != NULL); + + ASSERT_EQ(UnknownField::TYPE_FIXED64, field->type()); + EXPECT_EQ(all_fields_.optional_fixed64(), field->fixed64()); +} + +TEST_F(UnknownFieldSetTest, LengthDelimited) { + const UnknownField* field = GetField("optional_string"); + ASSERT_TRUE(field != NULL); + + ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED, field->type()); + EXPECT_EQ(all_fields_.optional_string(), field->length_delimited()); +} + +TEST_F(UnknownFieldSetTest, Group) { + const UnknownField* field = GetField("optionalgroup"); + ASSERT_TRUE(field != NULL); + + ASSERT_EQ(UnknownField::TYPE_GROUP, field->type()); + ASSERT_EQ(1, field->group().field_count()); + + const UnknownField& nested_field = field->group().field(0); + const FieldDescriptor* nested_field_descriptor = + unittest::TestAllTypes::OptionalGroup::descriptor()->FindFieldByName("a"); + ASSERT_TRUE(nested_field_descriptor != NULL); + + EXPECT_EQ(nested_field_descriptor->number(), nested_field.number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, nested_field.type()); + EXPECT_EQ(all_fields_.optionalgroup().a(), nested_field.varint()); +} + +TEST_F(UnknownFieldSetTest, SerializeFastAndSlowAreEquivalent) { + int size = WireFormat::ComputeUnknownFieldsSize( + empty_message_.unknown_fields()); + string slow_buffer; + string fast_buffer; + slow_buffer.resize(size); + fast_buffer.resize(size); + + uint8* target = reinterpret_cast(string_as_array(&fast_buffer)); + uint8* result = WireFormat::SerializeUnknownFieldsToArray( + empty_message_.unknown_fields(), target); + EXPECT_EQ(size, result - target); + + { + io::ArrayOutputStream raw_stream(string_as_array(&slow_buffer), size, 1); + io::CodedOutputStream output_stream(&raw_stream); + WireFormat::SerializeUnknownFields(empty_message_.unknown_fields(), + &output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + EXPECT_TRUE(fast_buffer == slow_buffer); +} + +TEST_F(UnknownFieldSetTest, Serialize) { + // Check that serializing the UnknownFieldSet produces the original data + // again. + + string data; + empty_message_.SerializeToString(&data); + + // Don't use EXPECT_EQ because we don't want to dump raw binary data to + // stdout. + EXPECT_TRUE(data == all_fields_data_); +} + +TEST_F(UnknownFieldSetTest, ParseViaReflection) { + // Make sure fields are properly parsed to the UnknownFieldSet when parsing + // via reflection. + + unittest::TestEmptyMessage message; + io::ArrayInputStream raw_input(all_fields_data_.data(), + all_fields_data_.size()); + io::CodedInputStream input(&raw_input); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message)); + + EXPECT_EQ(message.DebugString(), empty_message_.DebugString()); +} + +TEST_F(UnknownFieldSetTest, SerializeViaReflection) { + // Make sure fields are properly written from the UnknownFieldSet when + // serializing via reflection. + + string data; + + { + io::StringOutputStream raw_output(&data); + io::CodedOutputStream output(&raw_output); + int size = WireFormat::ByteSize(empty_message_); + WireFormat::SerializeWithCachedSizes(empty_message_, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Don't use EXPECT_EQ because we don't want to dump raw binary data to + // stdout. + EXPECT_TRUE(data == all_fields_data_); +} + +TEST_F(UnknownFieldSetTest, CopyFrom) { + unittest::TestEmptyMessage message; + + message.CopyFrom(empty_message_); + + EXPECT_EQ(empty_message_.DebugString(), message.DebugString()); +} + +TEST_F(UnknownFieldSetTest, Swap) { + unittest::TestEmptyMessage other_message; + ASSERT_TRUE(other_message.ParseFromString(GetBizarroData())); + + EXPECT_GT(empty_message_.unknown_fields().field_count(), 0); + EXPECT_GT(other_message.unknown_fields().field_count(), 0); + const string debug_string = empty_message_.DebugString(); + const string other_debug_string = other_message.DebugString(); + EXPECT_NE(debug_string, other_debug_string); + + empty_message_.Swap(&other_message); + EXPECT_EQ(debug_string, other_message.DebugString()); + EXPECT_EQ(other_debug_string, empty_message_.DebugString()); +} + +TEST_F(UnknownFieldSetTest, SwapWithSelf) { + const string debug_string = empty_message_.DebugString(); + EXPECT_GT(empty_message_.unknown_fields().field_count(), 0); + + empty_message_.Swap(&empty_message_); + EXPECT_GT(empty_message_.unknown_fields().field_count(), 0); + EXPECT_EQ(debug_string, empty_message_.DebugString()); +} + +TEST_F(UnknownFieldSetTest, MergeFrom) { + unittest::TestEmptyMessage source, destination; + + destination.mutable_unknown_fields()->AddVarint(1, 1); + destination.mutable_unknown_fields()->AddVarint(3, 2); + source.mutable_unknown_fields()->AddVarint(2, 3); + source.mutable_unknown_fields()->AddVarint(3, 4); + + destination.MergeFrom(source); + + EXPECT_EQ( + // Note: The ordering of fields here depends on the ordering of adds + // and merging, above. + "1: 1\n" + "3: 2\n" + "2: 3\n" + "3: 4\n", + destination.DebugString()); +} + + +TEST_F(UnknownFieldSetTest, Clear) { + // Clear the set. + empty_message_.Clear(); + EXPECT_EQ(0, unknown_fields_->field_count()); +} + +TEST_F(UnknownFieldSetTest, ClearAndFreeMemory) { + EXPECT_GT(unknown_fields_->field_count(), 0); + unknown_fields_->ClearAndFreeMemory(); + EXPECT_EQ(0, unknown_fields_->field_count()); + unknown_fields_->AddVarint(123456, 654321); + EXPECT_EQ(1, unknown_fields_->field_count()); +} + +TEST_F(UnknownFieldSetTest, ParseKnownAndUnknown) { + // Test mixing known and unknown fields when parsing. + + unittest::TestEmptyMessage source; + source.mutable_unknown_fields()->AddVarint(123456, 654321); + string data; + ASSERT_TRUE(source.SerializeToString(&data)); + + unittest::TestAllTypes destination; + ASSERT_TRUE(destination.ParseFromString(all_fields_data_ + data)); + + TestUtil::ExpectAllFieldsSet(destination); + ASSERT_EQ(1, destination.unknown_fields().field_count()); + ASSERT_EQ(UnknownField::TYPE_VARINT, + destination.unknown_fields().field(0).type()); + EXPECT_EQ(654321, destination.unknown_fields().field(0).varint()); +} + +TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknown) { + // Test that fields of the wrong wire type are treated like unknown fields + // when parsing. + + unittest::TestAllTypes all_types_message; + unittest::TestEmptyMessage empty_message; + string bizarro_data = GetBizarroData(); + ASSERT_TRUE(all_types_message.ParseFromString(bizarro_data)); + ASSERT_TRUE(empty_message.ParseFromString(bizarro_data)); + + // All fields should have been interpreted as unknown, so the debug strings + // should be the same. + EXPECT_EQ(empty_message.DebugString(), all_types_message.DebugString()); +} + +TEST_F(UnknownFieldSetTest, WrongTypeTreatedAsUnknownViaReflection) { + // Same as WrongTypeTreatedAsUnknown but via the reflection interface. + + unittest::TestAllTypes all_types_message; + unittest::TestEmptyMessage empty_message; + string bizarro_data = GetBizarroData(); + io::ArrayInputStream raw_input(bizarro_data.data(), bizarro_data.size()); + io::CodedInputStream input(&raw_input); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &all_types_message)); + ASSERT_TRUE(empty_message.ParseFromString(bizarro_data)); + + EXPECT_EQ(empty_message.DebugString(), all_types_message.DebugString()); +} + +TEST_F(UnknownFieldSetTest, UnknownExtensions) { + // Make sure fields are properly parsed to the UnknownFieldSet even when + // they are declared as extension numbers. + + unittest::TestEmptyMessageWithExtensions message; + ASSERT_TRUE(message.ParseFromString(all_fields_data_)); + + EXPECT_EQ(message.DebugString(), empty_message_.DebugString()); +} + +TEST_F(UnknownFieldSetTest, UnknownExtensionsReflection) { + // Same as UnknownExtensions except parsing via reflection. + + unittest::TestEmptyMessageWithExtensions message; + io::ArrayInputStream raw_input(all_fields_data_.data(), + all_fields_data_.size()); + io::CodedInputStream input(&raw_input); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &message)); + + EXPECT_EQ(message.DebugString(), empty_message_.DebugString()); +} + +TEST_F(UnknownFieldSetTest, WrongExtensionTypeTreatedAsUnknown) { + // Test that fields of the wrong wire type are treated like unknown fields + // when parsing extensions. + + unittest::TestAllExtensions all_extensions_message; + unittest::TestEmptyMessage empty_message; + string bizarro_data = GetBizarroData(); + ASSERT_TRUE(all_extensions_message.ParseFromString(bizarro_data)); + ASSERT_TRUE(empty_message.ParseFromString(bizarro_data)); + + // All fields should have been interpreted as unknown, so the debug strings + // should be the same. + EXPECT_EQ(empty_message.DebugString(), all_extensions_message.DebugString()); +} + +TEST_F(UnknownFieldSetTest, UnknownEnumValue) { + using unittest::TestAllTypes; + using unittest::TestAllExtensions; + using unittest::TestEmptyMessage; + + const FieldDescriptor* singular_field = + TestAllTypes::descriptor()->FindFieldByName("optional_nested_enum"); + const FieldDescriptor* repeated_field = + TestAllTypes::descriptor()->FindFieldByName("repeated_nested_enum"); + ASSERT_TRUE(singular_field != NULL); + ASSERT_TRUE(repeated_field != NULL); + + string data; + + { + TestEmptyMessage empty_message; + UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields(); + unknown_fields->AddVarint(singular_field->number(), TestAllTypes::BAR); + unknown_fields->AddVarint(singular_field->number(), 5); // not valid + unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::FOO); + unknown_fields->AddVarint(repeated_field->number(), 4); // not valid + unknown_fields->AddVarint(repeated_field->number(), TestAllTypes::BAZ); + unknown_fields->AddVarint(repeated_field->number(), 6); // not valid + empty_message.SerializeToString(&data); + } + + { + TestAllTypes message; + ASSERT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(TestAllTypes::BAR, message.optional_nested_enum()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + EXPECT_EQ(TestAllTypes::FOO, message.repeated_nested_enum(0)); + EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(1)); + + const UnknownFieldSet& unknown_fields = message.unknown_fields(); + ASSERT_EQ(3, unknown_fields.field_count()); + + EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type()); + EXPECT_EQ(5, unknown_fields.field(0).varint()); + + EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type()); + EXPECT_EQ(4, unknown_fields.field(1).varint()); + + EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type()); + EXPECT_EQ(6, unknown_fields.field(2).varint()); + } + + { + using unittest::optional_nested_enum_extension; + using unittest::repeated_nested_enum_extension; + + TestAllExtensions message; + ASSERT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(TestAllTypes::BAR, + message.GetExtension(optional_nested_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(repeated_nested_enum_extension)); + EXPECT_EQ(TestAllTypes::FOO, + message.GetExtension(repeated_nested_enum_extension, 0)); + EXPECT_EQ(TestAllTypes::BAZ, + message.GetExtension(repeated_nested_enum_extension, 1)); + + const UnknownFieldSet& unknown_fields = message.unknown_fields(); + ASSERT_EQ(3, unknown_fields.field_count()); + + EXPECT_EQ(singular_field->number(), unknown_fields.field(0).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(0).type()); + EXPECT_EQ(5, unknown_fields.field(0).varint()); + + EXPECT_EQ(repeated_field->number(), unknown_fields.field(1).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(1).type()); + EXPECT_EQ(4, unknown_fields.field(1).varint()); + + EXPECT_EQ(repeated_field->number(), unknown_fields.field(2).number()); + ASSERT_EQ(UnknownField::TYPE_VARINT, unknown_fields.field(2).type()); + EXPECT_EQ(6, unknown_fields.field(2).varint()); + } +} + +TEST_F(UnknownFieldSetTest, SpaceUsed) { + unittest::TestEmptyMessage empty_message; + + // Make sure an unknown field set has zero space used until a field is + // actually added. + int base_size = empty_message.SpaceUsed(); + UnknownFieldSet* unknown_fields = empty_message.mutable_unknown_fields(); + EXPECT_EQ(base_size, empty_message.SpaceUsed()); + + // Make sure each thing we add to the set increases the SpaceUsed(). + unknown_fields->AddVarint(1, 0); + EXPECT_LT(base_size, empty_message.SpaceUsed()); + base_size = empty_message.SpaceUsed(); + + string* str = unknown_fields->AddLengthDelimited(1); + EXPECT_LT(base_size, empty_message.SpaceUsed()); + base_size = empty_message.SpaceUsed(); + + str->assign(sizeof(string) + 1, 'x'); + EXPECT_LT(base_size, empty_message.SpaceUsed()); + base_size = empty_message.SpaceUsed(); + + UnknownFieldSet* group = unknown_fields->AddGroup(1); + EXPECT_LT(base_size, empty_message.SpaceUsed()); + base_size = empty_message.SpaceUsed(); + + group->AddVarint(1, 0); + EXPECT_LT(base_size, empty_message.SpaceUsed()); +} + + +TEST_F(UnknownFieldSetTest, Empty) { + UnknownFieldSet unknown_fields; + EXPECT_TRUE(unknown_fields.empty()); + unknown_fields.AddVarint(6, 123); + EXPECT_FALSE(unknown_fields.empty()); + unknown_fields.Clear(); + EXPECT_TRUE(unknown_fields.empty()); +} + +TEST_F(UnknownFieldSetTest, DeleteSubrange) { + // Exhaustively test the deletion of every possible subrange in arrays of all + // sizes from 0 through 9. + for (int size = 0; size < 10; ++size) { + for (int num = 0; num <= size; ++num) { + for (int start = 0; start < size - num; ++start) { + // Create a set with "size" fields. + UnknownFieldSet unknown; + for (int i = 0; i < size; ++i) { + unknown.AddFixed32(i, i); + } + // Delete the specified subrange. + unknown.DeleteSubrange(start, num); + // Make sure the resulting field values are still correct. + EXPECT_EQ(size - num, unknown.field_count()); + for (int i = 0; i < unknown.field_count(); ++i) { + if (i < start) { + EXPECT_EQ(i, unknown.field(i).fixed32()); + } else { + EXPECT_EQ(i + num, unknown.field(i).fixed32()); + } + } + } + } + } +} + +void CheckDeleteByNumber(const vector& field_numbers, int deleted_number, + const vector& expected_field_nubmers) { + UnknownFieldSet unknown_fields; + for (int i = 0; i < field_numbers.size(); ++i) { + unknown_fields.AddFixed32(field_numbers[i], i); + } + unknown_fields.DeleteByNumber(deleted_number); + ASSERT_EQ(expected_field_nubmers.size(), unknown_fields.field_count()); + for (int i = 0; i < expected_field_nubmers.size(); ++i) { + EXPECT_EQ(expected_field_nubmers[i], + unknown_fields.field(i).number()); + } +} + +#define MAKE_VECTOR(x) vector(x, x + GOOGLE_ARRAYSIZE(x)) +TEST_F(UnknownFieldSetTest, DeleteByNumber) { + CheckDeleteByNumber(vector(), 1, vector()); + static const int kTestFieldNumbers1[] = {1, 2, 3}; + static const int kFieldNumberToDelete1 = 1; + static const int kExpectedFieldNumbers1[] = {2, 3}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers1), kFieldNumberToDelete1, + MAKE_VECTOR(kExpectedFieldNumbers1)); + static const int kTestFieldNumbers2[] = {1, 2, 3}; + static const int kFieldNumberToDelete2 = 2; + static const int kExpectedFieldNumbers2[] = {1, 3}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers2), kFieldNumberToDelete2, + MAKE_VECTOR(kExpectedFieldNumbers2)); + static const int kTestFieldNumbers3[] = {1, 2, 3}; + static const int kFieldNumberToDelete3 = 3; + static const int kExpectedFieldNumbers3[] = {1, 2}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers3), kFieldNumberToDelete3, + MAKE_VECTOR(kExpectedFieldNumbers3)); + static const int kTestFieldNumbers4[] = {1, 2, 1, 4, 1}; + static const int kFieldNumberToDelete4 = 1; + static const int kExpectedFieldNumbers4[] = {2, 4}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers4), kFieldNumberToDelete4, + MAKE_VECTOR(kExpectedFieldNumbers4)); + static const int kTestFieldNumbers5[] = {1, 2, 3, 4, 5}; + static const int kFieldNumberToDelete5 = 6; + static const int kExpectedFieldNumbers5[] = {1, 2, 3, 4, 5}; + CheckDeleteByNumber(MAKE_VECTOR(kTestFieldNumbers5), kFieldNumberToDelete5, + MAKE_VECTOR(kExpectedFieldNumbers5)); +} +#undef MAKE_VECTOR +} // namespace + +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.cc new file mode 100644 index 000000000..ead763b18 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.cc @@ -0,0 +1,1063 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace google { +namespace protobuf { +namespace internal { + +namespace { + +// This function turns out to be convenient when using some macros later. +inline int GetEnumNumber(const EnumValueDescriptor* descriptor) { + return descriptor->number(); +} + +} // anonymous namespace + +// =================================================================== + +bool UnknownFieldSetFieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormat::SkipField(input, tag, unknown_fields_); +} + +bool UnknownFieldSetFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormat::SkipMessage(input, unknown_fields_); +} + +void UnknownFieldSetFieldSkipper::SkipUnknownEnum( + int field_number, int value) { + unknown_fields_->AddVarint(field_number, value); +} + +bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, + UnknownFieldSet* unknown_fields) { + int number = WireFormatLite::GetTagFieldNumber(tag); + + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64 value; + if (!input->ReadVarint64(&value)) return false; + if (unknown_fields != NULL) unknown_fields->AddVarint(number, value); + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64 value; + if (!input->ReadLittleEndian64(&value)) return false; + if (unknown_fields != NULL) unknown_fields->AddFixed64(number, value); + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (unknown_fields == NULL) { + if (!input->Skip(length)) return false; + } else { + if (!input->ReadString(unknown_fields->AddLengthDelimited(number), + length)) { + return false; + } + } + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input, (unknown_fields == NULL) ? + NULL : unknown_fields->AddGroup(number))) { + return false; + } + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32 value; + if (!input->ReadLittleEndian32(&value)) return false; + if (unknown_fields != NULL) unknown_fields->AddFixed32(number, value); + return true; + } + default: { + return false; + } + } +} + +bool WireFormat::SkipMessage(io::CodedInputStream* input, + UnknownFieldSet* unknown_fields) { + while(true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag, unknown_fields)) return false; + } +} + +void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, + io::CodedOutputStream* output) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + switch (field.type()) { + case UnknownField::TYPE_VARINT: + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_VARINT)); + output->WriteVarint64(field.varint()); + break; + case UnknownField::TYPE_FIXED32: + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED32)); + output->WriteLittleEndian32(field.fixed32()); + break; + case UnknownField::TYPE_FIXED64: + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED64)); + output->WriteLittleEndian64(field.fixed64()); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + output->WriteVarint32(field.length_delimited().size()); + output->WriteString(field.length_delimited()); + break; + case UnknownField::TYPE_GROUP: + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_START_GROUP)); + SerializeUnknownFields(field.group(), output); + output->WriteVarint32(WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_END_GROUP)); + break; + } + } +} + +uint8* WireFormat::SerializeUnknownFieldsToArray( + const UnknownFieldSet& unknown_fields, + uint8* target) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + switch (field.type()) { + case UnknownField::TYPE_VARINT: + target = WireFormatLite::WriteInt64ToArray( + field.number(), field.varint(), target); + break; + case UnknownField::TYPE_FIXED32: + target = WireFormatLite::WriteFixed32ToArray( + field.number(), field.fixed32(), target); + break; + case UnknownField::TYPE_FIXED64: + target = WireFormatLite::WriteFixed64ToArray( + field.number(), field.fixed64(), target); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + target = WireFormatLite::WriteBytesToArray( + field.number(), field.length_delimited(), target); + break; + case UnknownField::TYPE_GROUP: + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_START_GROUP, target); + target = SerializeUnknownFieldsToArray(field.group(), target); + target = WireFormatLite::WriteTagToArray( + field.number(), WireFormatLite::WIRETYPE_END_GROUP, target); + break; + } + } + return target; +} + +void WireFormat::SerializeUnknownMessageSetItems( + const UnknownFieldSet& unknown_fields, + io::CodedOutputStream* output) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + // The only unknown fields that are allowed to exist in a MessageSet are + // messages, which are length-delimited. + if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { + // Start group. + output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); + output->WriteVarint32(field.number()); + + // Write message. + output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); + field.SerializeLengthDelimitedNoTag(output); + + // End group. + output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); + } + } +} + +uint8* WireFormat::SerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, + uint8* target) { + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + // The only unknown fields that are allowed to exist in a MessageSet are + // messages, which are length-delimited. + if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { + // Start group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemStartTag, target); + + // Write type ID. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetTypeIdTag, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + field.number(), target); + + // Write message. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetMessageTag, target); + target = field.SerializeLengthDelimitedNoTagToArray(target); + + // End group. + target = io::CodedOutputStream::WriteTagToArray( + WireFormatLite::kMessageSetItemEndTag, target); + } + } + + return target; +} + +int WireFormat::ComputeUnknownFieldsSize( + const UnknownFieldSet& unknown_fields) { + int size = 0; + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + switch (field.type()) { + case UnknownField::TYPE_VARINT: + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_VARINT)); + size += io::CodedOutputStream::VarintSize64(field.varint()); + break; + case UnknownField::TYPE_FIXED32: + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED32)); + size += sizeof(int32); + break; + case UnknownField::TYPE_FIXED64: + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_FIXED64)); + size += sizeof(int64); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + size += io::CodedOutputStream::VarintSize32( + field.length_delimited().size()); + size += field.length_delimited().size(); + break; + case UnknownField::TYPE_GROUP: + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_START_GROUP)); + size += ComputeUnknownFieldsSize(field.group()); + size += io::CodedOutputStream::VarintSize32( + WireFormatLite::MakeTag(field.number(), + WireFormatLite::WIRETYPE_END_GROUP)); + break; + } + } + + return size; +} + +int WireFormat::ComputeUnknownMessageSetItemsSize( + const UnknownFieldSet& unknown_fields) { + int size = 0; + for (int i = 0; i < unknown_fields.field_count(); i++) { + const UnknownField& field = unknown_fields.field(i); + + // The only unknown fields that are allowed to exist in a MessageSet are + // messages, which are length-delimited. + if (field.type() == UnknownField::TYPE_LENGTH_DELIMITED) { + size += WireFormatLite::kMessageSetItemTagsSize; + size += io::CodedOutputStream::VarintSize32(field.number()); + + int field_size = field.GetLengthDelimitedSize(); + size += io::CodedOutputStream::VarintSize32(field_size); + size += field_size; + } + } + + return size; +} + +// =================================================================== + +bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, + Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* message_reflection = message->GetReflection(); + + while(true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + if (WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + const FieldDescriptor* field = NULL; + + if (descriptor != NULL) { + int field_number = WireFormatLite::GetTagFieldNumber(tag); + field = descriptor->FindFieldByNumber(field_number); + + // If that failed, check if the field is an extension. + if (field == NULL && descriptor->IsExtensionNumber(field_number)) { + if (input->GetExtensionPool() == NULL) { + field = message_reflection->FindKnownExtensionByNumber(field_number); + } else { + field = input->GetExtensionPool() + ->FindExtensionByNumber(descriptor, field_number); + } + } + + // If that failed, but we're a MessageSet, and this is the tag for a + // MessageSet item, then parse that. + if (field == NULL && + descriptor->options().message_set_wire_format() && + tag == WireFormatLite::kMessageSetItemStartTag) { + if (!ParseAndMergeMessageSetItem(input, message)) { + return false; + } + continue; // Skip ParseAndMergeField(); already taken care of. + } + } + + if (!ParseAndMergeField(tag, field, message, input)) { + return false; + } + } +} + +bool WireFormat::ParseAndMergeField( + uint32 tag, + const FieldDescriptor* field, // May be NULL for unknown + Message* message, + io::CodedInputStream* input) { + const Reflection* message_reflection = message->GetReflection(); + + enum { UNKNOWN, NORMAL_FORMAT, PACKED_FORMAT } value_format; + + if (field == NULL) { + value_format = UNKNOWN; + } else if (WireFormatLite::GetTagWireType(tag) == + WireTypeForFieldType(field->type())) { + value_format = NORMAL_FORMAT; + } else if (field->is_packable() && + WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + value_format = PACKED_FORMAT; + } else { + // We don't recognize this field. Either the field number is unknown + // or the wire type doesn't match. Put it in our unknown field set. + value_format = UNKNOWN; + } + + if (value_format == UNKNOWN) { + return SkipField(input, tag, + message_reflection->MutableUnknownFields(message)); + } else if (value_format == PACKED_FORMAT) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + + switch (field->type()) { +#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + while (input->BytesUntilLimit() > 0) { \ + CPPTYPE value; \ + if (!WireFormatLite::ReadPrimitive< \ + CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \ + return false; \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ + } + + HANDLE_PACKED_TYPE( INT32, int32, Int32) + HANDLE_PACKED_TYPE( INT64, int64, Int64) + HANDLE_PACKED_TYPE(SINT32, int32, Int32) + HANDLE_PACKED_TYPE(SINT64, int64, Int64) + HANDLE_PACKED_TYPE(UINT32, uint32, UInt32) + HANDLE_PACKED_TYPE(UINT64, uint64, UInt64) + + HANDLE_PACKED_TYPE( FIXED32, uint32, UInt32) + HANDLE_PACKED_TYPE( FIXED64, uint64, UInt64) + HANDLE_PACKED_TYPE(SFIXED32, int32, Int32) + HANDLE_PACKED_TYPE(SFIXED64, int64, Int64) + + HANDLE_PACKED_TYPE(FLOAT , float , Float ) + HANDLE_PACKED_TYPE(DOUBLE, double, Double) + + HANDLE_PACKED_TYPE(BOOL, bool, Bool) +#undef HANDLE_PACKED_TYPE + + case FieldDescriptor::TYPE_ENUM: { + while (input->BytesUntilLimit() > 0) { + int value; + if (!WireFormatLite::ReadPrimitive( + input, &value)) return false; + const EnumValueDescriptor* enum_value = + field->enum_type()->FindValueByNumber(value); + if (enum_value != NULL) { + message_reflection->AddEnum(message, field, enum_value); + } + } + + break; + } + + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_BYTES: + // Can't have packed fields of these types: these should be caught by + // the protocol compiler. + return false; + break; + } + + input->PopLimit(limit); + } else { + // Non-packed value (value_format == NORMAL_FORMAT) + switch (field->type()) { +#define HANDLE_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + CPPTYPE value; \ + if (!WireFormatLite::ReadPrimitive< \ + CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)) \ + return false; \ + if (field->is_repeated()) { \ + message_reflection->Add##CPPTYPE_METHOD(message, field, value); \ + } else { \ + message_reflection->Set##CPPTYPE_METHOD(message, field, value); \ + } \ + break; \ + } + + HANDLE_TYPE( INT32, int32, Int32) + HANDLE_TYPE( INT64, int64, Int64) + HANDLE_TYPE(SINT32, int32, Int32) + HANDLE_TYPE(SINT64, int64, Int64) + HANDLE_TYPE(UINT32, uint32, UInt32) + HANDLE_TYPE(UINT64, uint64, UInt64) + + HANDLE_TYPE( FIXED32, uint32, UInt32) + HANDLE_TYPE( FIXED64, uint64, UInt64) + HANDLE_TYPE(SFIXED32, int32, Int32) + HANDLE_TYPE(SFIXED64, int64, Int64) + + HANDLE_TYPE(FLOAT , float , Float ) + HANDLE_TYPE(DOUBLE, double, Double) + + HANDLE_TYPE(BOOL, bool, Bool) +#undef HANDLE_TYPE + + case FieldDescriptor::TYPE_ENUM: { + int value; + if (!WireFormatLite::ReadPrimitive( + input, &value)) return false; + const EnumValueDescriptor* enum_value = + field->enum_type()->FindValueByNumber(value); + if (enum_value != NULL) { + if (field->is_repeated()) { + message_reflection->AddEnum(message, field, enum_value); + } else { + message_reflection->SetEnum(message, field, enum_value); + } + } else { + // The enum value is not one of the known values. Add it to the + // UnknownFieldSet. + int64 sign_extended_value = static_cast(value); + message_reflection->MutableUnknownFields(message) + ->AddVarint(WireFormatLite::GetTagFieldNumber(tag), + sign_extended_value); + } + break; + } + + // Handle strings separately so that we can optimize the ctype=CORD case. + case FieldDescriptor::TYPE_STRING: { + string value; + if (!WireFormatLite::ReadString(input, &value)) return false; + VerifyUTF8String(value.data(), value.length(), PARSE); + if (field->is_repeated()) { + message_reflection->AddString(message, field, value); + } else { + message_reflection->SetString(message, field, value); + } + break; + } + + case FieldDescriptor::TYPE_BYTES: { + string value; + if (!WireFormatLite::ReadBytes(input, &value)) return false; + if (field->is_repeated()) { + message_reflection->AddString(message, field, value); + } else { + message_reflection->SetString(message, field, value); + } + break; + } + + case FieldDescriptor::TYPE_GROUP: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = message_reflection->AddMessage( + message, field, input->GetExtensionFactory()); + } else { + sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + } + + if (!WireFormatLite::ReadGroup(WireFormatLite::GetTagFieldNumber(tag), + input, sub_message)) + return false; + break; + } + + case FieldDescriptor::TYPE_MESSAGE: { + Message* sub_message; + if (field->is_repeated()) { + sub_message = message_reflection->AddMessage( + message, field, input->GetExtensionFactory()); + } else { + sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + } + + if (!WireFormatLite::ReadMessage(input, sub_message)) return false; + break; + } + } + } + + return true; +} + +bool WireFormat::ParseAndMergeMessageSetItem( + io::CodedInputStream* input, + Message* message) { + const Reflection* message_reflection = message->GetReflection(); + + // This method parses a group which should contain two fields: + // required int32 type_id = 2; + // required data message = 3; + + // Once we see a type_id, we'll construct a fake tag for this extension + // which is the tag it would have had under the proto2 extensions wire + // format. + uint32 fake_tag = 0; + + // Once we see a type_id, we'll look up the FieldDescriptor for the + // extension. + const FieldDescriptor* field = NULL; + + // If we see message data before the type_id, we'll append it to this so + // we can parse it later. + string message_data; + + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) return false; + + switch (tag) { + case WireFormatLite::kMessageSetTypeIdTag: { + uint32 type_id; + if (!input->ReadVarint32(&type_id)) return false; + fake_tag = WireFormatLite::MakeTag( + type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + field = message_reflection->FindKnownExtensionByNumber(type_id); + + if (!message_data.empty()) { + // We saw some message data before the type_id. Have to parse it + // now. + io::ArrayInputStream raw_input(message_data.data(), + message_data.size()); + io::CodedInputStream sub_input(&raw_input); + if (!ParseAndMergeField(fake_tag, field, message, + &sub_input)) { + return false; + } + message_data.clear(); + } + + break; + } + + case WireFormatLite::kMessageSetMessageTag: { + if (fake_tag == 0) { + // We haven't seen a type_id yet. Append this data to message_data. + string temp; + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->ReadString(&temp, length)) return false; + io::StringOutputStream output_stream(&message_data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteVarint32(length); + coded_output.WriteString(temp); + } else { + // Already saw type_id, so we can parse this directly. + if (!ParseAndMergeField(fake_tag, field, message, input)) { + return false; + } + } + + break; + } + + case WireFormatLite::kMessageSetItemEndTag: { + return true; + } + + default: { + if (!SkipField(input, tag, NULL)) return false; + } + } + } +} + +// =================================================================== + +void WireFormat::SerializeWithCachedSizes( + const Message& message, + int size, io::CodedOutputStream* output) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* message_reflection = message.GetReflection(); + int expected_endpoint = output->ByteCount() + size; + + vector fields; + message_reflection->ListFields(message, &fields); + for (int i = 0; i < fields.size(); i++) { + SerializeFieldWithCachedSizes(fields[i], message, output); + } + + if (descriptor->options().message_set_wire_format()) { + SerializeUnknownMessageSetItems( + message_reflection->GetUnknownFields(message), output); + } else { + SerializeUnknownFields( + message_reflection->GetUnknownFields(message), output); + } + + GOOGLE_CHECK_EQ(output->ByteCount(), expected_endpoint) + << ": Protocol message serialized to a size different from what was " + "originally expected. Perhaps it was modified by another thread " + "during serialization?"; +} + +void WireFormat::SerializeFieldWithCachedSizes( + const FieldDescriptor* field, + const Message& message, + io::CodedOutputStream* output) { + const Reflection* message_reflection = message.GetReflection(); + + if (field->is_extension() && + field->containing_type()->options().message_set_wire_format() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { + SerializeMessageSetItemWithCachedSizes(field, message, output); + return; + } + + int count = 0; + + if (field->is_repeated()) { + count = message_reflection->FieldSize(message, field); + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + const bool is_packed = field->options().packed(); + if (is_packed && count > 0) { + WireFormatLite::WriteTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + const int data_size = FieldDataOnlyByteSize(field, message); + output->WriteVarint32(data_size); + } + + for (int j = 0; j < count; j++) { + switch (field->type()) { +#define HANDLE_PRIMITIVE_TYPE(TYPE, CPPTYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: { \ + const CPPTYPE value = field->is_repeated() ? \ + message_reflection->GetRepeated##CPPTYPE_METHOD( \ + message, field, j) : \ + message_reflection->Get##CPPTYPE_METHOD( \ + message, field); \ + if (is_packed) { \ + WireFormatLite::Write##TYPE_METHOD##NoTag(value, output); \ + } else { \ + WireFormatLite::Write##TYPE_METHOD(field->number(), value, output); \ + } \ + break; \ + } + + HANDLE_PRIMITIVE_TYPE( INT32, int32, Int32, Int32) + HANDLE_PRIMITIVE_TYPE( INT64, int64, Int64, Int64) + HANDLE_PRIMITIVE_TYPE(SINT32, int32, SInt32, Int32) + HANDLE_PRIMITIVE_TYPE(SINT64, int64, SInt64, Int64) + HANDLE_PRIMITIVE_TYPE(UINT32, uint32, UInt32, UInt32) + HANDLE_PRIMITIVE_TYPE(UINT64, uint64, UInt64, UInt64) + + HANDLE_PRIMITIVE_TYPE( FIXED32, uint32, Fixed32, UInt32) + HANDLE_PRIMITIVE_TYPE( FIXED64, uint64, Fixed64, UInt64) + HANDLE_PRIMITIVE_TYPE(SFIXED32, int32, SFixed32, Int32) + HANDLE_PRIMITIVE_TYPE(SFIXED64, int64, SFixed64, Int64) + + HANDLE_PRIMITIVE_TYPE(FLOAT , float , Float , Float ) + HANDLE_PRIMITIVE_TYPE(DOUBLE, double, Double, Double) + + HANDLE_PRIMITIVE_TYPE(BOOL, bool, Bool, Bool) +#undef HANDLE_PRIMITIVE_TYPE + +#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: \ + WireFormatLite::Write##TYPE_METHOD( \ + field->number(), \ + field->is_repeated() ? \ + message_reflection->GetRepeated##CPPTYPE_METHOD( \ + message, field, j) : \ + message_reflection->Get##CPPTYPE_METHOD(message, field), \ + output); \ + break; + + HANDLE_TYPE(GROUP , Group , Message) + HANDLE_TYPE(MESSAGE, Message, Message) +#undef HANDLE_TYPE + + case FieldDescriptor::TYPE_ENUM: { + const EnumValueDescriptor* value = field->is_repeated() ? + message_reflection->GetRepeatedEnum(message, field, j) : + message_reflection->GetEnum(message, field); + if (is_packed) { + WireFormatLite::WriteEnumNoTag(value->number(), output); + } else { + WireFormatLite::WriteEnum(field->number(), value->number(), output); + } + break; + } + + // Handle strings separately so that we can get string references + // instead of copying. + case FieldDescriptor::TYPE_STRING: { + string scratch; + const string& value = field->is_repeated() ? + message_reflection->GetRepeatedStringReference( + message, field, j, &scratch) : + message_reflection->GetStringReference(message, field, &scratch); + VerifyUTF8String(value.data(), value.length(), SERIALIZE); + WireFormatLite::WriteString(field->number(), value, output); + break; + } + + case FieldDescriptor::TYPE_BYTES: { + string scratch; + const string& value = field->is_repeated() ? + message_reflection->GetRepeatedStringReference( + message, field, j, &scratch) : + message_reflection->GetStringReference(message, field, &scratch); + WireFormatLite::WriteBytes(field->number(), value, output); + break; + } + } + } +} + +void WireFormat::SerializeMessageSetItemWithCachedSizes( + const FieldDescriptor* field, + const Message& message, + io::CodedOutputStream* output) { + const Reflection* message_reflection = message.GetReflection(); + + // Start group. + output->WriteVarint32(WireFormatLite::kMessageSetItemStartTag); + + // Write type ID. + output->WriteVarint32(WireFormatLite::kMessageSetTypeIdTag); + output->WriteVarint32(field->number()); + + // Write message. + output->WriteVarint32(WireFormatLite::kMessageSetMessageTag); + + const Message& sub_message = message_reflection->GetMessage(message, field); + output->WriteVarint32(sub_message.GetCachedSize()); + sub_message.SerializeWithCachedSizes(output); + + // End group. + output->WriteVarint32(WireFormatLite::kMessageSetItemEndTag); +} + +// =================================================================== + +int WireFormat::ByteSize(const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* message_reflection = message.GetReflection(); + + int our_size = 0; + + vector fields; + message_reflection->ListFields(message, &fields); + for (int i = 0; i < fields.size(); i++) { + our_size += FieldByteSize(fields[i], message); + } + + if (descriptor->options().message_set_wire_format()) { + our_size += ComputeUnknownMessageSetItemsSize( + message_reflection->GetUnknownFields(message)); + } else { + our_size += ComputeUnknownFieldsSize( + message_reflection->GetUnknownFields(message)); + } + + return our_size; +} + +int WireFormat::FieldByteSize( + const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + if (field->is_extension() && + field->containing_type()->options().message_set_wire_format() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_repeated()) { + return MessageSetItemByteSize(field, message); + } + + int count = 0; + if (field->is_repeated()) { + count = message_reflection->FieldSize(message, field); + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + const int data_size = FieldDataOnlyByteSize(field, message); + int our_size = data_size; + if (field->options().packed()) { + if (data_size > 0) { + // Packed fields get serialized like a string, not their native type. + // Technically this doesn't really matter; the size only changes if it's + // a GROUP + our_size += TagSize(field->number(), FieldDescriptor::TYPE_STRING); + our_size += io::CodedOutputStream::VarintSize32(data_size); + } + } else { + our_size += count * TagSize(field->number(), field->type()); + } + return our_size; +} + +int WireFormat::FieldDataOnlyByteSize( + const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + int count = 0; + if (field->is_repeated()) { + count = message_reflection->FieldSize(message, field); + } else if (message_reflection->HasField(message, field)) { + count = 1; + } + + int data_size = 0; + switch (field->type()) { +#define HANDLE_TYPE(TYPE, TYPE_METHOD, CPPTYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: \ + if (field->is_repeated()) { \ + for (int j = 0; j < count; j++) { \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ + message_reflection->GetRepeated##CPPTYPE_METHOD( \ + message, field, j)); \ + } \ + } else { \ + data_size += WireFormatLite::TYPE_METHOD##Size( \ + message_reflection->Get##CPPTYPE_METHOD(message, field)); \ + } \ + break; + +#define HANDLE_FIXED_TYPE(TYPE, TYPE_METHOD) \ + case FieldDescriptor::TYPE_##TYPE: \ + data_size += count * WireFormatLite::k##TYPE_METHOD##Size; \ + break; + + HANDLE_TYPE( INT32, Int32, Int32) + HANDLE_TYPE( INT64, Int64, Int64) + HANDLE_TYPE(SINT32, SInt32, Int32) + HANDLE_TYPE(SINT64, SInt64, Int64) + HANDLE_TYPE(UINT32, UInt32, UInt32) + HANDLE_TYPE(UINT64, UInt64, UInt64) + + HANDLE_FIXED_TYPE( FIXED32, Fixed32) + HANDLE_FIXED_TYPE( FIXED64, Fixed64) + HANDLE_FIXED_TYPE(SFIXED32, SFixed32) + HANDLE_FIXED_TYPE(SFIXED64, SFixed64) + + HANDLE_FIXED_TYPE(FLOAT , Float ) + HANDLE_FIXED_TYPE(DOUBLE, Double) + + HANDLE_FIXED_TYPE(BOOL, Bool) + + HANDLE_TYPE(GROUP , Group , Message) + HANDLE_TYPE(MESSAGE, Message, Message) +#undef HANDLE_TYPE +#undef HANDLE_FIXED_TYPE + + case FieldDescriptor::TYPE_ENUM: { + if (field->is_repeated()) { + for (int j = 0; j < count; j++) { + data_size += WireFormatLite::EnumSize( + message_reflection->GetRepeatedEnum(message, field, j)->number()); + } + } else { + data_size += WireFormatLite::EnumSize( + message_reflection->GetEnum(message, field)->number()); + } + break; + } + + // Handle strings separately so that we can get string references + // instead of copying. + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: { + for (int j = 0; j < count; j++) { + string scratch; + const string& value = field->is_repeated() ? + message_reflection->GetRepeatedStringReference( + message, field, j, &scratch) : + message_reflection->GetStringReference(message, field, &scratch); + data_size += WireFormatLite::StringSize(value); + } + break; + } + } + return data_size; +} + +int WireFormat::MessageSetItemByteSize( + const FieldDescriptor* field, + const Message& message) { + const Reflection* message_reflection = message.GetReflection(); + + int our_size = WireFormatLite::kMessageSetItemTagsSize; + + // type_id + our_size += io::CodedOutputStream::VarintSize32(field->number()); + + // message + const Message& sub_message = message_reflection->GetMessage(message, field); + int message_size = sub_message.ByteSize(); + + our_size += io::CodedOutputStream::VarintSize32(message_size); + our_size += message_size; + + return our_size; +} + +void WireFormat::VerifyUTF8StringFallback(const char* data, + int size, + Operation op) { + if (!IsStructurallyValidUTF8(data, size)) { + const char* operation_str = NULL; + switch (op) { + case PARSE: + operation_str = "parsing"; + break; + case SERIALIZE: + operation_str = "serializing"; + break; + // no default case: have the compiler warn if a case is not covered. + } + GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when " + << operation_str + << " a protocol buffer. Use the 'bytes' type if you intend to " + "send raw bytes."; + } +} + + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.h new file mode 100644 index 000000000..6cc900299 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format.h @@ -0,0 +1,308 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// atenasio@google.com (Chris Atenasio) (ZigZag transform) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_H__ + +#include +#include +#include +#include +#include +#include + +// Do UTF-8 validation on string type in Debug build only +#ifndef NDEBUG +#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED +#endif + +namespace google { +namespace protobuf { + namespace io { + class CodedInputStream; // coded_stream.h + class CodedOutputStream; // coded_stream.h + } + class UnknownFieldSet; // unknown_field_set.h +} + +namespace protobuf { +namespace internal { + +// This class is for internal use by the protocol buffer library and by +// protocol-complier-generated message classes. It must not be called +// directly by clients. +// +// This class contains code for implementing the binary protocol buffer +// wire format via reflection. The WireFormatLite class implements the +// non-reflection based routines. +// +// This class is really a namespace that contains only static methods +class LIBPROTOBUF_EXPORT WireFormat { + public: + + // Given a field return its WireType + static inline WireFormatLite::WireType WireTypeForField( + const FieldDescriptor* field); + + // Given a FieldSescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + FieldDescriptor::Type type); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline int TagSize(int field_number, FieldDescriptor::Type type); + + // These procedures can be used to implement the methods of Message which + // handle parsing and serialization of the protocol buffer wire format + // using only the Reflection interface. When you ask the protocol + // compiler to optimize for code size rather than speed, it will implement + // those methods in terms of these procedures. Of course, these are much + // slower than the specialized implementations which the protocol compiler + // generates when told to optimize for speed. + + // Read a message in protocol buffer wire format. + // + // This procedure reads either to the end of the input stream or through + // a WIRETYPE_END_GROUP tag ending the message, whichever comes first. + // It returns false if the input is invalid. + // + // Required fields are NOT checked by this method. You must call + // IsInitialized() on the resulting message yourself. + static bool ParseAndMergePartial(io::CodedInputStream* input, + Message* message); + + // Serialize a message in protocol buffer wire format. + // + // Any embedded messages within the message must have their correct sizes + // cached. However, the top-level message need not; its size is passed as + // a parameter to this procedure. + // + // These return false iff the underlying stream returns a write error. + static void SerializeWithCachedSizes( + const Message& message, + int size, io::CodedOutputStream* output); + + // Implements Message::ByteSize() via reflection. WARNING: The result + // of this method is *not* cached anywhere. However, all embedded messages + // will have their ByteSize() methods called, so their sizes will be cached. + // Therefore, calling this method is sufficient to allow you to call + // WireFormat::SerializeWithCachedSizes() on the same object. + static int ByteSize(const Message& message); + + // ----------------------------------------------------------------- + // Helpers for dealing with unknown fields + + // Skips a field value of the given WireType. The input should start + // positioned immediately after the tag. If unknown_fields is non-NULL, + // the contents of the field will be added to it. + static bool SkipField(io::CodedInputStream* input, uint32 tag, + UnknownFieldSet* unknown_fields); + + // Reads and ignores a message from the input. If unknown_fields is non-NULL, + // the contents will be added to it. + static bool SkipMessage(io::CodedInputStream* input, + UnknownFieldSet* unknown_fields); + + // Write the contents of an UnknownFieldSet to the output. + static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields, + io::CodedOutputStream* output); + // Same as above, except writing directly to the provided buffer. + // Requires that the buffer have sufficient capacity for + // ComputeUnknownFieldsSize(unknown_fields). + // + // Returns a pointer past the last written byte. + static uint8* SerializeUnknownFieldsToArray( + const UnknownFieldSet& unknown_fields, + uint8* target); + + // Same thing except for messages that have the message_set_wire_format + // option. + static void SerializeUnknownMessageSetItems( + const UnknownFieldSet& unknown_fields, + io::CodedOutputStream* output); + // Same as above, except writing directly to the provided buffer. + // Requires that the buffer have sufficient capacity for + // ComputeUnknownMessageSetItemsSize(unknown_fields). + // + // Returns a pointer past the last written byte. + static uint8* SerializeUnknownMessageSetItemsToArray( + const UnknownFieldSet& unknown_fields, + uint8* target); + + // Compute the size of the UnknownFieldSet on the wire. + static int ComputeUnknownFieldsSize(const UnknownFieldSet& unknown_fields); + + // Same thing except for messages that have the message_set_wire_format + // option. + static int ComputeUnknownMessageSetItemsSize( + const UnknownFieldSet& unknown_fields); + + + // Helper functions for encoding and decoding tags. (Inlined below and in + // _inl.h) + // + // This is different from MakeTag(field->number(), field->type()) in the case + // of packed repeated fields. + static uint32 MakeTag(const FieldDescriptor* field); + + // Parse a single field. The input should start out positioned immidately + // after the tag. + static bool ParseAndMergeField( + uint32 tag, + const FieldDescriptor* field, // May be NULL for unknown + Message* message, + io::CodedInputStream* input); + + // Serialize a single field. + static void SerializeFieldWithCachedSizes( + const FieldDescriptor* field, // Cannot be NULL + const Message& message, + io::CodedOutputStream* output); + + // Compute size of a single field. If the field is a message type, this + // will call ByteSize() for the embedded message, insuring that it caches + // its size. + static int FieldByteSize( + const FieldDescriptor* field, // Cannot be NULL + const Message& message); + + // Parse/serialize a MessageSet::Item group. Used with messages that use + // opion message_set_wire_format = true. + static bool ParseAndMergeMessageSetItem( + io::CodedInputStream* input, + Message* message); + static void SerializeMessageSetItemWithCachedSizes( + const FieldDescriptor* field, + const Message& message, + io::CodedOutputStream* output); + static int MessageSetItemByteSize( + const FieldDescriptor* field, + const Message& message); + + // Computes the byte size of a field, excluding tags. For packed fields, it + // only includes the size of the raw data, and not the size of the total + // length, but for other length-delimited types, the size of the length is + // included. + static int FieldDataOnlyByteSize( + const FieldDescriptor* field, // Cannot be NULL + const Message& message); + + enum Operation { + PARSE, + SERIALIZE, + }; + + // Verifies that a string field is valid UTF8, logging an error if not. + static void VerifyUTF8String(const char* data, int size, Operation op); + + private: + // Verifies that a string field is valid UTF8, logging an error if not. + static void VerifyUTF8StringFallback( + const char* data, + int size, + Operation op); + + + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat); +}; + +// Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet. +class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { + public: + UnknownFieldSetFieldSkipper(UnknownFieldSet* unknown_fields) + : unknown_fields_(unknown_fields) {} + virtual ~UnknownFieldSetFieldSkipper() {} + + // implements FieldSkipper ----------------------------------------- + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + virtual bool SkipMessage(io::CodedInputStream* input); + virtual void SkipUnknownEnum(int field_number, int value); + + protected: + UnknownFieldSet* unknown_fields_; +}; + +// inline methods ==================================================== + +inline WireFormatLite::WireType WireFormat::WireTypeForField( + const FieldDescriptor* field) { + if (field->options().packed()) { + return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + } else { + return WireTypeForFieldType(field->type()); + } +} + +inline WireFormatLite::WireType WireFormat::WireTypeForFieldType( + FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::WireTypeForFieldType( + static_cast( + implicit_cast(type))); +} + +inline uint32 WireFormat::MakeTag(const FieldDescriptor* field) { + return WireFormatLite::MakeTag(field->number(), WireTypeForField(field)); +} + +inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) { + // Some compilers don't like enum -> enum casts, so we implicit_cast to + // int first. + return WireFormatLite::TagSize(field_number, + static_cast( + implicit_cast(type))); +} + +inline void WireFormat::VerifyUTF8String(const char* data, int size, + WireFormat::Operation op) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormat::VerifyUTF8StringFallback(data, size, op); +#else + // Avoid the compiler warning about unsued variables. + (void)data; (void)size; (void)op; +#endif +} + + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.cc new file mode 100644 index 000000000..738fc4214 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.cc @@ -0,0 +1,361 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +#ifndef _MSC_VER // MSVC doesn't like definitions of inline constants, GCC + // requires them. +const int WireFormatLite::kMessageSetItemStartTag; +const int WireFormatLite::kMessageSetItemEndTag; +const int WireFormatLite::kMessageSetTypeIdTag; +const int WireFormatLite::kMessageSetMessageTag; + +#endif + +const int WireFormatLite::kMessageSetItemTagsSize = + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value + + io::CodedOutputStream::StaticVarintSize32::value; + +const WireFormatLite::CppType +WireFormatLite::kFieldTypeToCppTypeMap[MAX_FIELD_TYPE + 1] = { + static_cast(0), // 0 is reserved for errors + + CPPTYPE_DOUBLE, // TYPE_DOUBLE + CPPTYPE_FLOAT, // TYPE_FLOAT + CPPTYPE_INT64, // TYPE_INT64 + CPPTYPE_UINT64, // TYPE_UINT64 + CPPTYPE_INT32, // TYPE_INT32 + CPPTYPE_UINT64, // TYPE_FIXED64 + CPPTYPE_UINT32, // TYPE_FIXED32 + CPPTYPE_BOOL, // TYPE_BOOL + CPPTYPE_STRING, // TYPE_STRING + CPPTYPE_MESSAGE, // TYPE_GROUP + CPPTYPE_MESSAGE, // TYPE_MESSAGE + CPPTYPE_STRING, // TYPE_BYTES + CPPTYPE_UINT32, // TYPE_UINT32 + CPPTYPE_ENUM, // TYPE_ENUM + CPPTYPE_INT32, // TYPE_SFIXED32 + CPPTYPE_INT64, // TYPE_SFIXED64 + CPPTYPE_INT32, // TYPE_SINT32 + CPPTYPE_INT64, // TYPE_SINT64 +}; + +const WireFormatLite::WireType +WireFormatLite::kWireTypeForFieldType[MAX_FIELD_TYPE + 1] = { + static_cast(-1), // invalid + WireFormatLite::WIRETYPE_FIXED64, // TYPE_DOUBLE + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FLOAT + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_INT32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_FIXED64 + WireFormatLite::WIRETYPE_FIXED32, // TYPE_FIXED32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_BOOL + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_STRING + WireFormatLite::WIRETYPE_START_GROUP, // TYPE_GROUP + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_MESSAGE + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, // TYPE_BYTES + WireFormatLite::WIRETYPE_VARINT, // TYPE_UINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_ENUM + WireFormatLite::WIRETYPE_FIXED32, // TYPE_SFIXED32 + WireFormatLite::WIRETYPE_FIXED64, // TYPE_SFIXED64 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT32 + WireFormatLite::WIRETYPE_VARINT, // TYPE_SINT64 +}; + +bool WireFormatLite::SkipField( + io::CodedInputStream* input, uint32 tag) { + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64 value; + if (!input->ReadVarint64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64 value; + if (!input->ReadLittleEndian64(&value)) return false; + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->Skip(length)) return false; + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32 value; + if (!input->ReadLittleEndian32(&value)) return false; + return true; + } + default: { + return false; + } + } +} + +bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { + while(true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag)) return false; + } +} + +bool FieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormatLite::SkipField(input, tag); +} + +bool FieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input); +} + +void FieldSkipper::SkipUnknownEnum( + int field_number, int value) { + // Nothing. +} + +bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input, + bool (*is_valid)(int), + RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid(value)) { + values->Add(value); + } + } + input->PopLimit(limit); + return true; +} + +void WireFormatLite::WriteInt32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt32NoTag(value, output); +} +void WireFormatLite::WriteInt64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteInt64NoTag(value, output); +} +void WireFormatLite::WriteUInt32(int field_number, uint32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt32NoTag(value, output); +} +void WireFormatLite::WriteUInt64(int field_number, uint64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteUInt64NoTag(value, output); +} +void WireFormatLite::WriteSInt32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt32NoTag(value, output); +} +void WireFormatLite::WriteSInt64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteSInt64NoTag(value, output); +} +void WireFormatLite::WriteFixed32(int field_number, uint32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFixed32NoTag(value, output); +} +void WireFormatLite::WriteFixed64(int field_number, uint64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteFixed64NoTag(value, output); +} +void WireFormatLite::WriteSFixed32(int field_number, int32 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteSFixed32NoTag(value, output); +} +void WireFormatLite::WriteSFixed64(int field_number, int64 value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteSFixed64NoTag(value, output); +} +void WireFormatLite::WriteFloat(int field_number, float value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED32, output); + WriteFloatNoTag(value, output); +} +void WireFormatLite::WriteDouble(int field_number, double value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_FIXED64, output); + WriteDoubleNoTag(value, output); +} +void WireFormatLite::WriteBool(int field_number, bool value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteBoolNoTag(value, output); +} +void WireFormatLite::WriteEnum(int field_number, int value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_VARINT, output); + WriteEnumNoTag(value, output); +} + +void WireFormatLite::WriteString(int field_number, const string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteString(value); +} +void WireFormatLite::WriteBytes(int field_number, const string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteString(value); +} + + +void WireFormatLite::WriteGroup(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} + +void WireFormatLite::WriteMessage(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + const int size = value.GetCachedSize(); + output->WriteVarint32(size); + value.SerializeWithCachedSizes(output); +} + +void WireFormatLite::WriteGroupMaybeToArray(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + const int size = value.GetCachedSize(); + uint8* target = output->GetDirectBufferForNBytesAndAdvance(size); + if (target != NULL) { + uint8* end = value.SerializeWithCachedSizesToArray(target); + GOOGLE_DCHECK_EQ(end - target, size); + } else { + value.SerializeWithCachedSizes(output); + } + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} + +void WireFormatLite::WriteMessageMaybeToArray(int field_number, + const MessageLite& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + const int size = value.GetCachedSize(); + output->WriteVarint32(size); + uint8* target = output->GetDirectBufferForNBytesAndAdvance(size); + if (target != NULL) { + uint8* end = value.SerializeWithCachedSizesToArray(target); + GOOGLE_DCHECK_EQ(end - target, size); + } else { + value.SerializeWithCachedSizes(output); + } +} + +bool WireFormatLite::ReadString(io::CodedInputStream* input, + string* value) { + // String is for UTF-8 text only + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->InternalReadStringInline(value, length)) return false; + return true; +} +bool WireFormatLite::ReadBytes(io::CodedInputStream* input, + string* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + return input->InternalReadStringInline(value, length); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.h new file mode 100644 index 000000000..cb4fc918b --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite.h @@ -0,0 +1,622 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// atenasio@google.com (Chris Atenasio) (ZigZag transform) +// wink@google.com (Wink Saville) (refactored from wire_format.h) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This header is logically internal, but is made public because it is used +// from protocol-compiler-generated code, which may reside in other components. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ + +#include +#include +#include +#include // for CodedOutputStream::Varint32Size + +namespace google { + +namespace protobuf { + template class RepeatedField; // repeated_field.h +} + +namespace protobuf { +namespace internal { + +class StringPieceField; + +// This class is for internal use by the protocol buffer library and by +// protocol-complier-generated message classes. It must not be called +// directly by clients. +// +// This class contains helpers for implementing the binary protocol buffer +// wire format without the need for reflection. Use WireFormat when using +// reflection. +// +// This class is really a namespace that contains only static methods. +class LIBPROTOBUF_EXPORT WireFormatLite { + public: + + // ----------------------------------------------------------------- + // Helper constants and functions related to the format. These are + // mostly meant for internal and generated code to use. + + // The wire format is composed of a sequence of tag/value pairs, each + // of which contains the value of one field (or one element of a repeated + // field). Each tag is encoded as a varint. The lower bits of the tag + // identify its wire type, which specifies the format of the data to follow. + // The rest of the bits contain the field number. Each type of field (as + // declared by FieldDescriptor::Type, in descriptor.h) maps to one of + // these wire types. Immediately following each tag is the field's value, + // encoded in the format specified by the wire type. Because the tag + // identifies the encoding of this data, it is possible to skip + // unrecognized fields for forwards compatibility. + + enum WireType { + WIRETYPE_VARINT = 0, + WIRETYPE_FIXED64 = 1, + WIRETYPE_LENGTH_DELIMITED = 2, + WIRETYPE_START_GROUP = 3, + WIRETYPE_END_GROUP = 4, + WIRETYPE_FIXED32 = 5, + }; + + // Lite alternative to FieldDescriptor::Type. Must be kept in sync. + enum FieldType { + TYPE_DOUBLE = 1, + TYPE_FLOAT = 2, + TYPE_INT64 = 3, + TYPE_UINT64 = 4, + TYPE_INT32 = 5, + TYPE_FIXED64 = 6, + TYPE_FIXED32 = 7, + TYPE_BOOL = 8, + TYPE_STRING = 9, + TYPE_GROUP = 10, + TYPE_MESSAGE = 11, + TYPE_BYTES = 12, + TYPE_UINT32 = 13, + TYPE_ENUM = 14, + TYPE_SFIXED32 = 15, + TYPE_SFIXED64 = 16, + TYPE_SINT32 = 17, + TYPE_SINT64 = 18, + MAX_FIELD_TYPE = 18, + }; + + // Lite alternative to FieldDescriptor::CppType. Must be kept in sync. + enum CppType { + CPPTYPE_INT32 = 1, + CPPTYPE_INT64 = 2, + CPPTYPE_UINT32 = 3, + CPPTYPE_UINT64 = 4, + CPPTYPE_DOUBLE = 5, + CPPTYPE_FLOAT = 6, + CPPTYPE_BOOL = 7, + CPPTYPE_ENUM = 8, + CPPTYPE_STRING = 9, + CPPTYPE_MESSAGE = 10, + MAX_CPPTYPE = 10, + }; + + // Helper method to get the CppType for a particular Type. + static CppType FieldTypeToCppType(FieldType type); + + // Given a FieldSescriptor::Type return its WireType + static inline WireFormatLite::WireType WireTypeForFieldType( + WireFormatLite::FieldType type) { + return kWireTypeForFieldType[type]; + } + + // Number of bits in a tag which identify the wire type. + static const int kTagTypeBits = 3; + // Mask for those bits. + static const uint32 kTagTypeMask = (1 << kTagTypeBits) - 1; + + // Helper functions for encoding and decoding tags. (Inlined below and in + // _inl.h) + // + // This is different from MakeTag(field->number(), field->type()) in the case + // of packed repeated fields. + static uint32 MakeTag(int field_number, WireType type); + static WireType GetTagWireType(uint32 tag); + static int GetTagFieldNumber(uint32 tag); + + // Compute the byte size of a tag. For groups, this includes both the start + // and end tags. + static inline int TagSize(int field_number, WireFormatLite::FieldType type); + + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are simply discarded, + // not recorded anywhere. See WireFormat::SkipField() for a version that + // records to an UnknownFieldSet. + static bool SkipField(io::CodedInputStream* input, uint32 tag); + + // Reads and ignores a message from the input. Skipped values are simply + // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a + // version that records to an UnknownFieldSet. + static bool SkipMessage(io::CodedInputStream* input); + +// This macro does the same thing as WireFormatLite::MakeTag(), but the +// result is usable as a compile-time constant, which makes it usable +// as a switch case or a template input. WireFormatLite::MakeTag() is more +// type-safe, though, so prefer it if possible. +#define GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(FIELD_NUMBER, TYPE) \ + static_cast( \ + ((FIELD_NUMBER) << ::google::protobuf::internal::WireFormatLite::kTagTypeBits) \ + | (TYPE)) + + // These are the tags for the old MessageSet format, which was defined as: + // message MessageSet { + // repeated group Item = 1 { + // required int32 type_id = 2; + // required string message = 3; + // } + // } + static const int kMessageSetItemNumber = 1; + static const int kMessageSetTypeIdNumber = 2; + static const int kMessageSetMessageNumber = 3; + static const int kMessageSetItemStartTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber, + WireFormatLite::WIRETYPE_START_GROUP); + static const int kMessageSetItemEndTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetItemNumber, + WireFormatLite::WIRETYPE_END_GROUP); + static const int kMessageSetTypeIdTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetTypeIdNumber, + WireFormatLite::WIRETYPE_VARINT); + static const int kMessageSetMessageTag = + GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(kMessageSetMessageNumber, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + + // Byte size of all tags of a MessageSet::Item combined. + static const int kMessageSetItemTagsSize; + + // Helper functions for converting between floats/doubles and IEEE-754 + // uint32s/uint64s so that they can be written. (Assumes your platform + // uses IEEE-754 floats.) + static uint32 EncodeFloat(float value); + static float DecodeFloat(uint32 value); + static uint64 EncodeDouble(double value); + static double DecodeDouble(uint64 value); + + // Helper functions for mapping signed integers to unsigned integers in + // such a way that numbers with small magnitudes will encode to smaller + // varints. If you simply static_cast a negative number to an unsigned + // number and varint-encode it, it will always take 10 bytes, defeating + // the purpose of varint. So, for the "sint32" and "sint64" field types, + // we ZigZag-encode the values. + static uint32 ZigZagEncode32(int32 n); + static int32 ZigZagDecode32(uint32 n); + static uint64 ZigZagEncode64(int64 n); + static int64 ZigZagDecode64(uint64 n); + + // ================================================================= + // Methods for reading/writing individual field. The implementations + // of these methods are defined in wire_format_lite_inl.h; you must #include + // that file to use these. + +// Avoid ugly line wrapping +#define input io::CodedInputStream* input +#define output io::CodedOutputStream* output +#define field_number int field_number +#define INL GOOGLE_ATTRIBUTE_ALWAYS_INLINE + + // Read fields, not including tags. The assumption is that you already + // read the tag to determine what field to read. + + // For primitive fields, we just use a templatized routine parameterized by + // the represented type and the FieldType. These are specialized with the + // appropriate definition for each declared type. + template + static inline bool ReadPrimitive(input, CType* value) INL; + + // Reads repeated primitive values, with optimizations for repeats. + // tag_size and tag should both be compile-time constants provided by the + // protocol compiler. + template + static inline bool ReadRepeatedPrimitive(int tag_size, + uint32 tag, + input, + RepeatedField* value) INL; + + // Identical to ReadRepeatedPrimitive, except will not inline the + // implementation. + template + static bool ReadRepeatedPrimitiveNoInline(int tag_size, + uint32 tag, + input, + RepeatedField* value); + + // Reads a primitive value directly from the provided buffer. It returns a + // pointer past the segment of data that was read. + // + // This is only implemented for the types with fixed wire size, e.g. + // float, double, and the (s)fixed* types. + template + static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer, + CType* value) INL; + + // Reads a primitive packed field. + // + // This is only implemented for packable types. + template + static inline bool ReadPackedPrimitive(input, + RepeatedField* value) INL; + + // Identical to ReadPackedPrimitive, except will not inline the + // implementation. + template + static bool ReadPackedPrimitiveNoInline(input, RepeatedField* value); + + // Read a packed enum field. Values for which is_valid() returns false are + // dropped. + static bool ReadPackedEnumNoInline(input, + bool (*is_valid)(int), + RepeatedField* value); + + static bool ReadString(input, string* value); + static bool ReadBytes (input, string* value); + + static inline bool ReadGroup (field_number, input, MessageLite* value); + static inline bool ReadMessage(input, MessageLite* value); + + // Like above, but de-virtualize the call to MergePartialFromCodedStream(). + // The pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override MergePartialFromCodedStream()). + template + static inline bool ReadGroupNoVirtual(field_number, input, + MessageType* value); + template + static inline bool ReadMessageNoVirtual(input, MessageType* value); + + // Write a tag. The Write*() functions typically include the tag, so + // normally there's no need to call this unless using the Write*NoTag() + // variants. + static inline void WriteTag(field_number, WireType type, output) INL; + + // Write fields, without tags. + static inline void WriteInt32NoTag (int32 value, output) INL; + static inline void WriteInt64NoTag (int64 value, output) INL; + static inline void WriteUInt32NoTag (uint32 value, output) INL; + static inline void WriteUInt64NoTag (uint64 value, output) INL; + static inline void WriteSInt32NoTag (int32 value, output) INL; + static inline void WriteSInt64NoTag (int64 value, output) INL; + static inline void WriteFixed32NoTag (uint32 value, output) INL; + static inline void WriteFixed64NoTag (uint64 value, output) INL; + static inline void WriteSFixed32NoTag(int32 value, output) INL; + static inline void WriteSFixed64NoTag(int64 value, output) INL; + static inline void WriteFloatNoTag (float value, output) INL; + static inline void WriteDoubleNoTag (double value, output) INL; + static inline void WriteBoolNoTag (bool value, output) INL; + static inline void WriteEnumNoTag (int value, output) INL; + + // Write fields, including tags. + static void WriteInt32 (field_number, int32 value, output); + static void WriteInt64 (field_number, int64 value, output); + static void WriteUInt32 (field_number, uint32 value, output); + static void WriteUInt64 (field_number, uint64 value, output); + static void WriteSInt32 (field_number, int32 value, output); + static void WriteSInt64 (field_number, int64 value, output); + static void WriteFixed32 (field_number, uint32 value, output); + static void WriteFixed64 (field_number, uint64 value, output); + static void WriteSFixed32(field_number, int32 value, output); + static void WriteSFixed64(field_number, int64 value, output); + static void WriteFloat (field_number, float value, output); + static void WriteDouble (field_number, double value, output); + static void WriteBool (field_number, bool value, output); + static void WriteEnum (field_number, int value, output); + + static void WriteString(field_number, const string& value, output); + static void WriteBytes (field_number, const string& value, output); + + static void WriteGroup( + field_number, const MessageLite& value, output); + static void WriteMessage( + field_number, const MessageLite& value, output); + // Like above, but these will check if the output stream has enough + // space to write directly to a flat array. + static void WriteGroupMaybeToArray( + field_number, const MessageLite& value, output); + static void WriteMessageMaybeToArray( + field_number, const MessageLite& value, output); + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template + static inline void WriteGroupNoVirtual( + field_number, const MessageType& value, output); + template + static inline void WriteMessageNoVirtual( + field_number, const MessageType& value, output); + +#undef output +#define output uint8* target + + // Like above, but use only *ToArray methods of CodedOutputStream. + static inline uint8* WriteTagToArray(field_number, WireType type, output) INL; + + // Write fields, without tags. + static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL; + static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL; + static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL; + static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL; + static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL; + static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL; + static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL; + static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL; + static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL; + static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL; + static inline uint8* WriteFloatNoTagToArray (float value, output) INL; + static inline uint8* WriteDoubleNoTagToArray (double value, output) INL; + static inline uint8* WriteBoolNoTagToArray (bool value, output) INL; + static inline uint8* WriteEnumNoTagToArray (int value, output) INL; + + // Write fields, including tags. + static inline uint8* WriteInt32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteInt64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteUInt32ToArray( + field_number, uint32 value, output) INL; + static inline uint8* WriteUInt64ToArray( + field_number, uint64 value, output) INL; + static inline uint8* WriteSInt32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteSInt64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteFixed32ToArray( + field_number, uint32 value, output) INL; + static inline uint8* WriteFixed64ToArray( + field_number, uint64 value, output) INL; + static inline uint8* WriteSFixed32ToArray( + field_number, int32 value, output) INL; + static inline uint8* WriteSFixed64ToArray( + field_number, int64 value, output) INL; + static inline uint8* WriteFloatToArray( + field_number, float value, output) INL; + static inline uint8* WriteDoubleToArray( + field_number, double value, output) INL; + static inline uint8* WriteBoolToArray( + field_number, bool value, output) INL; + static inline uint8* WriteEnumToArray( + field_number, int value, output) INL; + + static inline uint8* WriteStringToArray( + field_number, const string& value, output) INL; + static inline uint8* WriteBytesToArray( + field_number, const string& value, output) INL; + + static inline uint8* WriteGroupToArray( + field_number, const MessageLite& value, output) INL; + static inline uint8* WriteMessageToArray( + field_number, const MessageLite& value, output) INL; + + // Like above, but de-virtualize the call to SerializeWithCachedSizes(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override SerializeWithCachedSizes()). + template + static inline uint8* WriteGroupNoVirtualToArray( + field_number, const MessageType& value, output) INL; + template + static inline uint8* WriteMessageNoVirtualToArray( + field_number, const MessageType& value, output) INL; + +#undef output +#undef input +#undef INL + +#undef field_number + + // Compute the byte size of a field. The XxSize() functions do NOT include + // the tag, so you must also call TagSize(). (This is because, for repeated + // fields, you should only call TagSize() once and multiply it by the element + // count, but you may have to call XxSize() for each individual element.) + static inline int Int32Size ( int32 value); + static inline int Int64Size ( int64 value); + static inline int UInt32Size (uint32 value); + static inline int UInt64Size (uint64 value); + static inline int SInt32Size ( int32 value); + static inline int SInt64Size ( int64 value); + static inline int EnumSize ( int value); + + // These types always have the same size. + static const int kFixed32Size = 4; + static const int kFixed64Size = 8; + static const int kSFixed32Size = 4; + static const int kSFixed64Size = 8; + static const int kFloatSize = 4; + static const int kDoubleSize = 8; + static const int kBoolSize = 1; + + static inline int StringSize(const string& value); + static inline int BytesSize (const string& value); + + static inline int GroupSize (const MessageLite& value); + static inline int MessageSize(const MessageLite& value); + + // Like above, but de-virtualize the call to ByteSize(). The + // pointer must point at an instance of MessageType, *not* a subclass (or + // the subclass must not override ByteSize()). + template + static inline int GroupSizeNoVirtual (const MessageType& value); + template + static inline int MessageSizeNoVirtual(const MessageType& value); + + // Given the length of data, calculate the byte size of the data on the + // wire if we encode the data as a length delimited field. + static inline int LengthDelimitedSize(int length); + + private: + // A helper method for the repeated primitive reader. This method has + // optimizations for primitive types that have fixed size on the wire, and + // can be read using potentially faster paths. + template + static inline bool ReadRepeatedFixedSizePrimitive( + int tag_size, + uint32 tag, + google::protobuf::io::CodedInputStream* input, + RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + + static const CppType kFieldTypeToCppTypeMap[]; + static const WireFormatLite::WireType kWireTypeForFieldType[]; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite); +}; + +// A class which deals with unknown values. The default implementation just +// discards them. WireFormat defines a subclass which writes to an +// UnknownFieldSet. This class is used by ExtensionSet::ParseField(), since +// ExtensionSet is part of the lite library but UnknownFieldSet is not. +class LIBPROTOBUF_EXPORT FieldSkipper { + public: + FieldSkipper() {} + virtual ~FieldSkipper() {} + + // Skip a field whose tag has already been consumed. + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + + // Skip an entire message or group, up to an end-group tag (which is consumed) + // or end-of-stream. + virtual bool SkipMessage(io::CodedInputStream* input); + + // Deal with an already-parsed unrecognized enum value. The default + // implementation does nothing, but the UnknownFieldSet-based implementation + // saves it as an unknown varint. + virtual void SkipUnknownEnum(int field_number, int value); +}; + +// inline methods ==================================================== + +inline WireFormatLite::CppType +WireFormatLite::FieldTypeToCppType(FieldType type) { + return kFieldTypeToCppTypeMap[type]; +} + +inline uint32 WireFormatLite::MakeTag(int field_number, WireType type) { + return GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(field_number, type); +} + +inline WireFormatLite::WireType WireFormatLite::GetTagWireType(uint32 tag) { + return static_cast(tag & kTagTypeMask); +} + +inline int WireFormatLite::GetTagFieldNumber(uint32 tag) { + return static_cast(tag >> kTagTypeBits); +} + +inline int WireFormatLite::TagSize(int field_number, + WireFormatLite::FieldType type) { + int result = io::CodedOutputStream::VarintSize32( + field_number << kTagTypeBits); + if (type == TYPE_GROUP) { + // Groups have both a start and an end tag. + return result * 2; + } else { + return result; + } +} + +inline uint32 WireFormatLite::EncodeFloat(float value) { + union {float f; uint32 i;}; + f = value; + return i; +} + +inline float WireFormatLite::DecodeFloat(uint32 value) { + union {float f; uint32 i;}; + i = value; + return f; +} + +inline uint64 WireFormatLite::EncodeDouble(double value) { + union {double f; uint64 i;}; + f = value; + return i; +} + +inline double WireFormatLite::DecodeDouble(uint64 value) { + union {double f; uint64 i;}; + i = value; + return f; +} + +// ZigZag Transform: Encodes signed integers so that they can be +// effectively used with varint encoding. +// +// varint operates on unsigned integers, encoding smaller numbers into +// fewer bytes. If you try to use it on a signed integer, it will treat +// this number as a very large unsigned integer, which means that even +// small signed numbers like -1 will take the maximum number of bytes +// (10) to encode. ZigZagEncode() maps signed integers to unsigned +// in such a way that those with a small absolute value will have smaller +// encoded values, making them appropriate for encoding using varint. +// +// int32 -> uint32 +// ------------------------- +// 0 -> 0 +// -1 -> 1 +// 1 -> 2 +// -2 -> 3 +// ... -> ... +// 2147483647 -> 4294967294 +// -2147483648 -> 4294967295 +// +// >> encode >> +// << decode << + +inline uint32 WireFormatLite::ZigZagEncode32(int32 n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 31); +} + +inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { + return (n >> 1) ^ -static_cast(n & 1); +} + +inline uint64 WireFormatLite::ZigZagEncode64(int64 n) { + // Note: the right-shift must be arithmetic + return (n << 1) ^ (n >> 63); +} + +inline int64 WireFormatLite::ZigZagDecode64(uint64 n) { + return (n >> 1) ^ -static_cast(n & 1); +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite_inl.h b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite_inl.h new file mode 100644 index 000000000..89cb51bf9 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_lite_inl.h @@ -0,0 +1,776 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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) +// wink@google.com (Wink Saville) (refactored from wire_format.h) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ +#define GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ + +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace internal { + +// Implementation details of ReadPrimitive. + +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; + *value = static_cast(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + uint32* value) { + return input->ReadVarint32(value); +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + uint64* value) { + return input->ReadVarint64(value); +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = ZigZagDecode32(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; + *value = ZigZagDecode64(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + uint32* value) { + return input->ReadLittleEndian32(value); +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + uint64* value) { + return input->ReadLittleEndian64(value); +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int32* value) { + uint32 temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = static_cast(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int64* value) { + uint64 temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = static_cast(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + float* value) { + uint32 temp; + if (!input->ReadLittleEndian32(&temp)) return false; + *value = DecodeFloat(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + double* value) { + uint64 temp; + if (!input->ReadLittleEndian64(&temp)) return false; + *value = DecodeDouble(temp); + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + bool* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = temp != 0; + return true; +} +template <> +inline bool WireFormatLite::ReadPrimitive( + io::CodedInputStream* input, + int* value) { + uint32 temp; + if (!input->ReadVarint32(&temp)) return false; + *value = static_cast(temp); + return true; +} + +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + uint32, WireFormatLite::TYPE_FIXED32>( + const uint8* buffer, + uint32* value) { + return io::CodedInputStream::ReadLittleEndian32FromArray(buffer, value); +} +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + uint64, WireFormatLite::TYPE_FIXED64>( + const uint8* buffer, + uint64* value) { + return io::CodedInputStream::ReadLittleEndian64FromArray(buffer, value); +} +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + int32, WireFormatLite::TYPE_SFIXED32>( + const uint8* buffer, + int32* value) { + uint32 temp; + buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); + *value = static_cast(temp); + return buffer; +} +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + int64, WireFormatLite::TYPE_SFIXED64>( + const uint8* buffer, + int64* value) { + uint64 temp; + buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); + *value = static_cast(temp); + return buffer; +} +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + float, WireFormatLite::TYPE_FLOAT>( + const uint8* buffer, + float* value) { + uint32 temp; + buffer = io::CodedInputStream::ReadLittleEndian32FromArray(buffer, &temp); + *value = DecodeFloat(temp); + return buffer; +} +template <> +inline const uint8* WireFormatLite::ReadPrimitiveFromArray< + double, WireFormatLite::TYPE_DOUBLE>( + const uint8* buffer, + double* value) { + uint64 temp; + buffer = io::CodedInputStream::ReadLittleEndian64FromArray(buffer, &temp); + *value = DecodeDouble(temp); + return buffer; +} + +template +inline bool WireFormatLite::ReadRepeatedPrimitive(int, // tag_size, unused. + uint32 tag, + io::CodedInputStream* input, + RepeatedField* values) { + CType value; + if (!ReadPrimitive(input, &value)) return false; + values->Add(value); + int elements_already_reserved = values->Capacity() - values->size(); + while (elements_already_reserved > 0 && input->ExpectTag(tag)) { + if (!ReadPrimitive(input, &value)) return false; + values->AddAlreadyReserved(value); + elements_already_reserved--; + } + return true; +} + +template +inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( + int tag_size, + uint32 tag, + io::CodedInputStream* input, + RepeatedField* values) { + GOOGLE_DCHECK_EQ(UInt32Size(tag), tag_size); + CType value; + if (!ReadPrimitive(input, &value)) + return false; + values->Add(value); + + // For fixed size values, repeated values can be read more quickly by + // reading directly from a raw array. + // + // We can get a tight loop by only reading as many elements as can be + // added to the RepeatedField without having to do any resizing. Additionally, + // we only try to read as many elements as are available from the current + // buffer space. Doing so avoids having to perform boundary checks when + // reading the value: the maximum number of elements that can be read is + // known outside of the loop. + const void* void_pointer; + int size; + input->GetDirectBufferPointerInline(&void_pointer, &size); + if (size > 0) { + const uint8* buffer = reinterpret_cast(void_pointer); + // The number of bytes each type occupies on the wire. + const int per_value_size = tag_size + sizeof(value); + + int elements_available = min(values->Capacity() - values->size(), + size / per_value_size); + int num_read = 0; + while (num_read < elements_available && + (buffer = io::CodedInputStream::ExpectTagFromArray( + buffer, tag)) != NULL) { + buffer = ReadPrimitiveFromArray(buffer, &value); + values->AddAlreadyReserved(value); + ++num_read; + } + const int read_bytes = num_read * per_value_size; + if (read_bytes > 0) { + input->Skip(read_bytes); + } + } + return true; +} + +// Specializations of ReadRepeatedPrimitive for the fixed size types, which use +// the optimized code path. +#define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ +template <> \ +inline bool WireFormatLite::ReadRepeatedPrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + int tag_size, \ + uint32 tag, \ + io::CodedInputStream* input, \ + RepeatedField* values) { \ + return ReadRepeatedFixedSizePrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + tag_size, tag, input, values); \ +} + +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT) +READ_REPEATED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE) + +#undef READ_REPEATED_FIXED_SIZE_PRIMITIVE + +template +bool WireFormatLite::ReadRepeatedPrimitiveNoInline( + int tag_size, + uint32 tag, + io::CodedInputStream* input, + RepeatedField* value) { + return ReadRepeatedPrimitive( + tag_size, tag, input, value); +} + +template +inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, + RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + CType value; + if (!ReadPrimitive(input, &value)) return false; + values->Add(value); + } + input->PopLimit(limit); + return true; +} + +template +bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, + RepeatedField* values) { + return ReadPackedPrimitive(input, values); +} + + +inline bool WireFormatLite::ReadGroup(int field_number, + io::CodedInputStream* input, + MessageLite* value) { + if (!input->IncrementRecursionDepth()) return false; + if (!value->MergePartialFromCodedStream(input)) return false; + input->DecrementRecursionDepth(); + // Make sure the last thing read was an end tag for this group. + if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { + return false; + } + return true; +} +inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, + MessageLite* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->IncrementRecursionDepth()) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + if (!value->MergePartialFromCodedStream(input)) return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + if (!input->ConsumedEntireMessage()) return false; + input->PopLimit(limit); + input->DecrementRecursionDepth(); + return true; +} + +// We name the template parameter something long and extremely unlikely to occur +// elsewhere because a *qualified* member access expression designed to avoid +// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the +// name of the qualifying class to be looked up both in the context of the full +// expression (finding the template parameter) and in the context of the object +// whose member we are accessing. This could potentially find a nested type +// within that object. The standard goes on to require these names to refer to +// the same entity, which this collision would violate. The lack of a safe way +// to avoid this collision appears to be a defect in the standard, but until it +// is corrected, we choose the name to avoid accidental collisions. +template +inline bool WireFormatLite::ReadGroupNoVirtual( + int field_number, io::CodedInputStream* input, + MessageType_WorkAroundCppLookupDefect* value) { + if (!input->IncrementRecursionDepth()) return false; + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; + input->DecrementRecursionDepth(); + // Make sure the last thing read was an end tag for this group. + if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { + return false; + } + return true; +} +template +inline bool WireFormatLite::ReadMessageNoVirtual( + io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (!input->IncrementRecursionDepth()) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + if (!input->ConsumedEntireMessage()) return false; + input->PopLimit(limit); + input->DecrementRecursionDepth(); + return true; +} + +// =================================================================== + +inline void WireFormatLite::WriteTag(int field_number, WireType type, + io::CodedOutputStream* output) { + output->WriteTag(MakeTag(field_number, type)); +} + +inline void WireFormatLite::WriteInt32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} +inline void WireFormatLite::WriteInt64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(static_cast(value)); +} +inline void WireFormatLite::WriteUInt32NoTag(uint32 value, + io::CodedOutputStream* output) { + output->WriteVarint32(value); +} +inline void WireFormatLite::WriteUInt64NoTag(uint64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(value); +} +inline void WireFormatLite::WriteSInt32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteVarint32(ZigZagEncode32(value)); +} +inline void WireFormatLite::WriteSInt64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteVarint64(ZigZagEncode64(value)); +} +inline void WireFormatLite::WriteFixed32NoTag(uint32 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(value); +} +inline void WireFormatLite::WriteFixed64NoTag(uint64 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(value); +} +inline void WireFormatLite::WriteSFixed32NoTag(int32 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(static_cast(value)); +} +inline void WireFormatLite::WriteSFixed64NoTag(int64 value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(static_cast(value)); +} +inline void WireFormatLite::WriteFloatNoTag(float value, + io::CodedOutputStream* output) { + output->WriteLittleEndian32(EncodeFloat(value)); +} +inline void WireFormatLite::WriteDoubleNoTag(double value, + io::CodedOutputStream* output) { + output->WriteLittleEndian64(EncodeDouble(value)); +} +inline void WireFormatLite::WriteBoolNoTag(bool value, + io::CodedOutputStream* output) { + output->WriteVarint32(value ? 1 : 0); +} +inline void WireFormatLite::WriteEnumNoTag(int value, + io::CodedOutputStream* output) { + output->WriteVarint32SignExtended(value); +} + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline void WireFormatLite::WriteGroupNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_START_GROUP, output); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); + WriteTag(field_number, WIRETYPE_END_GROUP, output); +} +template +inline void WireFormatLite::WriteMessageNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); +} + +// =================================================================== + +inline uint8* WireFormatLite::WriteTagToArray(int field_number, + WireType type, + uint8* target) { + return io::CodedOutputStream::WriteTagToArray(MakeTag(field_number, type), + target); +} + +inline uint8* WireFormatLite::WriteInt32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} +inline uint8* WireFormatLite::WriteInt64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteUInt32NoTagToArray(uint32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt64NoTagToArray(uint64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(ZigZagEncode32(value), + target); +} +inline uint8* WireFormatLite::WriteSInt64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteVarint64ToArray(ZigZagEncode64(value), + target); +} +inline uint8* WireFormatLite::WriteFixed32NoTagToArray(uint32 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed64NoTagToArray(uint64 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed32NoTagToArray(int32 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteSFixed64NoTagToArray(int64 value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray( + static_cast(value), target); +} +inline uint8* WireFormatLite::WriteFloatNoTagToArray(float value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian32ToArray(EncodeFloat(value), + target); +} +inline uint8* WireFormatLite::WriteDoubleNoTagToArray(double value, + uint8* target) { + return io::CodedOutputStream::WriteLittleEndian64ToArray(EncodeDouble(value), + target); +} +inline uint8* WireFormatLite::WriteBoolNoTagToArray(bool value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32ToArray(value ? 1 : 0, target); +} +inline uint8* WireFormatLite::WriteEnumNoTagToArray(int value, + uint8* target) { + return io::CodedOutputStream::WriteVarint32SignExtendedToArray(value, target); +} + +inline uint8* WireFormatLite::WriteInt32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteInt64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt32ToArray(int field_number, + uint32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteUInt64ToArray(int field_number, + uint64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteUInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSInt64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteSInt64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed32ToArray(int field_number, + uint32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFixed32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFixed64ToArray(int field_number, + uint64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteFixed64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed32ToArray(int field_number, + int32 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteSFixed32NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteSFixed64ToArray(int field_number, + int64 value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteSFixed64NoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteFloatToArray(int field_number, + float value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED32, target); + return WriteFloatNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteDoubleToArray(int field_number, + double value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_FIXED64, target); + return WriteDoubleNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteBoolToArray(int field_number, + bool value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteBoolNoTagToArray(value, target); +} +inline uint8* WireFormatLite::WriteEnumToArray(int field_number, + int value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_VARINT, target); + return WriteEnumNoTagToArray(value, target); +} + +inline uint8* WireFormatLite::WriteStringToArray(int field_number, + const string& value, + uint8* target) { + // String is for UTF-8 text only + // WARNING: In wire_format.cc, both strings and bytes are handled by + // WriteString() to avoid code duplication. If the implementations become + // different, you will need to update that usage. + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); + return io::CodedOutputStream::WriteStringToArray(value, target); +} +inline uint8* WireFormatLite::WriteBytesToArray(int field_number, + const string& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); + return io::CodedOutputStream::WriteStringToArray(value, target); +} + + +inline uint8* WireFormatLite::WriteGroupToArray(int field_number, + const MessageLite& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value.SerializeWithCachedSizesToArray(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} +inline uint8* WireFormatLite::WriteMessageToArray(int field_number, + const MessageLite& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + value.GetCachedSize(), target); + return value.SerializeWithCachedSizesToArray(target); +} + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); + target = value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); + return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); +} +template +inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { + target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); + target = io::CodedOutputStream::WriteVarint32ToArray( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target); + return value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); +} + +// =================================================================== + +inline int WireFormatLite::Int32Size(int32 value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} +inline int WireFormatLite::Int64Size(int64 value) { + return io::CodedOutputStream::VarintSize64(static_cast(value)); +} +inline int WireFormatLite::UInt32Size(uint32 value) { + return io::CodedOutputStream::VarintSize32(value); +} +inline int WireFormatLite::UInt64Size(uint64 value) { + return io::CodedOutputStream::VarintSize64(value); +} +inline int WireFormatLite::SInt32Size(int32 value) { + return io::CodedOutputStream::VarintSize32(ZigZagEncode32(value)); +} +inline int WireFormatLite::SInt64Size(int64 value) { + return io::CodedOutputStream::VarintSize64(ZigZagEncode64(value)); +} +inline int WireFormatLite::EnumSize(int value) { + return io::CodedOutputStream::VarintSize32SignExtended(value); +} + +inline int WireFormatLite::StringSize(const string& value) { + return io::CodedOutputStream::VarintSize32(value.size()) + + value.size(); +} +inline int WireFormatLite::BytesSize(const string& value) { + return io::CodedOutputStream::VarintSize32(value.size()) + + value.size(); +} + + +inline int WireFormatLite::GroupSize(const MessageLite& value) { + return value.ByteSize(); +} +inline int WireFormatLite::MessageSize(const MessageLite& value) { + return LengthDelimitedSize(value.ByteSize()); +} + +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline int WireFormatLite::GroupSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return value.MessageType_WorkAroundCppLookupDefect::ByteSize(); +} +template +inline int WireFormatLite::MessageSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return LengthDelimitedSize( + value.MessageType_WorkAroundCppLookupDefect::ByteSize()); +} + +inline int WireFormatLite::LengthDelimitedSize(int length) { + return io::CodedOutputStream::VarintSize32(length) + length; +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_INL_H__ diff --git a/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_unittest.cc b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_unittest.cc new file mode 100644 index 000000000..9822828b1 --- /dev/null +++ b/modules/dnn/3rdparty/protobuf/src/google/protobuf/wire_format_unittest.cc @@ -0,0 +1,978 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST(WireFormatTest, EnumsInSync) { + // Verify that WireFormatLite::FieldType and WireFormatLite::CppType match + // FieldDescriptor::Type and FieldDescriptor::CppType. + + EXPECT_EQ(implicit_cast(FieldDescriptor::MAX_TYPE), + implicit_cast(WireFormatLite::MAX_FIELD_TYPE)); + EXPECT_EQ(implicit_cast(FieldDescriptor::MAX_CPPTYPE), + implicit_cast(WireFormatLite::MAX_CPPTYPE)); + + for (int i = 1; i <= WireFormatLite::MAX_FIELD_TYPE; i++) { + EXPECT_EQ( + implicit_cast(FieldDescriptor::TypeToCppType( + static_cast(i))), + implicit_cast(WireFormatLite::FieldTypeToCppType( + static_cast(i)))); + } +} + +TEST(WireFormatTest, MaxFieldNumber) { + // Make sure the max field number constant is accurate. + EXPECT_EQ((1 << (32 - WireFormatLite::kTagTypeBits)) - 1, + FieldDescriptor::kMaxNumber); +} + +TEST(WireFormatTest, Parse) { + unittest::TestAllTypes source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetAllFields(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectAllFieldsSet(dest); +} + +TEST(WireFormatTest, ParseExtensions) { + unittest::TestAllExtensions source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetAllExtensions(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectAllExtensionsSet(dest); +} + +TEST(WireFormatTest, ParsePacked) { + unittest::TestPackedTypes source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetPackedFields(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectPackedFieldsSet(dest); +} + +TEST(WireFormatTest, ParsePackedFromUnpacked) { + // Serialize using the generated code. + unittest::TestUnpackedTypes source; + TestUtil::SetUnpackedFields(&source); + string data = source.SerializeAsString(); + + // Parse using WireFormat. + unittest::TestPackedTypes dest; + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectPackedFieldsSet(dest); +} + +TEST(WireFormatTest, ParseUnpackedFromPacked) { + // Serialize using the generated code. + unittest::TestPackedTypes source; + TestUtil::SetPackedFields(&source); + string data = source.SerializeAsString(); + + // Parse using WireFormat. + unittest::TestUnpackedTypes dest; + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectUnpackedFieldsSet(dest); +} + +TEST(WireFormatTest, ParsePackedExtensions) { + unittest::TestPackedExtensions source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetPackedExtensions(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectPackedExtensionsSet(dest); +} + +TEST(WireFormatTest, ByteSize) { + unittest::TestAllTypes message; + TestUtil::SetAllFields(&message); + + EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message)); + message.Clear(); + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + +TEST(WireFormatTest, ByteSizeExtensions) { + unittest::TestAllExtensions message; + TestUtil::SetAllExtensions(&message); + + EXPECT_EQ(message.ByteSize(), + WireFormat::ByteSize(message)); + message.Clear(); + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + +TEST(WireFormatTest, ByteSizePacked) { + unittest::TestPackedTypes message; + TestUtil::SetPackedFields(&message); + + EXPECT_EQ(message.ByteSize(), WireFormat::ByteSize(message)); + message.Clear(); + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + +TEST(WireFormatTest, ByteSizePackedExtensions) { + unittest::TestPackedExtensions message; + TestUtil::SetPackedExtensions(&message); + + EXPECT_EQ(message.ByteSize(), + WireFormat::ByteSize(message)); + message.Clear(); + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + +TEST(WireFormatTest, Serialize) { + unittest::TestAllTypes message; + string generated_data; + string dynamic_data; + + TestUtil::SetAllFields(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); +} + +TEST(WireFormatTest, SerializeExtensions) { + unittest::TestAllExtensions message; + string generated_data; + string dynamic_data; + + TestUtil::SetAllExtensions(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); +} + +TEST(WireFormatTest, SerializeFieldsAndExtensions) { + unittest::TestFieldOrderings message; + string generated_data; + string dynamic_data; + + TestUtil::SetAllFieldsAndExtensions(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); + + // Should output in canonical order. + TestUtil::ExpectAllFieldsAndExtensionsInOrder(dynamic_data); + TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data); +} + +TEST(WireFormatTest, ParseMultipleExtensionRanges) { + // Make sure we can parse a message that contains multiple extensions ranges. + unittest::TestFieldOrderings source; + string data; + + TestUtil::SetAllFieldsAndExtensions(&source); + source.SerializeToString(&data); + + { + unittest::TestFieldOrderings dest; + EXPECT_TRUE(dest.ParseFromString(data)); + EXPECT_EQ(source.DebugString(), dest.DebugString()); + } + + // Also test using reflection-based parsing. + { + unittest::TestFieldOrderings dest; + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream coded_input(&raw_input); + EXPECT_TRUE(WireFormat::ParseAndMergePartial(&coded_input, &dest)); + EXPECT_EQ(source.DebugString(), dest.DebugString()); + } +} + +const int kUnknownTypeId = 1550055; + +TEST(WireFormatTest, SerializeMessageSet) { + // Set up a TestMessageSet with two known messages and an unknown one. + unittest::TestMessageSet message_set; + message_set.MutableExtension( + unittest::TestMessageSetExtension1::message_set_extension)->set_i(123); + message_set.MutableExtension( + unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo"); + message_set.mutable_unknown_fields()->AddLengthDelimited( + kUnknownTypeId, "bar"); + + string data; + ASSERT_TRUE(message_set.SerializeToString(&data)); + + // Parse back using RawMessageSet and check the contents. + unittest::RawMessageSet raw; + ASSERT_TRUE(raw.ParseFromString(data)); + + EXPECT_EQ(0, raw.unknown_fields().field_count()); + + ASSERT_EQ(3, raw.item_size()); + EXPECT_EQ( + unittest::TestMessageSetExtension1::descriptor()->extension(0)->number(), + raw.item(0).type_id()); + EXPECT_EQ( + unittest::TestMessageSetExtension2::descriptor()->extension(0)->number(), + raw.item(1).type_id()); + EXPECT_EQ(kUnknownTypeId, raw.item(2).type_id()); + + unittest::TestMessageSetExtension1 message1; + EXPECT_TRUE(message1.ParseFromString(raw.item(0).message())); + EXPECT_EQ(123, message1.i()); + + unittest::TestMessageSetExtension2 message2; + EXPECT_TRUE(message2.ParseFromString(raw.item(1).message())); + EXPECT_EQ("foo", message2.str()); + + EXPECT_EQ("bar", raw.item(2).message()); +} + +TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) { + // Serialize a MessageSet to a stream and to a flat array using generated + // code, and also using WireFormat, and check that the results are equal. + // Set up a TestMessageSet with two known messages and an unknown one, as + // above. + + unittest::TestMessageSet message_set; + message_set.MutableExtension( + unittest::TestMessageSetExtension1::message_set_extension)->set_i(123); + message_set.MutableExtension( + unittest::TestMessageSetExtension2::message_set_extension)->set_str("foo"); + message_set.mutable_unknown_fields()->AddLengthDelimited( + kUnknownTypeId, "bar"); + + int size = message_set.ByteSize(); + EXPECT_EQ(size, message_set.GetCachedSize()); + ASSERT_EQ(size, WireFormat::ByteSize(message_set)); + + string flat_data; + string stream_data; + string dynamic_data; + flat_data.resize(size); + stream_data.resize(size); + + // Serialize to flat array + { + uint8* target = reinterpret_cast(string_as_array(&flat_data)); + uint8* end = message_set.SerializeWithCachedSizesToArray(target); + EXPECT_EQ(size, end - target); + } + + // Serialize to buffer + { + io::ArrayOutputStream array_stream(string_as_array(&stream_data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message_set.SerializeWithCachedSizes(&output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + + // Serialize to buffer with WireFormat. + { + io::StringOutputStream string_stream(&dynamic_data); + io::CodedOutputStream output_stream(&string_stream); + WireFormat::SerializeWithCachedSizes(message_set, size, &output_stream); + ASSERT_FALSE(output_stream.HadError()); + } + + EXPECT_TRUE(flat_data == stream_data); + EXPECT_TRUE(flat_data == dynamic_data); +} + +TEST(WireFormatTest, ParseMessageSet) { + // Set up a RawMessageSet with two known messages and an unknown one. + unittest::RawMessageSet raw; + + { + unittest::RawMessageSet::Item* item = raw.add_item(); + item->set_type_id( + unittest::TestMessageSetExtension1::descriptor()->extension(0)->number()); + unittest::TestMessageSetExtension1 message; + message.set_i(123); + message.SerializeToString(item->mutable_message()); + } + + { + unittest::RawMessageSet::Item* item = raw.add_item(); + item->set_type_id( + unittest::TestMessageSetExtension2::descriptor()->extension(0)->number()); + unittest::TestMessageSetExtension2 message; + message.set_str("foo"); + message.SerializeToString(item->mutable_message()); + } + + { + unittest::RawMessageSet::Item* item = raw.add_item(); + item->set_type_id(kUnknownTypeId); + item->set_message("bar"); + } + + string data; + ASSERT_TRUE(raw.SerializeToString(&data)); + + // Parse as a TestMessageSet and check the contents. + unittest::TestMessageSet message_set; + ASSERT_TRUE(message_set.ParseFromString(data)); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + EXPECT_EQ("foo", message_set.GetExtension( + unittest::TestMessageSetExtension2::message_set_extension).str()); + + ASSERT_EQ(1, message_set.unknown_fields().field_count()); + ASSERT_EQ(UnknownField::TYPE_LENGTH_DELIMITED, + message_set.unknown_fields().field(0).type()); + EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited()); + + // Also parse using WireFormat. + unittest::TestMessageSet dynamic_message_set; + io::CodedInputStream input(reinterpret_cast(data.data()), + data.size()); + ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set)); + EXPECT_EQ(message_set.DebugString(), dynamic_message_set.DebugString()); +} + +TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) { + string data; + { + unittest::TestMessageSetExtension1 message; + message.set_i(123); + // Build a MessageSet manually with its message content put before its + // type_id. + io::StringOutputStream output_stream(&data); + io::CodedOutputStream coded_output(&output_stream); + coded_output.WriteTag(WireFormatLite::kMessageSetItemStartTag); + // Write the message content first. + WireFormatLite::WriteTag(WireFormatLite::kMessageSetMessageNumber, + WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + &coded_output); + coded_output.WriteVarint32(message.ByteSize()); + message.SerializeWithCachedSizes(&coded_output); + // Write the type id. + uint32 type_id = message.GetDescriptor()->extension(0)->number(); + WireFormatLite::WriteUInt32(WireFormatLite::kMessageSetTypeIdNumber, + type_id, &coded_output); + coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag); + } + { + unittest::TestMessageSet message_set; + ASSERT_TRUE(message_set.ParseFromString(data)); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } + { + // Test parse the message via Reflection. + unittest::TestMessageSet message_set; + io::CodedInputStream input( + reinterpret_cast(data.data()), data.size()); + EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set)); + EXPECT_TRUE(input.ConsumedEntireMessage()); + + EXPECT_EQ(123, message_set.GetExtension( + unittest::TestMessageSetExtension1::message_set_extension).i()); + } +} + +TEST(WireFormatTest, ParseBrokenMessageSet) { + unittest::TestMessageSet message_set; + string input("goodbye"); // Invalid wire format data. + EXPECT_FALSE(message_set.ParseFromString(input)); +} + +TEST(WireFormatTest, RecursionLimit) { + unittest::TestRecursiveMessage message; + message.mutable_a()->mutable_a()->mutable_a()->mutable_a()->set_i(1); + string data; + message.SerializeToString(&data); + + { + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetRecursionLimit(4); + unittest::TestRecursiveMessage message2; + EXPECT_TRUE(message2.ParseFromCodedStream(&input)); + } + + { + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetRecursionLimit(3); + unittest::TestRecursiveMessage message2; + EXPECT_FALSE(message2.ParseFromCodedStream(&input)); + } +} + +TEST(WireFormatTest, UnknownFieldRecursionLimit) { + unittest::TestEmptyMessage message; + message.mutable_unknown_fields() + ->AddGroup(1234) + ->AddGroup(1234) + ->AddGroup(1234) + ->AddGroup(1234) + ->AddVarint(1234, 123); + string data; + message.SerializeToString(&data); + + { + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetRecursionLimit(4); + unittest::TestEmptyMessage message2; + EXPECT_TRUE(message2.ParseFromCodedStream(&input)); + } + + { + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + input.SetRecursionLimit(3); + unittest::TestEmptyMessage message2; + EXPECT_FALSE(message2.ParseFromCodedStream(&input)); + } +} + +TEST(WireFormatTest, ZigZag) { +// avoid line-wrapping +#define LL(x) GOOGLE_LONGLONG(x) +#define ULL(x) GOOGLE_ULONGLONG(x) +#define ZigZagEncode32(x) WireFormatLite::ZigZagEncode32(x) +#define ZigZagDecode32(x) WireFormatLite::ZigZagDecode32(x) +#define ZigZagEncode64(x) WireFormatLite::ZigZagEncode64(x) +#define ZigZagDecode64(x) WireFormatLite::ZigZagDecode64(x) + + EXPECT_EQ(0u, ZigZagEncode32( 0)); + EXPECT_EQ(1u, ZigZagEncode32(-1)); + EXPECT_EQ(2u, ZigZagEncode32( 1)); + EXPECT_EQ(3u, ZigZagEncode32(-2)); + EXPECT_EQ(0x7FFFFFFEu, ZigZagEncode32(0x3FFFFFFF)); + EXPECT_EQ(0x7FFFFFFFu, ZigZagEncode32(0xC0000000)); + EXPECT_EQ(0xFFFFFFFEu, ZigZagEncode32(0x7FFFFFFF)); + EXPECT_EQ(0xFFFFFFFFu, ZigZagEncode32(0x80000000)); + + EXPECT_EQ( 0, ZigZagDecode32(0u)); + EXPECT_EQ(-1, ZigZagDecode32(1u)); + EXPECT_EQ( 1, ZigZagDecode32(2u)); + EXPECT_EQ(-2, ZigZagDecode32(3u)); + EXPECT_EQ(0x3FFFFFFF, ZigZagDecode32(0x7FFFFFFEu)); + EXPECT_EQ(0xC0000000, ZigZagDecode32(0x7FFFFFFFu)); + EXPECT_EQ(0x7FFFFFFF, ZigZagDecode32(0xFFFFFFFEu)); + EXPECT_EQ(0x80000000, ZigZagDecode32(0xFFFFFFFFu)); + + EXPECT_EQ(0u, ZigZagEncode64( 0)); + EXPECT_EQ(1u, ZigZagEncode64(-1)); + EXPECT_EQ(2u, ZigZagEncode64( 1)); + EXPECT_EQ(3u, ZigZagEncode64(-2)); + EXPECT_EQ(ULL(0x000000007FFFFFFE), ZigZagEncode64(LL(0x000000003FFFFFFF))); + EXPECT_EQ(ULL(0x000000007FFFFFFF), ZigZagEncode64(LL(0xFFFFFFFFC0000000))); + EXPECT_EQ(ULL(0x00000000FFFFFFFE), ZigZagEncode64(LL(0x000000007FFFFFFF))); + EXPECT_EQ(ULL(0x00000000FFFFFFFF), ZigZagEncode64(LL(0xFFFFFFFF80000000))); + EXPECT_EQ(ULL(0xFFFFFFFFFFFFFFFE), ZigZagEncode64(LL(0x7FFFFFFFFFFFFFFF))); + EXPECT_EQ(ULL(0xFFFFFFFFFFFFFFFF), ZigZagEncode64(LL(0x8000000000000000))); + + EXPECT_EQ( 0, ZigZagDecode64(0u)); + EXPECT_EQ(-1, ZigZagDecode64(1u)); + EXPECT_EQ( 1, ZigZagDecode64(2u)); + EXPECT_EQ(-2, ZigZagDecode64(3u)); + EXPECT_EQ(LL(0x000000003FFFFFFF), ZigZagDecode64(ULL(0x000000007FFFFFFE))); + EXPECT_EQ(LL(0xFFFFFFFFC0000000), ZigZagDecode64(ULL(0x000000007FFFFFFF))); + EXPECT_EQ(LL(0x000000007FFFFFFF), ZigZagDecode64(ULL(0x00000000FFFFFFFE))); + EXPECT_EQ(LL(0xFFFFFFFF80000000), ZigZagDecode64(ULL(0x00000000FFFFFFFF))); + EXPECT_EQ(LL(0x7FFFFFFFFFFFFFFF), ZigZagDecode64(ULL(0xFFFFFFFFFFFFFFFE))); + EXPECT_EQ(LL(0x8000000000000000), ZigZagDecode64(ULL(0xFFFFFFFFFFFFFFFF))); + + // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) + // were chosen semi-randomly via keyboard bashing. + EXPECT_EQ( 0, ZigZagDecode32(ZigZagEncode32( 0))); + EXPECT_EQ( 1, ZigZagDecode32(ZigZagEncode32( 1))); + EXPECT_EQ( -1, ZigZagDecode32(ZigZagEncode32( -1))); + EXPECT_EQ(14927, ZigZagDecode32(ZigZagEncode32(14927))); + EXPECT_EQ(-3612, ZigZagDecode32(ZigZagEncode32(-3612))); + + EXPECT_EQ( 0, ZigZagDecode64(ZigZagEncode64( 0))); + EXPECT_EQ( 1, ZigZagDecode64(ZigZagEncode64( 1))); + EXPECT_EQ( -1, ZigZagDecode64(ZigZagEncode64( -1))); + EXPECT_EQ(14927, ZigZagDecode64(ZigZagEncode64(14927))); + EXPECT_EQ(-3612, ZigZagDecode64(ZigZagEncode64(-3612))); + + EXPECT_EQ(LL(856912304801416), ZigZagDecode64(ZigZagEncode64( + LL(856912304801416)))); + EXPECT_EQ(LL(-75123905439571256), ZigZagDecode64(ZigZagEncode64( + LL(-75123905439571256)))); +} + +TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) { + // At one point checks would trigger when parsing repeated fixed scalar + // fields. + protobuf_unittest::TestRepeatedScalarDifferentTagSizes msg1, msg2; + for (int i = 0; i < 100; ++i) { + msg1.add_repeated_fixed32(i); + msg1.add_repeated_int32(i); + msg1.add_repeated_fixed64(i); + msg1.add_repeated_int64(i); + msg1.add_repeated_float(i); + msg1.add_repeated_uint64(i); + } + + // Make sure that we have a variety of tag sizes. + const google::protobuf::Descriptor* desc = msg1.GetDescriptor(); + const google::protobuf::FieldDescriptor* field; + field = desc->FindFieldByName("repeated_fixed32"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type())); + field = desc->FindFieldByName("repeated_int32"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(1, WireFormat::TagSize(field->number(), field->type())); + field = desc->FindFieldByName("repeated_fixed64"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type())); + field = desc->FindFieldByName("repeated_int64"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(2, WireFormat::TagSize(field->number(), field->type())); + field = desc->FindFieldByName("repeated_float"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type())); + field = desc->FindFieldByName("repeated_uint64"); + ASSERT_TRUE(field != NULL); + ASSERT_EQ(3, WireFormat::TagSize(field->number(), field->type())); + + EXPECT_TRUE(msg2.ParseFromString(msg1.SerializeAsString())); + EXPECT_EQ(msg1.DebugString(), msg2.DebugString()); +} + +class WireFormatInvalidInputTest : public testing::Test { + protected: + // Make a serialized TestAllTypes in which the field optional_nested_message + // contains exactly the given bytes, which may be invalid. + string MakeInvalidEmbeddedMessage(const char* bytes, int size) { + const FieldDescriptor* field = + unittest::TestAllTypes::descriptor()->FindFieldByName( + "optional_nested_message"); + GOOGLE_CHECK(field != NULL); + + string result; + + { + io::StringOutputStream raw_output(&result); + io::CodedOutputStream output(&raw_output); + + WireFormatLite::WriteBytes(field->number(), string(bytes, size), &output); + } + + return result; + } + + // Make a serialized TestAllTypes in which the field optionalgroup + // contains exactly the given bytes -- which may be invalid -- and + // possibly no end tag. + string MakeInvalidGroup(const char* bytes, int size, bool include_end_tag) { + const FieldDescriptor* field = + unittest::TestAllTypes::descriptor()->FindFieldByName( + "optionalgroup"); + GOOGLE_CHECK(field != NULL); + + string result; + + { + io::StringOutputStream raw_output(&result); + io::CodedOutputStream output(&raw_output); + + output.WriteVarint32(WireFormat::MakeTag(field)); + output.WriteString(string(bytes, size)); + if (include_end_tag) { + output.WriteVarint32(WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_END_GROUP)); + } + } + + return result; + } +}; + +TEST_F(WireFormatInvalidInputTest, InvalidSubMessage) { + unittest::TestAllTypes message; + + // Control case. + EXPECT_TRUE(message.ParseFromString(MakeInvalidEmbeddedMessage("", 0))); + + // The byte is a valid varint, but not a valid tag (zero). + EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\0", 1))); + + // The byte is a malformed varint. + EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\200", 1))); + + // The byte is an endgroup tag, but we aren't parsing a group. + EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\014", 1))); + + // The byte is a valid varint but not a valid tag (bad wire type). + EXPECT_FALSE(message.ParseFromString(MakeInvalidEmbeddedMessage("\017", 1))); +} + +TEST_F(WireFormatInvalidInputTest, InvalidGroup) { + unittest::TestAllTypes message; + + // Control case. + EXPECT_TRUE(message.ParseFromString(MakeInvalidGroup("", 0, true))); + + // Missing end tag. Groups cannot end at EOF. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("", 0, false))); + + // The byte is a valid varint, but not a valid tag (zero). + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\0", 1, false))); + + // The byte is a malformed varint. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\200", 1, false))); + + // The byte is an endgroup tag, but not the right one for this group. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\014", 1, false))); + + // The byte is a valid varint but not a valid tag (bad wire type). + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\017", 1, true))); +} + +TEST_F(WireFormatInvalidInputTest, InvalidUnknownGroup) { + // Use TestEmptyMessage so that the group made by MakeInvalidGroup will not + // be a known tag number. + unittest::TestEmptyMessage message; + + // Control case. + EXPECT_TRUE(message.ParseFromString(MakeInvalidGroup("", 0, true))); + + // Missing end tag. Groups cannot end at EOF. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("", 0, false))); + + // The byte is a valid varint, but not a valid tag (zero). + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\0", 1, false))); + + // The byte is a malformed varint. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\200", 1, false))); + + // The byte is an endgroup tag, but not the right one for this group. + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\014", 1, false))); + + // The byte is a valid varint but not a valid tag (bad wire type). + EXPECT_FALSE(message.ParseFromString(MakeInvalidGroup("\017", 1, true))); +} + +TEST_F(WireFormatInvalidInputTest, InvalidStringInUnknownGroup) { + // Test a bug fix: SkipMessage should fail if the message contains a string + // whose length would extend beyond the message end. + + unittest::TestAllTypes message; + message.set_optional_string("foo foo foo foo"); + string data; + message.SerializeToString(&data); + + // Chop some bytes off the end. + data.resize(data.size() - 4); + + // Try to skip it. Note that the bug was only present when parsing to an + // UnknownFieldSet. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream coded_input(&raw_input); + UnknownFieldSet unknown_fields; + EXPECT_FALSE(WireFormat::SkipMessage(&coded_input, &unknown_fields)); +} + +// Test differences between string and bytes. +// Value of a string type must be valid UTF-8 string. When UTF-8 +// validation is enabled (GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED): +// WriteInvalidUTF8String: see error message. +// ReadInvalidUTF8String: see error message. +// WriteValidUTF8String: fine. +// ReadValidUTF8String: fine. +// WriteAnyBytes: fine. +// ReadAnyBytes: fine. +const char * kInvalidUTF8String = "Invalid UTF-8: \xA0\xB0\xC0\xD0"; +// This used to be "Valid UTF-8: \x01\x02\u8C37\u6B4C", but MSVC seems to +// interpret \u differently from GCC. +const char * kValidUTF8String = "Valid UTF-8: \x01\x02\350\260\267\346\255\214"; + +template +bool WriteMessage(const char *value, T *message, string *wire_buffer) { + message->set_data(value); + wire_buffer->clear(); + message->AppendToString(wire_buffer); + return (wire_buffer->size() > 0); +} + +template +bool ReadMessage(const string &wire_buffer, T *message) { + return message->ParseFromArray(wire_buffer.data(), wire_buffer.size()); +} + +bool StartsWith(const string& s, const string& prefix) { + return s.substr(0, prefix.length()) == prefix; +} + +TEST(Utf8ValidationTest, WriteInvalidUTF8String) { + string wire_buffer; + protobuf_unittest::OneString input; + vector errors; + { + ScopedMemoryLog log; + WriteMessage(kInvalidUTF8String, &input, &wire_buffer); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(1, errors.size()); + EXPECT_TRUE(StartsWith(errors[0], + "String field contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); +#else + ASSERT_EQ(0, errors.size()); +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED +} + +TEST(Utf8ValidationTest, ReadInvalidUTF8String) { + string wire_buffer; + protobuf_unittest::OneString input; + WriteMessage(kInvalidUTF8String, &input, &wire_buffer); + protobuf_unittest::OneString output; + vector errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(1, errors.size()); + EXPECT_TRUE(StartsWith(errors[0], + "String field contains invalid UTF-8 data when " + "parsing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); + +#else + ASSERT_EQ(0, errors.size()); +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED +} + +TEST(Utf8ValidationTest, WriteValidUTF8String) { + string wire_buffer; + protobuf_unittest::OneString input; + vector errors; + { + ScopedMemoryLog log; + WriteMessage(kValidUTF8String, &input, &wire_buffer); + errors = log.GetMessages(ERROR); + } + ASSERT_EQ(0, errors.size()); +} + +TEST(Utf8ValidationTest, ReadValidUTF8String) { + string wire_buffer; + protobuf_unittest::OneString input; + WriteMessage(kValidUTF8String, &input, &wire_buffer); + protobuf_unittest::OneString output; + vector errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } + ASSERT_EQ(0, errors.size()); + EXPECT_EQ(input.data(), output.data()); +} + +// Bytes: anything can pass as bytes, use invalid UTF-8 string to test +TEST(Utf8ValidationTest, WriteArbitraryBytes) { + string wire_buffer; + protobuf_unittest::OneBytes input; + vector errors; + { + ScopedMemoryLog log; + WriteMessage(kInvalidUTF8String, &input, &wire_buffer); + errors = log.GetMessages(ERROR); + } + ASSERT_EQ(0, errors.size()); +} + +TEST(Utf8ValidationTest, ReadArbitraryBytes) { + string wire_buffer; + protobuf_unittest::OneBytes input; + WriteMessage(kInvalidUTF8String, &input, &wire_buffer); + protobuf_unittest::OneBytes output; + vector errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } + ASSERT_EQ(0, errors.size()); + EXPECT_EQ(input.data(), output.data()); +} + +TEST(Utf8ValidationTest, ParseRepeatedString) { + protobuf_unittest::MoreBytes input; + input.add_data(kValidUTF8String); + input.add_data(kInvalidUTF8String); + input.add_data(kInvalidUTF8String); + string wire_buffer = input.SerializeAsString(); + + protobuf_unittest::MoreString output; + vector errors; + { + ScopedMemoryLog log; + ReadMessage(wire_buffer, &output); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(2, errors.size()); +#else + ASSERT_EQ(0, errors.size()); +#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + EXPECT_EQ(wire_buffer, output.SerializeAsString()); +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt new file mode 100644 index 000000000..c2fdea927 --- /dev/null +++ b/modules/dnn/CMakeLists.txt @@ -0,0 +1,61 @@ +cmake_minimum_required(VERSION 2.8) +set(the_description "Deep neural network module. It allows to load models from different frameworks and to make forward pass") +set(OPENCV_MODULE_IS_PART_OF_WORLD OFF) + +ocv_add_module(dnn opencv_core opencv_imgproc WRAP python matlab) +ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-shadow -Wno-parentheses -Wmaybe-uninitialized -Wsign-promo -Wmissing-declarations -Wmissing-prototypes) +ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4701) + +# ---------------------------------------------------------------------------- +# Resolve libprotobuf dependency +# ---------------------------------------------------------------------------- +include(cmake/OpenCVFindLibProtobuf.cmake) +ocv_glob_module_sources(${PROTOBUF_SRCS} ${PROTOBUF_HDRS}) +ocv_source_group("Src\\protobuf" FILES ${PROTOBUF_SRCS} ${PROTOBUF_HDRS}) +ocv_module_include_directories(include ${PROTOBUF_INCLUDE_DIR}) + +ocv_create_module(${PROTOBUF_LIBRARIES}) +ocv_add_samples() +ocv_add_accuracy_tests() +ocv_add_perf_tests() + +# ---------------------------------------------------------------------------- +# Download pre-trained models for complex testing on GoogLeNet and AlexNet +# ---------------------------------------------------------------------------- +OCV_OPTION(${the_module}_DOWNLOAD_CAFFE_MODELS "Use GoogLeNet Caffe model for testing" ON IF BUILD_TESTS AND PYTHON2_EXECUTABLE AND DEFINED ENV{OPENCV_TEST_DATA_PATH}) +if(BUILD_TESTS AND ${the_module}_DOWNLOAD_CAFFE_MODELS) + add_custom_command( TARGET opencv_test_${name} POST_BUILD + COMMAND ${PYTHON2_EXECUTABLE} download_model.py test_models.json + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts ) + add_definitions(-DENABLE_CAFFE_MODEL_TESTS=1) +endif() + +# ---------------------------------------------------------------------------- +# Torch7 importer of blobs and models, produced by Torch.nn module +# ---------------------------------------------------------------------------- +OCV_OPTION(${the_module}_BUILD_TORCH_IMPORTER "Build Torch model importer (experimental functionality!)" OFF) +if(${the_module}_BUILD_TORCH_IMPORTER) + add_definitions(-DENABLE_TORCH_IMPORTER=1) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4702 /wd4127 /wd4267) #supress warnings in original torch files +endif() + +# ---------------------------------------------------------------------------- +# Generating test data for Torch importer +# ---------------------------------------------------------------------------- +OCV_OPTION(${the_module}_BUILD_TORCH_TESTS "Build Torch tests (installed torch7 with nn module is required)" ON IF BUILD_TESTS AND ${the_module}_BUILD_TORCH_IMPORTER) +if(${the_module}_BUILD_TORCH_TESTS) + + if(NOT DEFINED ENV{OPENCV_TEST_DATA_PATH}) + message(FATAL_ERROR "OPENCV_TEST_DATA_PATH environment variable was not specified") + endif() + + execute_process(COMMAND th ${CMAKE_CURRENT_SOURCE_DIR}/testdata/dnn/torch/torch_nn_echo.lua RESULT_VARIABLE TORCH_STATUS) + if(TORCH_STATUS) + message(FATAL_ERROR "Torch executable \"th\" not found (status: ${TORCH_STATUS}) or nn module not found") + endif() + + add_custom_command( TARGET opencv_test_${name} POST_BUILD + COMMAND th ${CMAKE_CURRENT_SOURCE_DIR}/testdata/dnn/torch/torch_gen_test_data.lua + WORKING_DIRECTORY $ENV{OPENCV_TEST_DATA_PATH}/dnn/torch ) + add_definitions(-DENABLE_TORCH_TESTS=1) +endif() \ No newline at end of file diff --git a/modules/dnn/README.md b/modules/dnn/README.md new file mode 100644 index 000000000..6e7e9c408 --- /dev/null +++ b/modules/dnn/README.md @@ -0,0 +1,2 @@ +Deep Neural Network module +========================== \ No newline at end of file diff --git a/modules/dnn/cmake/OpenCVFindLibProtobuf.cmake b/modules/dnn/cmake/OpenCVFindLibProtobuf.cmake new file mode 100644 index 000000000..b6a038cde --- /dev/null +++ b/modules/dnn/cmake/OpenCVFindLibProtobuf.cmake @@ -0,0 +1,43 @@ +OCV_OPTION(BUILD_LIBPROTOBUF_FROM_SOURCES "Force to build libprotobuf from sources (don't try to find it in system)" OFF) + +if(NOT BUILD_LIBPROTOBUF_FROM_SOURCES) + find_package(Protobuf) +endif() + +if(NOT BUILD_LIBPROTOBUF_FROM_SOURCES AND PROTOBUF_FOUND AND EXISTS ${PROTOBUF_PROTOC_EXECUTABLE}) + message(STATUS "The protocol buffer compiler and libprotobuf were found") + PROTOBUF_GENERATE_CPP(PROTOBUF_HDRS PROTOBUF_SRCS src/caffe/caffe.proto) + add_definitions(-DHAVE_PROTOBUF=1) +else() + message(STATUS "Build libprotobuf from sources:") + if(NOT PROTOBUF_FOUND) + message(STATUS " libprotobuf not found into system") + endif() + if(NOT EXISTS ${PROTOBUF_PROTOC_EXECUTABLE}) + message(STATUS " The protocol buffer compiler not found") + endif() + + #take into account OpenCV two-pass module addition scheme + if(NOT OPENCV_INITIAL_PASS) #TODO: it looks like a hack + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/protobuf) + endif() + + set(PROTOBUF_LIBRARIES libprotobuf) + set(PROTOBUF_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/protobuf/src ${CMAKE_CURRENT_BINARY_DIR}) + set(PROTOBUF_SRCS ${CMAKE_CURRENT_BINARY_DIR}/caffe.pb.cc) + set(PROTOBUF_HDRS ${CMAKE_CURRENT_BINARY_DIR}/caffe.pb.h) + add_definitions(-DHAVE_PROTOBUF=1) + + add_custom_command( + OUTPUT ${PROTOBUF_SRCS} ${PROTOBUF_HDRS} + COMMAND ${CMAKE_COMMAND} -E tar xzf ${CMAKE_CURRENT_SOURCE_DIR}/src/caffe/compiled/caffe.tar.gz + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Unpacking compiled caffe protobuf files" + VERBATIM + ) + set_source_files_properties(${PROTOBUF_SRCS} ${PROTOBUF_HDRS} PROPERTIES GENERATED TRUE) + + #supress warnings in autogenerated caffe.pb.* files + ocv_warnings_disable(CMAKE_CXX_FLAGS -Wunused-parameter) + ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4125 /wd4267 /wd4127 /wd4244 /wd4512 /wd4702) +endif() \ No newline at end of file diff --git a/modules/dnn/include/opencv2/dnn.hpp b/modules/dnn/include/opencv2/dnn.hpp new file mode 100644 index 000000000..37be98926 --- /dev/null +++ b/modules/dnn/include/opencv2/dnn.hpp @@ -0,0 +1,64 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_HPP__ +#define __OPENCV_DNN_HPP__ + +// This is an umbrealla header to include into you project. +// We are free to change headers layout in dnn subfolder, so please include +// this header for future compartibility + + +/** @defgroup dnn Deep Neural Network module + @{ + This module contains: + - API for new layers creation, layers are building bricks of neural networks; + - set of built-in most-useful Layers; + - API to constuct and modify comprehensive neural networks from layers; + - functionality for loading serialized networks models from differnet frameworks. + + Functionality of this module is designed only for forward pass computations (i. e. network testing). + A network training is in principle not supported. + @} +*/ +#include + +#endif /* __OPENCV_DNN_HPP__ */ diff --git a/modules/dnn/include/opencv2/dnn/blob.hpp b/modules/dnn/include/opencv2/dnn/blob.hpp new file mode 100644 index 000000000..bc582c83b --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/blob.hpp @@ -0,0 +1,238 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_DNN_BLOB_HPP__ +#define __OPENCV_DNN_DNN_BLOB_HPP__ +#include +#include +#include + +namespace cv +{ +namespace dnn +{ +//! @addtogroup dnn +//! @{ + + /** @brief Lightweight class for storing and processing a shape of blob (or anything else). */ + struct BlobShape + { + explicit BlobShape(int ndims = 4, int fill = 1); //!< Creates n-dim shape and fill its by @p fill + BlobShape(int num, int cn, int rows, int cols); //!< Creates 4-dim shape [@p num, @p cn, @p rows, @p cols] + BlobShape(int ndims, const int *sizes); //!< Creates n-dim shape from the @p sizes array + BlobShape(const std::vector &sizes); //!< Creates n-dim shape from the @p sizes vector + template + BlobShape(const Vec &shape); //!< Creates n-dim shape from @ref cv::Vec + + /** @brief Returns number of dimensions. */ + int dims() const; + + /** @brief Returns reference to the size of the specified @p axis. + * + * Negative @p axis is supported, in this case a counting starts from the last axis, + * i. e. -1 corresponds to last axis. + * If non-existing axis was passed then an error will be generated. + */ + int &size(int axis); + + /** @brief Returns the size of the specified @p axis. + * @see size() + */ + int size(int axis) const; + + int operator[](int axis) const; //!< Does the same thing as size(axis). + int &operator[](int axis); //!< Does the same thing as size(int) const. + + /** @brief Returns the size of the specified @p axis. + * + * Does the same thing as size(int) const, but if non-existing axis will be passed then 1 will be returned, + * therefore this function always finishes successfully. + */ + int xsize(int axis) const; + + /** @brief Returns the product of all sizes of axes. */ + ptrdiff_t total(); + + /** @brief Returns pointer to the first element of continuous size array. */ + const int *ptr() const; + + /** @brief Checks equality of two shapes. */ + bool equal(const BlobShape &other) const; + + bool operator== (const BlobShape &r) const; + + private: + cv::AutoBuffer sz; + }; + + + /** @brief This class provides methods for continuous n-dimensional CPU and GPU array processing. + * + * The class is realized as a wrapper over @ref cv::Mat and @ref cv::UMat. + * It will support methods for switching and logical synchronization between CPU and GPU. + */ + class CV_EXPORTS Blob + { + public: + explicit Blob(); + + /** @brief Constructs blob with specified @p shape and @p type. */ + explicit Blob(const BlobShape &shape, int type = CV_32F); + + /** @brief Constucts 4-dimensional blob (so-called batch) from image or array of images. + * @param image 2-dimensional multi-channel or 3-dimensional single-channel image (or array of images) + * @param dstCn specify size of second axis of ouptut blob + */ + explicit Blob(InputArray image, int dstCn = -1); + + /** @brief Creates blob with specified @p shape and @p type. */ + void create(const BlobShape &shape, int type = CV_32F); + + /** @brief Creates blob from cv::Mat or cv::UMat without copying the data */ + void fill(InputArray in); + /** @brief Creates blob from user data. + * @details If @p deepCopy is false then CPU data will not be allocated. + */ + void fill(const BlobShape &shape, int type, void *data, bool deepCopy = true); + + Mat& matRef(); //!< Returns reference to cv::Mat, containing blob data. + const Mat& matRefConst() const; //!< Returns reference to cv::Mat, containing blob data, for read-only purposes. + UMat &umatRef(); //!< Returns reference to cv::UMat, containing blob data (not implemented yet). + const UMat &umatRefConst() const; //!< Returns reference to cv::UMat, containing blob data, for read-only purposes (not implemented yet). + + /** @brief Returns number of blob dimensions. */ + int dims() const; + + /** @brief Returns the size of the specified @p axis. + * + * Negative @p axis is supported, in this case a counting starts from the last axis, + * i. e. -1 corresponds to last axis. + * If non-existing axis was passed then an error will be generated. + */ + int size(int axis) const; + + /** @brief Returns the size of the specified @p axis. + * + * Does the same thing as size(int) const, but if non-existing axis will be passed then 1 will be returned, + * therefore this function always finishes successfully. + */ + int xsize(int axis) const; + + /** @brief Computes the product of sizes of axes among the specified axes range [@p startAxis; @p endAxis). + * @param startAxis the first axis to include in the range. + * @param endAxis the first axis to exclude from the range. + * @details Negative axis indexing can be used. + */ + size_t total(int startAxis = 0, int endAxis = INT_MAX) const; + + /** @brief Converts @p axis index to canonical format (where 0 <= axis < dims()). */ + int canonicalAxis(int axis) const; + + /** @brief Returns shape of the blob. */ + BlobShape shape() const; + + /** @brief Checks equality of two blobs shapes. */ + bool equalShape(const Blob &other) const; + + /** @brief Returns slice of first two dimensions. + * @details The behaviour is similar to the following numpy code: blob[n, cn, ...] + */ + Mat getPlane(int n, int cn); + + /* Shape getters of 4-dimensional blobs. */ + int cols() const; //!< Returns size of the fourth axis blob. + int rows() const; //!< Returns size of the thrid axis blob. + int channels() const; //!< Returns size of the second axis blob. + int num() const; //!< Returns size of the first axis blob. + Size size2() const; //!< Returns cv::Size(cols(), rows()) + Vec4i shape4() const; //!< Returns shape of first four blob axes. + + /** @brief Returns linear index of the element with specified coordinates in the blob. + * + * If @p n < dims() then unspecified coordinates will be filled by zeros. + * If @p n > dims() then extra coordinates will be ignored. + */ + template + size_t offset(const Vec &pos) const; + /** @overload */ + size_t offset(int n = 0, int cn = 0, int row = 0, int col = 0) const; + + /* CPU pointer getters */ + /** @brief Returns pointer to the blob element with the specified position, stored in CPU memory. + * + * @p n correspond to the first axis, @p cn - to the second, etc. + * If dims() > 4 then unspecified coordinates will be filled by zeros. + * If dims() < 4 then extra coordinates will be ignored. + */ + uchar *ptr(int n = 0, int cn = 0, int row = 0, int col = 0); + /** @overload */ + template + TFloat *ptr(int n = 0, int cn = 0, int row = 0, int col = 0); + /** @overload ptr() */ + float *ptrf(int n = 0, int cn = 0, int row = 0, int col = 0); + //TODO: add const ptr methods + + /** @brief Shares data from other @p blob. + * @returns *this + */ + Blob &shareFrom(const Blob &blob); + + /** @brief Changes shape of the blob without copying the data. + * @returns *this + */ + Blob &reshape(const BlobShape &shape); + + /** @brief Returns type of the blob. */ + int type() const; + + private: + const int *sizes() const; + + Mat m; + }; + +//! @} +} +} + +#include "blob.inl.hpp" + +#endif diff --git a/modules/dnn/include/opencv2/dnn/blob.inl.hpp b/modules/dnn/include/opencv2/dnn/blob.inl.hpp new file mode 100644 index 000000000..4a6de4804 --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/blob.inl.hpp @@ -0,0 +1,342 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_DNN_BLOB_INL_HPP__ +#define __OPENCV_DNN_DNN_BLOB_INL_HPP__ +#include "blob.hpp" + +namespace cv +{ +namespace dnn +{ + +inline BlobShape::BlobShape(int ndims, int fill) : sz( (size_t)std::max(ndims, 0) ) +{ + CV_Assert(ndims >= 0); + for (int i = 0; i < ndims; i++) + sz[i] = fill; +} + +inline BlobShape::BlobShape(int ndims, const int *sizes) : sz( (size_t)std::max(ndims, 0) ) +{ + CV_Assert(ndims >= 0); + for (int i = 0; i < ndims; i++) + sz[i] = sizes[i]; +} + +inline BlobShape::BlobShape(int num, int cn, int rows, int cols) : sz(4) +{ + sz[0] = num; + sz[1] = cn; + sz[2] = rows; + sz[3] = cols; +} + +inline BlobShape::BlobShape(const std::vector &sizes) : sz( sizes.size() ) +{ + for (int i = 0; i < (int)sizes.size(); i++) + sz[i] = sizes[i]; +} + +template +inline BlobShape::BlobShape(const Vec &shape) : sz(n) +{ + for (int i = 0; i < n; i++) + sz[i] = shape[i]; +} + +inline int BlobShape::dims() const +{ + return (int)sz.size(); +} + +inline int BlobShape::xsize(int axis) const +{ + if (axis < -dims() || axis >= dims()) + return 1; + + return sz[(axis < 0) ? axis + dims() : axis]; +} + +inline int BlobShape::size(int axis) const +{ + CV_Assert(-dims() <= axis && axis < dims()); + return sz[(axis < 0) ? axis + dims() : axis]; +} + +inline int &BlobShape::size(int axis) +{ + CV_Assert(-dims() <= axis && axis < dims()); + return sz[(axis < 0) ? axis + dims() : axis]; +} + +inline int BlobShape::operator[] (int axis) const +{ + CV_Assert(-dims() <= axis && axis < dims()); + return sz[(axis < 0) ? axis + dims() : axis]; +} + +inline int &BlobShape::operator[] (int axis) +{ + CV_Assert(-dims() <= axis && axis < dims()); + return sz[(axis < 0) ? axis + dims() : axis]; +} + +inline ptrdiff_t BlobShape::total() +{ + if (dims() == 0) + return 0; + + ptrdiff_t res = 1; + for (int i = 0; i < dims(); i++) + res *= sz[i]; + return res; +} + +inline const int *BlobShape::ptr() const +{ + return sz; +} + +inline bool BlobShape::equal(const BlobShape &other) const +{ + if (this->dims() != other.dims()) + return false; + + for (int i = 0; i < other.dims(); i++) + { + if (sz[i] != other.sz[i]) + return false; + } + + return true; +} + +inline bool BlobShape::operator==(const BlobShape &r) const +{ + return this->equal(r); +} + +CV_EXPORTS std::ostream &operator<< (std::ostream &stream, const BlobShape &shape); + +///////////////////////////////////////////////////////////////////// + +inline int Blob::canonicalAxis(int axis) const +{ + CV_Assert(-dims() <= axis && axis < dims()); + return (axis < 0) ? axis + dims() : axis; +} + +inline int Blob::dims() const +{ + return m.dims; +} + +inline int Blob::xsize(int axis) const +{ + if (axis < -dims() || axis >= dims()) + return 1; + + return sizes()[(axis < 0) ? axis + dims() : axis]; +} + +inline int Blob::size(int axis) const +{ + CV_Assert(-dims() <= axis && axis < dims()); + return sizes()[(axis < 0) ? axis + dims() : axis]; +} + +inline size_t Blob::total(int startAxis, int endAxis) const +{ + if (startAxis < 0) + startAxis += dims(); + + if (endAxis == INT_MAX) + endAxis = dims(); + else if (endAxis < 0) + endAxis += dims(); + + CV_Assert(0 <= startAxis && startAxis <= endAxis && endAxis <= dims()); + + size_t size = 1; //fix: assume that slice isn't empty + for (int i = startAxis; i < endAxis; i++) + size *= (size_t)sizes()[i]; + + return size; +} + + +template +inline size_t Blob::offset(const Vec &pos) const +{ + size_t ofs = 0; + int i; + for (i = 0; i < std::min(n, dims()); i++) + { + CV_DbgAssert(pos[i] >= 0 && pos[i] < size(i)); + ofs = ofs * (size_t)size(i) + pos[i]; + } + for (; i < dims(); i++) + ofs *= (size_t)size(i); + return ofs; +} + +inline size_t Blob::offset(int n, int cn, int row, int col) const +{ + return offset(Vec4i(n, cn, row, col)); +} + +inline float *Blob::ptrf(int n, int cn, int row, int col) +{ + CV_Assert(type() == CV_32F); + return (float*)m.data + offset(n, cn, row, col); +} + +inline uchar *Blob::ptr(int n, int cn, int row, int col) +{ + return m.data + m.elemSize() * offset(n, cn, row, col); +} + +template +inline TFloat* Blob::ptr(int n, int cn, int row, int col) +{ + CV_Assert(type() == cv::DataDepth::value); + return (TFloat*) ptr(n, cn, row, col); +} + +inline BlobShape Blob::shape() const +{ + return BlobShape(dims(), sizes()); +} + +inline bool Blob::equalShape(const Blob &other) const +{ + if (this->dims() != other.dims()) + return false; + + for (int i = 0; i < dims(); i++) + { + if (this->sizes()[i] != other.sizes()[i]) + return false; + } + return true; +} + +inline Mat& Blob::matRef() +{ + return m; +} + +inline const Mat& Blob::matRefConst() const +{ + return m; +} + +inline UMat &Blob::umatRef() +{ + CV_Error(Error::StsNotImplemented, ""); + return *(new UMat()); +} + +inline const UMat &Blob::umatRefConst() const +{ + CV_Error(Error::StsNotImplemented, ""); + return *(new UMat()); +} + +inline Mat Blob::getPlane(int n, int cn) +{ + CV_Assert(dims() > 2); + return Mat(dims() - 2, sizes() + 2, type(), ptr(n, cn)); +} + +inline int Blob::cols() const +{ + return xsize(3); +} + +inline int Blob::rows() const +{ + return xsize(2); +} + +inline int Blob::channels() const +{ + return xsize(1); +} + +inline int Blob::num() const +{ + return xsize(0); +} + +inline Size Blob::size2() const +{ + return Size(cols(), rows()); +} + +inline int Blob::type() const +{ + return m.depth(); +} + +inline const int * Blob::sizes() const +{ + return &m.size[0]; +} + + +inline Blob &Blob::shareFrom(const Blob &blob) +{ + this->m = blob.m; + return *this; +} + +inline Blob &Blob::reshape(const BlobShape &shape) +{ + m = m.reshape(1, shape.dims(), shape.ptr()); + return *this; +} + +} +} + +#endif diff --git a/modules/dnn/include/opencv2/dnn/dict.hpp b/modules/dnn/include/opencv2/dnn/dict.hpp new file mode 100644 index 000000000..61db133c2 --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/dict.hpp @@ -0,0 +1,141 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_DNN_DICT_HPP__ +#define __OPENCV_DNN_DNN_DICT_HPP__ + +#include +#include +#include + +namespace cv +{ +namespace dnn +{ +//! @addtogroup dnn +//! @{ + +/** @brief This struct stores the scalar value (or array) of one of the following type: double, cv::String or int64. + * @todo Maybe int64 is useless because double type exactly stores at least 2^52 integers. + */ +struct DictValue +{ + DictValue(const DictValue &r); + DictValue(int p = 0) : type(Param::INT), pi(new AutoBuffer) { (*pi)[0] = p; } //!< Constructs integer scalar + DictValue(unsigned p) : type(Param::INT), pi(new AutoBuffer) { (*pi)[0] = p; } //!< Constructs integer scalar + DictValue(double p) : type(Param::REAL), pd(new AutoBuffer) { (*pd)[0] = p; } //!< Constructs floating point scalar + DictValue(const String &p) : type(Param::STRING), ps(new AutoBuffer) { (*ps)[0] = p; } //!< Constructs string scalar + + template + static DictValue arrayInt(TypeIter begin, int size); //!< Constructs integer array + template + static DictValue arrayReal(TypeIter begin, int size); //!< Constructs floating point array + template + static DictValue arrayString(TypeIter begin, int size); //!< Constructs array of strings + + template + T get(int idx = -1) const; //!< Tries to convert array element with specified index to requested type and returns its. + + int size() const; + + bool isInt() const; + bool isString() const; + bool isReal() const; + + DictValue &operator=(const DictValue &r); + + friend std::ostream &operator<<(std::ostream &stream, const DictValue &dictv); + + ~DictValue(); + +private: + + int type; + + union + { + AutoBuffer *pi; + AutoBuffer *pd; + AutoBuffer *ps; + void *p; + }; + + DictValue(int _type, void *_p) : type(_type), p(_p) {} + void release(); +}; + +/** @brief This class implements name-value dictionary, values are instances of DictValue. */ +class CV_EXPORTS Dict +{ + typedef std::map _Dict; + _Dict dict; + +public: + + //! Checks a presence of the @p key in the dictionary. + bool has(const String &key); + + //! If the @p key in the dictionary then returns pointer to its value, else returns NULL. + DictValue *ptr(const String &key); + + //! If the @p key in the dictionary then returns its value, else an error will be generated. + const DictValue &get(const String &key) const; + + /** @overload */ + template + T get(const String &key) const; + + //! If the @p key in the dictionary then returns its value, else returns @p defaultValue. + template + T get(const String &key, const T &defaultValue) const; + + //! Sets new @p value for the @p key, or adds new key-value pair into the dictionary. + template + const T &set(const String &key, const T &value); + + friend std::ostream &operator<<(std::ostream &stream, const Dict &dict); +}; + +//! @} +} +} + +#endif diff --git a/modules/dnn/include/opencv2/dnn/dnn.hpp b/modules/dnn/include/opencv2/dnn/dnn.hpp new file mode 100644 index 000000000..1d1244dad --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/dnn.hpp @@ -0,0 +1,304 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_DNN_HPP__ +#define __OPENCV_DNN_DNN_HPP__ + +#include +#include +#include +#include + +namespace cv +{ +namespace dnn //! This namespace is used for dnn module functionlaity. +{ +//! @addtogroup dnn +//! @{ + + /** @brief Initialize dnn module and built-in layers. + * + * This function automatically called on most of OpenCV builds, + * but you need to call it manually on some specific configurations (iOS for example). + */ + CV_EXPORTS void initModule(); + + /** @brief This class provides all data needed to initialize layer. + * + * It includes dictionary with scalar params (which can be readed by using Dict interface), + * blob params #blobs and optional meta information: #name and #type of layer instance. + */ + struct CV_EXPORTS LayerParams : public Dict + { + std::vector blobs; //!< List of learned parameters stored as blobs. + + String name; //!< Name of the layer instance (optional, can be used internal purposes). + String type; //!< Type name which was used for creating layer by layer factory (optional). + }; + + /** @brief This interface class allows to build new Layers - are building blocks of networks. + * + * Each class, derived from Layer, must implement allocate() methods to declare own outputs and forward() to compute outputs. + * Also before using the new layer into networks you must register your layer by using one of @ref LayerFactoryModule "LayerFactory" macros. + */ + struct CV_EXPORTS Layer + { + //! List of learned parameters must be stored here to allow read them by using Net::getParam(). + std::vector blobs; + + /** @brief Allocates internal buffers and output blobs with respect to the shape of inputs. + * @param[in] input vector of already allocated input blobs + * @param[out] output vector of output blobs, which must be allocated + * + * This method must create each produced blob according to shape of @p input blobs and internal layer params. + * If this method is called first time then @p output vector consists from empty blobs and its size determined by number of output connections. + * This method can be called multiple times if size of any @p input blob was changed. + */ + virtual void allocate(const std::vector &input, std::vector &output) = 0; + + /** @brief Given the @p input blobs, computes the output @p blobs. + * @param[in] input the input blobs. + * @param[out] output allocated output blobs, which will store results of the computation. + */ + virtual void forward(std::vector &input, std::vector &output) = 0; + + /** @brief Returns index of input blob into the input array. + * @param inputName label of input blob + * + * Each layer input and output can be labeled to easily identify them using "%[.output_name]" notation. + * This method maps label of input blob to its index into input vector. + */ + virtual int inputNameToIndex(String inputName); + /** @brief Returns index of output blob in output array. + * @see inputNameToIndex() + */ + virtual int outputNameToIndex(String outputName); + + String name; //!< Name of the layer instance, can be used for logging or other internal purposes. + String type; //!< Type name which was used for creating layer by layer factory. + + Layer(); + explicit Layer(const LayerParams ¶ms); //!< Initialize only #name, #type and #blobs fields. + virtual ~Layer(); + }; + + /** @brief This class allows to create and manipulate comprehensive artificial neural networks. + * + * Neural network is presented as directed acyclic graph (DAG), where vertices are Layer instances, + * and edges specify relationships between layers inputs and outputs. + * + * Each network layer has unique integer id and unique string name inside its network. + * LayerId can store either layer name or layer id. + * + * This class supports reference counting of its instances, i. e. copies point to the same instance. + */ + class CV_EXPORTS Net + { + public: + + Net(); //!< Default constructor. + ~Net(); //!< Destructor frees the net only if there aren't references to the net anymore. + + /** @brief Adds new layer to the net. + * @param name unique name of the adding layer. + * @param type typename of the adding layer (type must be registered in LayerRegister). + * @param params parameters which will be used to initialize the creating layer. + * @returns unique identifier of created layer, or -1 if a failure will happen. + */ + int addLayer(const String &name, const String &type, LayerParams ¶ms); + /** @brief Adds new layer and connects its first input to the first output of previously added layer. + * @see addLayer() + */ + int addLayerToPrev(const String &name, const String &type, LayerParams ¶ms); + + /** @brief Converts string name of the layer to the integer identifier. + * @returns id of the layer, or -1 if the layer wasn't found. + */ + int getLayerId(const String &layer); + + /** @brief Container for strings and integers. */ + typedef DictValue LayerId; + + /** @brief Delete layer for the network (not implemented yet) */ + void deleteLayer(LayerId layer); + + /** @brief Connects output of the first layer to input of the second layer. + * @param outPin descriptor of the first layer output. + * @param inpPin descriptor of the second layer input. + * + * Descriptors have the following template <layer_name>[.input_number]: + * - the first part of the template layer_name is sting name of the added layer. + * If this part is empty then the network input pseudo layer will be used; + * - the second optional part of the template input_number + * is either number of the layer input, either label one. + * If this part is omitted then the first layer input will be used. + * + * @see setNetInputs(), Layer::inputNameToIndex(), Layer::outputNameToIndex() + */ + void connect(String outPin, String inpPin); + /** @brief Connects #@p outNum output of the first layer to #@p inNum input of the second layer. + * @param outLayerId identifier of the first layer + * @param inpLayerId identifier of the second layer + * @param outNum number of the first layer output + * @param inpNum number of the second layer input + */ + void connect(int outLayerId, int outNum, int inpLayerId, int inpNum); + /** @brief Sets ouputs names of the network input pseudo layer. + * + * Each net always has special own the network input pseudo layer with id=0. + * This layer stores the user blobs only and don't make any computations. + * In fact, this layer provides the only way to pass user data into the network. + * As any other layer, this layer can label its outputs and this function provides an easy way to do this. + */ + void setNetInputs(const std::vector &inputBlobNames); + + /** @brief Runs forward pass for the whole network */ + void forward(); + /** @brief Runs forward pass to compute output of layer @p toLayer */ + void forward(LayerId toLayer); + /** @brief Runs forward pass to compute output of layer @p toLayer, but computations start from @p startLayer */ + void forward(LayerId startLayer, LayerId toLayer); + /** @overload */ + void forward(const std::vector &startLayers, const std::vector &toLayers); + + //TODO: + /** @brief Optimized forward. + * @warning Not implemented yet. + * @details Makes forward only those layers which weren't changed after previous forward(). + */ + void forwardOpt(LayerId toLayer); + /** @overload */ + void forwardOpt(const std::vector &toLayers); + + /** @brief Sets the new value for the layer output blob + * @param outputName descriptor of the updating layer output blob. + * @param blob new blob. + * @see connect(String, String) to know format of the descriptor. + * @note If updating blob is not empty then @p blob must have the same shape, + * because network reshaping is not implemented yet. + */ + void setBlob(String outputName, const Blob &blob); + /** @brief Returns the layer output blob. + * @param outputName the descriptor of the returning layer output blob. + * @see connect(String, String) + */ + Blob getBlob(String outputName); + + /** @brief Sets the new value for the learned param of the layer. + * @param layer name or id of the layer. + * @param numParam index of the layer parameter in the Layer::blobs array. + * @param blob the new value. + * @see Layer::blobs + * @note If shape of the new blob differs from the previous shape, + * then the following forward pass may fail. + */ + void setParam(LayerId layer, int numParam, const Blob &blob); + /** @brief Returns parameter blob of the layer. + * @param layer name or id of the layer. + * @param numParam index of the layer parameter in the Layer::blobs array. + * @see Layer::blobs + */ + Blob getParam(LayerId layer, int numParam = 0); + + private: + + struct Impl; + Ptr impl; + }; + + /** @brief Small interface class for loading trained serialized models of different dnn-frameworks. */ + class Importer + { + public: + + /** @brief Adds loaded layers into the @p net and sets connetions between them. */ + virtual void populateNet(Net net) = 0; + + virtual ~Importer(); + }; + + /** @brief Creates the importer of Caffe framework network. + * @param prototxt path to the .prototxt file with text description of the network architecture. + * @param caffeModel path to the .caffemodel file with learned network. + * @returns Pointer to the created importer, NULL in failure cases. + */ + CV_EXPORTS Ptr createCaffeImporter(const String &prototxt, const String &caffeModel = String()); + + /** @brief Creates the importer of Torch7 framework network. + * @param filename path to the file, dumped from Torch by using torch.save() function. + * @param isBinary specifies whether the network was serialized in ascii mode or binary. + * @returns Pointer to the created importer, NULL in failure cases. + * + * @warning Torch7 importer is experimental now, you need explicitly set CMake opencv_dnn_BUILD_TORCH_IMPORTER flag to compile its. + * + * @note Ascii mode of Torch serializer is more preferable, because binary mode extensively use long type of C language, + * which has different bit-length on different systems. + * + * The loading file must contain serialized nn.Module object + * with importing network. Try to eliminate a custom objects from serialazing data to avoid importing errors. + * + * List of supported layers (i.e. object instances derived from Torch nn.Module class): + * - nn.Sequential + * - nn.Parallel + * - nn.Concat + * - nn.Linear + * - nn.SpatialConvolution + * - nn.SpatialMaxPooling, nn.SpatialAveragePooling + * - nn.ReLU, nn.TanH, nn.Sigmoid + * - nn.Reshape + * + * Also some equivalents of these classes from cunn, cudnn, and fbcunn may be successfully imported. + */ + CV_EXPORTS Ptr createTorchImporter(const String &filename, bool isBinary = true); + + /** @brief Loads blob which was serialized as torch.Tensor object of Torch7 framework. + * @warning This function has the same limitations as createTorchImporter(). + */ + CV_EXPORTS Blob readTorchBlob(const String &filename, bool isBinary = true); + +//! @} +} +} + +#include +#include + +#endif /* __OPENCV_DNN_DNN_HPP__ */ diff --git a/modules/dnn/include/opencv2/dnn/dnn.inl.hpp b/modules/dnn/include/opencv2/dnn/dnn.inl.hpp new file mode 100644 index 000000000..300ae5821 --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/dnn.inl.hpp @@ -0,0 +1,351 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_DNN_INL_HPP__ +#define __OPENCV_DNN_DNN_INL_HPP__ + +#include + +namespace cv +{ +namespace dnn +{ + +template +DictValue DictValue::arrayInt(TypeIter begin, int size) +{ + DictValue res(Param::INT, new AutoBuffer(size)); + for (int j = 0; j < size; begin++, j++) + (*res.pi)[j] = *begin; + return res; +} + +template +DictValue DictValue::arrayReal(TypeIter begin, int size) +{ + DictValue res(Param::REAL, new AutoBuffer(size)); + for (int j = 0; j < size; begin++, j++) + (*res.pd)[j] = *begin; + return res; +} + +template +DictValue DictValue::arrayString(TypeIter begin, int size) +{ + DictValue res(Param::STRING, new AutoBuffer(size)); + for (int j = 0; j < size; begin++, j++) + (*res.ps)[j] = *begin; + return res; +} + +template<> +inline DictValue DictValue::get(int idx) const +{ + CV_Assert(idx == -1); + return *this; +} + +template<> +inline int64 DictValue::get(int idx) const +{ + CV_Assert(idx == -1 && size() == 1 || idx >= 0 && idx < size()); + idx = (idx == -1) ? 0 : idx; + + if (type == Param::INT) + { + return (*pi)[idx]; + } + else if (type == Param::REAL) + { + double doubleValue = (*pd)[idx]; + + double fracpart, intpart; + fracpart = std::modf(doubleValue, &intpart); + CV_Assert(fracpart == 0.0); + + return (int64)doubleValue; + } + else + { + CV_Assert(isInt() || isReal()); + return 0; + } +} + +template<> +inline int DictValue::get(int idx) const +{ + return (int)get(idx); +} + +template<> +inline unsigned DictValue::get(int idx) const +{ + return (unsigned)get(idx); +} + +template<> +inline bool DictValue::get(int idx) const +{ + return (get(idx) != 0); +} + +template<> +inline double DictValue::get(int idx) const +{ + CV_Assert(idx == -1 && size() == 1 || idx >= 0 && idx < size()); + idx = (idx == -1) ? 0 : idx; + + if (type == Param::REAL) + { + return (*pd)[idx]; + } + else if (type == Param::INT) + { + return (double)(*pi)[idx]; + } + else + { + CV_Assert(isReal() || isInt()); + return 0; + } +} + +template<> +inline float DictValue::get(int idx) const +{ + return (float)get(idx); +} + +template<> +inline String DictValue::get(int idx) const +{ + CV_Assert(isString()); + CV_Assert(idx == -1 && ps->size() == 1 || idx >= 0 && idx < (int)ps->size()); + return (*ps)[(idx == -1) ? 0 : idx]; +} + +inline void DictValue::release() +{ + switch (type) + { + case Param::INT: + delete pi; + break; + case Param::STRING: + delete ps; + break; + case Param::REAL: + delete pd; + break; + } +} + +inline DictValue::~DictValue() +{ + release(); +} + +inline DictValue & DictValue::operator=(const DictValue &r) +{ + if (&r == this) + return *this; + + if (r.type == Param::INT) + { + AutoBuffer *tmp = new AutoBuffer(*r.pi); + release(); + pi = tmp; + } + else if (r.type == Param::STRING) + { + AutoBuffer *tmp = new AutoBuffer(*r.ps); + release(); + ps = tmp; + } + else if (r.type == Param::REAL) + { + AutoBuffer *tmp = new AutoBuffer(*r.pd); + release(); + pd = tmp; + } + + type = r.type; + + return *this; +} + +inline DictValue::DictValue(const DictValue &r) +{ + type = r.type; + + if (r.type == Param::INT) + pi = new AutoBuffer(*r.pi); + else if (r.type == Param::STRING) + ps = new AutoBuffer(*r.ps); + else if (r.type == Param::REAL) + pd = new AutoBuffer(*r.pd); +} + +inline bool DictValue::isString() const +{ + return (type == Param::STRING); +} + +inline bool DictValue::isInt() const +{ + return (type == Param::INT); +} + +inline bool DictValue::isReal() const +{ + return (type == Param::REAL || type == Param::INT); +} + +inline int DictValue::size() const +{ + switch (type) + { + case Param::INT: + return (int)pi->size(); + break; + case Param::STRING: + return (int)ps->size(); + break; + case Param::REAL: + return (int)pd->size(); + break; + default: + CV_Error(Error::StsInternal, ""); + return -1; + } +} + +inline std::ostream &operator<<(std::ostream &stream, const DictValue &dictv) +{ + int i; + + if (dictv.isInt()) + { + for (i = 0; i < dictv.size() - 1; i++) + stream << dictv.get(i) << ", "; + stream << dictv.get(i); + } + else if (dictv.isReal()) + { + for (i = 0; i < dictv.size() - 1; i++) + stream << dictv.get(i) << ", "; + stream << dictv.get(i); + } + else if (dictv.isString()) + { + for (i = 0; i < dictv.size() - 1; i++) + stream << "\"" << dictv.get(i) << "\", "; + stream << dictv.get(i); + } + + return stream; +} + +///////////////////////////////////////////////////////////////// + +inline bool Dict::has(const String &key) +{ + return dict.count(key) != 0; +} + +inline DictValue *Dict::ptr(const String &key) +{ + _Dict::iterator i = dict.find(key); + return (i == dict.end()) ? NULL : &i->second; +} + +inline const DictValue &Dict::get(const String &key) const +{ + _Dict::const_iterator i = dict.find(key); + if (i == dict.end()) + CV_Error(Error::StsObjectNotFound, "Required argument \"" + key + "\" not found into dictionary"); + return i->second; +} + +template +inline T Dict::get(const String &key) const +{ + return this->get(key).get(); +} + +template +inline T Dict::get(const String &key, const T &defaultValue) const +{ + _Dict::const_iterator i = dict.find(key); + + if (i != dict.end()) + return i->second.get(); + else + return defaultValue; +} + +template +inline const T &Dict::set(const String &key, const T &value) +{ + _Dict::iterator i = dict.find(key); + + if (i != dict.end()) + i->second = DictValue(value); + else + dict.insert(std::make_pair(key, DictValue(value))); + + return value; +} + +inline std::ostream &operator<<(std::ostream &stream, const Dict &dict) +{ + Dict::_Dict::const_iterator it; + for (it = dict.dict.begin(); it != dict.dict.end(); it++) + stream << it->first << " : " << it->second << "\n"; + + return stream; +} + +} +} + +#endif diff --git a/modules/dnn/include/opencv2/dnn/layer.hpp b/modules/dnn/include/opencv2/dnn/layer.hpp new file mode 100644 index 000000000..b28b6acd8 --- /dev/null +++ b/modules/dnn/include/opencv2/dnn/layer.hpp @@ -0,0 +1,147 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYER_HPP__ +#define __OPENCV_DNN_LAYER_HPP__ +#include + +namespace cv +{ +namespace dnn +{ +//! @addtogroup dnn +//! @{ +//! +//! @defgroup LayerFactoryModule Utilities for new layers registration +//! @{ + +/** @brief %Layer factory allows to create instances of registered layers. */ +class CV_EXPORTS LayerFactory +{ +public: + + //! Each Layer class must provide this function to the factory + typedef Ptr(*Constuctor)(LayerParams ¶ms); + + //! Registers the layer class with typename @p type and specified @p constructor. + static void registerLayer(const String &type, Constuctor constructor); + + //! Unregisters registered layer with specified type name. + static void unregisterLayer(const String &type); + + /** @brief Creates instance of registered layer. + * @param type type name of creating layer. + * @param params parameters which will be used for layer initialization. + */ + static Ptr createLayerInstance(const String &type, LayerParams& params); + +private: + LayerFactory(); + + struct Impl; + static Ptr impl(); +}; + +/** @brief Registers layer constructor in runtime. +* @param type string, containing type name of the layer. +* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer. +* @details This macros must be placed inside the function code. +*/ +#define REG_RUNTIME_LAYER_FUNC(type, constuctorFunc) \ + LayerFactory::registerLayer(#type, constuctorFunc); + +/** @brief Registers layer class in runtime. + * @param type string, containing type name of the layer. + * @param class C++ class, derived from Layer. + * @details This macros must be placed inside the function code. + */ +#define REG_RUNTIME_LAYER_CLASS(type, class) \ + LayerFactory::registerLayer(#type, _layerDynamicRegisterer); + +/** @brief Registers layer constructor on module load time. +* @param type string, containing type name of the layer. +* @param constuctorFunc pointer to the function of type LayerRegister::Constuctor, which creates the layer. +* @details This macros must be placed outside the function code. +*/ +#define REG_STATIC_LAYER_FUNC(type, constuctorFunc) \ +static _LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, constuctorFunc); + +/** @brief Registers layer class on module load time. + * @param type string, containing type name of the layer. + * @param class C++ class, derived from Layer. + * @details This macros must be placed outside the function code. + */ +#define REG_STATIC_LAYER_CLASS(type, class) \ +Ptr __LayerStaticRegisterer_func_##type(LayerParams ¶ms) \ + { return Ptr(new class(params)); } \ +static _LayerStaticRegisterer __LayerStaticRegisterer_##type(#type, __LayerStaticRegisterer_func_##type); + + +//! @} +//! @} + + +template +Ptr _layerDynamicRegisterer(LayerParams ¶ms) +{ + return Ptr(new LayerClass(params)); +} + +//allows automatically register created layer on module load time +struct _LayerStaticRegisterer +{ + String type; + + _LayerStaticRegisterer(const String &type, LayerFactory::Constuctor constuctor) + { + this->type = type; + LayerFactory::registerLayer(type, constuctor); + } + + ~_LayerStaticRegisterer() + { + LayerFactory::unregisterLayer(type); + } +}; + +} +} +#endif diff --git a/modules/dnn/samples/bvlc_googlenet.prototxt b/modules/dnn/samples/bvlc_googlenet.prototxt new file mode 100644 index 000000000..4648bf26e --- /dev/null +++ b/modules/dnn/samples/bvlc_googlenet.prototxt @@ -0,0 +1,2156 @@ +name: "GoogleNet" +input: "data" +input_dim: 10 +input_dim: 3 +input_dim: 224 +input_dim: 224 +layer { + name: "conv1/7x7_s2" + type: "Convolution" + bottom: "data" + top: "conv1/7x7_s2" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 3 + kernel_size: 7 + stride: 2 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "conv1/relu_7x7" + type: "ReLU" + bottom: "conv1/7x7_s2" + top: "conv1/7x7_s2" +} +layer { + name: "pool1/3x3_s2" + type: "Pooling" + bottom: "conv1/7x7_s2" + top: "pool1/3x3_s2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layer { + name: "pool1/norm1" + type: "LRN" + bottom: "pool1/3x3_s2" + top: "pool1/norm1" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layer { + name: "conv2/3x3_reduce" + type: "Convolution" + bottom: "pool1/norm1" + top: "conv2/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "conv2/relu_3x3_reduce" + type: "ReLU" + bottom: "conv2/3x3_reduce" + top: "conv2/3x3_reduce" +} +layer { + name: "conv2/3x3" + type: "Convolution" + bottom: "conv2/3x3_reduce" + top: "conv2/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "conv2/relu_3x3" + type: "ReLU" + bottom: "conv2/3x3" + top: "conv2/3x3" +} +layer { + name: "conv2/norm2" + type: "LRN" + bottom: "conv2/3x3" + top: "conv2/norm2" + lrn_param { + local_size: 5 + alpha: 0.0001 + beta: 0.75 + } +} +layer { + name: "pool2/3x3_s2" + type: "Pooling" + bottom: "conv2/norm2" + top: "pool2/3x3_s2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layer { + name: "inception_3a/1x1" + type: "Convolution" + bottom: "pool2/3x3_s2" + top: "inception_3a/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_1x1" + type: "ReLU" + bottom: "inception_3a/1x1" + top: "inception_3a/1x1" +} +layer { + name: "inception_3a/3x3_reduce" + type: "Convolution" + bottom: "pool2/3x3_s2" + top: "inception_3a/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3_reduce" +} +layer { + name: "inception_3a/3x3" + type: "Convolution" + bottom: "inception_3a/3x3_reduce" + top: "inception_3a/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_3x3" + type: "ReLU" + bottom: "inception_3a/3x3" + top: "inception_3a/3x3" +} +layer { + name: "inception_3a/5x5_reduce" + type: "Convolution" + bottom: "pool2/3x3_s2" + top: "inception_3a/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5_reduce" +} +layer { + name: "inception_3a/5x5" + type: "Convolution" + bottom: "inception_3a/5x5_reduce" + top: "inception_3a/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_5x5" + type: "ReLU" + bottom: "inception_3a/5x5" + top: "inception_3a/5x5" +} +layer { + name: "inception_3a/pool" + type: "Pooling" + bottom: "pool2/3x3_s2" + top: "inception_3a/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_3a/pool_proj" + type: "Convolution" + bottom: "inception_3a/pool" + top: "inception_3a/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3a/relu_pool_proj" + type: "ReLU" + bottom: "inception_3a/pool_proj" + top: "inception_3a/pool_proj" +} +layer { + name: "inception_3a/output" + type: "Concat" + bottom: "inception_3a/1x1" + bottom: "inception_3a/3x3" + bottom: "inception_3a/5x5" + bottom: "inception_3a/pool_proj" + top: "inception_3a/output" +} +layer { + name: "inception_3b/1x1" + type: "Convolution" + bottom: "inception_3a/output" + top: "inception_3b/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_1x1" + type: "ReLU" + bottom: "inception_3b/1x1" + top: "inception_3b/1x1" +} +layer { + name: "inception_3b/3x3_reduce" + type: "Convolution" + bottom: "inception_3a/output" + top: "inception_3b/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3_reduce" +} +layer { + name: "inception_3b/3x3" + type: "Convolution" + bottom: "inception_3b/3x3_reduce" + top: "inception_3b/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 192 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_3x3" + type: "ReLU" + bottom: "inception_3b/3x3" + top: "inception_3b/3x3" +} +layer { + name: "inception_3b/5x5_reduce" + type: "Convolution" + bottom: "inception_3a/output" + top: "inception_3b/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5_reduce" +} +layer { + name: "inception_3b/5x5" + type: "Convolution" + bottom: "inception_3b/5x5_reduce" + top: "inception_3b/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 96 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_5x5" + type: "ReLU" + bottom: "inception_3b/5x5" + top: "inception_3b/5x5" +} +layer { + name: "inception_3b/pool" + type: "Pooling" + bottom: "inception_3a/output" + top: "inception_3b/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_3b/pool_proj" + type: "Convolution" + bottom: "inception_3b/pool" + top: "inception_3b/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_3b/relu_pool_proj" + type: "ReLU" + bottom: "inception_3b/pool_proj" + top: "inception_3b/pool_proj" +} +layer { + name: "inception_3b/output" + type: "Concat" + bottom: "inception_3b/1x1" + bottom: "inception_3b/3x3" + bottom: "inception_3b/5x5" + bottom: "inception_3b/pool_proj" + top: "inception_3b/output" +} +layer { + name: "pool3/3x3_s2" + type: "Pooling" + bottom: "inception_3b/output" + top: "pool3/3x3_s2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layer { + name: "inception_4a/1x1" + type: "Convolution" + bottom: "pool3/3x3_s2" + top: "inception_4a/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_1x1" + type: "ReLU" + bottom: "inception_4a/1x1" + top: "inception_4a/1x1" +} +layer { + name: "inception_4a/3x3_reduce" + type: "Convolution" + bottom: "pool3/3x3_s2" + top: "inception_4a/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 96 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3_reduce" +} +layer { + name: "inception_4a/3x3" + type: "Convolution" + bottom: "inception_4a/3x3_reduce" + top: "inception_4a/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 208 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_3x3" + type: "ReLU" + bottom: "inception_4a/3x3" + top: "inception_4a/3x3" +} +layer { + name: "inception_4a/5x5_reduce" + type: "Convolution" + bottom: "pool3/3x3_s2" + top: "inception_4a/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 16 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5_reduce" +} +layer { + name: "inception_4a/5x5" + type: "Convolution" + bottom: "inception_4a/5x5_reduce" + top: "inception_4a/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 48 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_5x5" + type: "ReLU" + bottom: "inception_4a/5x5" + top: "inception_4a/5x5" +} +layer { + name: "inception_4a/pool" + type: "Pooling" + bottom: "pool3/3x3_s2" + top: "inception_4a/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_4a/pool_proj" + type: "Convolution" + bottom: "inception_4a/pool" + top: "inception_4a/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4a/relu_pool_proj" + type: "ReLU" + bottom: "inception_4a/pool_proj" + top: "inception_4a/pool_proj" +} +layer { + name: "inception_4a/output" + type: "Concat" + bottom: "inception_4a/1x1" + bottom: "inception_4a/3x3" + bottom: "inception_4a/5x5" + bottom: "inception_4a/pool_proj" + top: "inception_4a/output" +} +layer { + name: "inception_4b/1x1" + type: "Convolution" + bottom: "inception_4a/output" + top: "inception_4b/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_1x1" + type: "ReLU" + bottom: "inception_4b/1x1" + top: "inception_4b/1x1" +} +layer { + name: "inception_4b/3x3_reduce" + type: "Convolution" + bottom: "inception_4a/output" + top: "inception_4b/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3_reduce" +} +layer { + name: "inception_4b/3x3" + type: "Convolution" + bottom: "inception_4b/3x3_reduce" + top: "inception_4b/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 224 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_3x3" + type: "ReLU" + bottom: "inception_4b/3x3" + top: "inception_4b/3x3" +} +layer { + name: "inception_4b/5x5_reduce" + type: "Convolution" + bottom: "inception_4a/output" + top: "inception_4b/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5_reduce" +} +layer { + name: "inception_4b/5x5" + type: "Convolution" + bottom: "inception_4b/5x5_reduce" + top: "inception_4b/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_5x5" + type: "ReLU" + bottom: "inception_4b/5x5" + top: "inception_4b/5x5" +} +layer { + name: "inception_4b/pool" + type: "Pooling" + bottom: "inception_4a/output" + top: "inception_4b/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_4b/pool_proj" + type: "Convolution" + bottom: "inception_4b/pool" + top: "inception_4b/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4b/relu_pool_proj" + type: "ReLU" + bottom: "inception_4b/pool_proj" + top: "inception_4b/pool_proj" +} +layer { + name: "inception_4b/output" + type: "Concat" + bottom: "inception_4b/1x1" + bottom: "inception_4b/3x3" + bottom: "inception_4b/5x5" + bottom: "inception_4b/pool_proj" + top: "inception_4b/output" +} +layer { + name: "inception_4c/1x1" + type: "Convolution" + bottom: "inception_4b/output" + top: "inception_4c/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_1x1" + type: "ReLU" + bottom: "inception_4c/1x1" + top: "inception_4c/1x1" +} +layer { + name: "inception_4c/3x3_reduce" + type: "Convolution" + bottom: "inception_4b/output" + top: "inception_4c/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3_reduce" +} +layer { + name: "inception_4c/3x3" + type: "Convolution" + bottom: "inception_4c/3x3_reduce" + top: "inception_4c/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_3x3" + type: "ReLU" + bottom: "inception_4c/3x3" + top: "inception_4c/3x3" +} +layer { + name: "inception_4c/5x5_reduce" + type: "Convolution" + bottom: "inception_4b/output" + top: "inception_4c/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 24 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5_reduce" +} +layer { + name: "inception_4c/5x5" + type: "Convolution" + bottom: "inception_4c/5x5_reduce" + top: "inception_4c/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_5x5" + type: "ReLU" + bottom: "inception_4c/5x5" + top: "inception_4c/5x5" +} +layer { + name: "inception_4c/pool" + type: "Pooling" + bottom: "inception_4b/output" + top: "inception_4c/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_4c/pool_proj" + type: "Convolution" + bottom: "inception_4c/pool" + top: "inception_4c/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4c/relu_pool_proj" + type: "ReLU" + bottom: "inception_4c/pool_proj" + top: "inception_4c/pool_proj" +} +layer { + name: "inception_4c/output" + type: "Concat" + bottom: "inception_4c/1x1" + bottom: "inception_4c/3x3" + bottom: "inception_4c/5x5" + bottom: "inception_4c/pool_proj" + top: "inception_4c/output" +} +layer { + name: "inception_4d/1x1" + type: "Convolution" + bottom: "inception_4c/output" + top: "inception_4d/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 112 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_1x1" + type: "ReLU" + bottom: "inception_4d/1x1" + top: "inception_4d/1x1" +} +layer { + name: "inception_4d/3x3_reduce" + type: "Convolution" + bottom: "inception_4c/output" + top: "inception_4d/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 144 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3_reduce" +} +layer { + name: "inception_4d/3x3" + type: "Convolution" + bottom: "inception_4d/3x3_reduce" + top: "inception_4d/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 288 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_3x3" + type: "ReLU" + bottom: "inception_4d/3x3" + top: "inception_4d/3x3" +} +layer { + name: "inception_4d/5x5_reduce" + type: "Convolution" + bottom: "inception_4c/output" + top: "inception_4d/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5_reduce" +} +layer { + name: "inception_4d/5x5" + type: "Convolution" + bottom: "inception_4d/5x5_reduce" + top: "inception_4d/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_5x5" + type: "ReLU" + bottom: "inception_4d/5x5" + top: "inception_4d/5x5" +} +layer { + name: "inception_4d/pool" + type: "Pooling" + bottom: "inception_4c/output" + top: "inception_4d/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_4d/pool_proj" + type: "Convolution" + bottom: "inception_4d/pool" + top: "inception_4d/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 64 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4d/relu_pool_proj" + type: "ReLU" + bottom: "inception_4d/pool_proj" + top: "inception_4d/pool_proj" +} +layer { + name: "inception_4d/output" + type: "Concat" + bottom: "inception_4d/1x1" + bottom: "inception_4d/3x3" + bottom: "inception_4d/5x5" + bottom: "inception_4d/pool_proj" + top: "inception_4d/output" +} +layer { + name: "inception_4e/1x1" + type: "Convolution" + bottom: "inception_4d/output" + top: "inception_4e/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_1x1" + type: "ReLU" + bottom: "inception_4e/1x1" + top: "inception_4e/1x1" +} +layer { + name: "inception_4e/3x3_reduce" + type: "Convolution" + bottom: "inception_4d/output" + top: "inception_4e/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3_reduce" +} +layer { + name: "inception_4e/3x3" + type: "Convolution" + bottom: "inception_4e/3x3_reduce" + top: "inception_4e/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_3x3" + type: "ReLU" + bottom: "inception_4e/3x3" + top: "inception_4e/3x3" +} +layer { + name: "inception_4e/5x5_reduce" + type: "Convolution" + bottom: "inception_4d/output" + top: "inception_4e/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5_reduce" +} +layer { + name: "inception_4e/5x5" + type: "Convolution" + bottom: "inception_4e/5x5_reduce" + top: "inception_4e/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_5x5" + type: "ReLU" + bottom: "inception_4e/5x5" + top: "inception_4e/5x5" +} +layer { + name: "inception_4e/pool" + type: "Pooling" + bottom: "inception_4d/output" + top: "inception_4e/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_4e/pool_proj" + type: "Convolution" + bottom: "inception_4e/pool" + top: "inception_4e/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_4e/relu_pool_proj" + type: "ReLU" + bottom: "inception_4e/pool_proj" + top: "inception_4e/pool_proj" +} +layer { + name: "inception_4e/output" + type: "Concat" + bottom: "inception_4e/1x1" + bottom: "inception_4e/3x3" + bottom: "inception_4e/5x5" + bottom: "inception_4e/pool_proj" + top: "inception_4e/output" +} +layer { + name: "pool4/3x3_s2" + type: "Pooling" + bottom: "inception_4e/output" + top: "pool4/3x3_s2" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 2 + } +} +layer { + name: "inception_5a/1x1" + type: "Convolution" + bottom: "pool4/3x3_s2" + top: "inception_5a/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 256 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_1x1" + type: "ReLU" + bottom: "inception_5a/1x1" + top: "inception_5a/1x1" +} +layer { + name: "inception_5a/3x3_reduce" + type: "Convolution" + bottom: "pool4/3x3_s2" + top: "inception_5a/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 160 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3_reduce" +} +layer { + name: "inception_5a/3x3" + type: "Convolution" + bottom: "inception_5a/3x3_reduce" + top: "inception_5a/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 320 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_3x3" + type: "ReLU" + bottom: "inception_5a/3x3" + top: "inception_5a/3x3" +} +layer { + name: "inception_5a/5x5_reduce" + type: "Convolution" + bottom: "pool4/3x3_s2" + top: "inception_5a/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 32 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5_reduce" +} +layer { + name: "inception_5a/5x5" + type: "Convolution" + bottom: "inception_5a/5x5_reduce" + top: "inception_5a/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_5x5" + type: "ReLU" + bottom: "inception_5a/5x5" + top: "inception_5a/5x5" +} +layer { + name: "inception_5a/pool" + type: "Pooling" + bottom: "pool4/3x3_s2" + top: "inception_5a/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_5a/pool_proj" + type: "Convolution" + bottom: "inception_5a/pool" + top: "inception_5a/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5a/relu_pool_proj" + type: "ReLU" + bottom: "inception_5a/pool_proj" + top: "inception_5a/pool_proj" +} +layer { + name: "inception_5a/output" + type: "Concat" + bottom: "inception_5a/1x1" + bottom: "inception_5a/3x3" + bottom: "inception_5a/5x5" + bottom: "inception_5a/pool_proj" + top: "inception_5a/output" +} +layer { + name: "inception_5b/1x1" + type: "Convolution" + bottom: "inception_5a/output" + top: "inception_5b/1x1" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 384 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_1x1" + type: "ReLU" + bottom: "inception_5b/1x1" + top: "inception_5b/1x1" +} +layer { + name: "inception_5b/3x3_reduce" + type: "Convolution" + bottom: "inception_5a/output" + top: "inception_5b/3x3_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 192 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.09 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_3x3_reduce" + type: "ReLU" + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3_reduce" +} +layer { + name: "inception_5b/3x3" + type: "Convolution" + bottom: "inception_5b/3x3_reduce" + top: "inception_5b/3x3" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 384 + pad: 1 + kernel_size: 3 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_3x3" + type: "ReLU" + bottom: "inception_5b/3x3" + top: "inception_5b/3x3" +} +layer { + name: "inception_5b/5x5_reduce" + type: "Convolution" + bottom: "inception_5a/output" + top: "inception_5b/5x5_reduce" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 48 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.2 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_5x5_reduce" + type: "ReLU" + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5_reduce" +} +layer { + name: "inception_5b/5x5" + type: "Convolution" + bottom: "inception_5b/5x5_reduce" + top: "inception_5b/5x5" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + pad: 2 + kernel_size: 5 + weight_filler { + type: "xavier" + std: 0.03 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_5x5" + type: "ReLU" + bottom: "inception_5b/5x5" + top: "inception_5b/5x5" +} +layer { + name: "inception_5b/pool" + type: "Pooling" + bottom: "inception_5a/output" + top: "inception_5b/pool" + pooling_param { + pool: MAX + kernel_size: 3 + stride: 1 + pad: 1 + } +} +layer { + name: "inception_5b/pool_proj" + type: "Convolution" + bottom: "inception_5b/pool" + top: "inception_5b/pool_proj" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + convolution_param { + num_output: 128 + kernel_size: 1 + weight_filler { + type: "xavier" + std: 0.1 + } + bias_filler { + type: "constant" + value: 0.2 + } + } +} +layer { + name: "inception_5b/relu_pool_proj" + type: "ReLU" + bottom: "inception_5b/pool_proj" + top: "inception_5b/pool_proj" +} +layer { + name: "inception_5b/output" + type: "Concat" + bottom: "inception_5b/1x1" + bottom: "inception_5b/3x3" + bottom: "inception_5b/5x5" + bottom: "inception_5b/pool_proj" + top: "inception_5b/output" +} +layer { + name: "pool5/7x7_s1" + type: "Pooling" + bottom: "inception_5b/output" + top: "pool5/7x7_s1" + pooling_param { + pool: AVE + kernel_size: 7 + stride: 1 + } +} +layer { + name: "pool5/drop_7x7_s1" + type: "Dropout" + bottom: "pool5/7x7_s1" + top: "pool5/7x7_s1" + dropout_param { + dropout_ratio: 0.4 + } +} +layer { + name: "loss3/classifier" + type: "InnerProduct" + bottom: "pool5/7x7_s1" + top: "loss3/classifier" + param { + lr_mult: 1 + decay_mult: 1 + } + param { + lr_mult: 2 + decay_mult: 0 + } + inner_product_param { + num_output: 1000 + weight_filler { + type: "xavier" + } + bias_filler { + type: "constant" + value: 0 + } + } +} +layer { + name: "prob" + type: "Softmax" + bottom: "loss3/classifier" + top: "prob" +} diff --git a/modules/dnn/samples/caffe_googlenet.cpp b/modules/dnn/samples/caffe_googlenet.cpp new file mode 100644 index 000000000..0901cb560 --- /dev/null +++ b/modules/dnn/samples/caffe_googlenet.cpp @@ -0,0 +1,154 @@ +/**M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ +#include +#include +#include +using namespace cv; +using namespace cv::dnn; + +#include +#include +#include +using namespace std; + +/* Find best class for the blob (i. e. class with maximal probability) */ +void getMaxClass(dnn::Blob &probBlob, int *classId, double *classProb) +{ + Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix + Point classNumber; + + minMaxLoc(probMat, NULL, classProb, NULL, &classNumber); + *classId = classNumber.x; +} + +std::vector readClassNames(const char *filename = "synset_words.txt") +{ + std::vector classNames; + + std::ifstream fp(filename); + if (!fp.is_open()) + { + std::cerr << "File with classes labels not found: " << filename << std::endl; + exit(-1); + } + + std::string name; + while (!fp.eof()) + { + std::getline(fp, name); + if (name.length()) + classNames.push_back( name.substr(name.find(' ')+1) ); + } + + fp.close(); + return classNames; +} + +int main(int argc, char **argv) +{ + String modelTxt = "bvlc_googlenet.prototxt"; + String modelBin = "bvlc_googlenet.caffemodel"; + String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg"; + + //! [Create the importer of Caffe model] + Ptr importer; + try //Try to import Caffe GoogleNet model + { + importer = dnn::createCaffeImporter(modelTxt, modelBin); + } + catch (const cv::Exception &err) //Importer can throw errors, we will catch them + { + std::cerr << err.msg << std::endl; + } + //! [Create the importer of Caffe model] + + if (!importer) + { + std::cerr << "Can't load network by using the following files: " << std::endl; + std::cerr << "prototxt: " << modelTxt << std::endl; + std::cerr << "caffemodel: " << modelBin << std::endl; + std::cerr << "bvlc_googlenet.caffemodel can be downloaded here:" << std::endl; + std::cerr << "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" << std::endl; + exit(-1); + } + + //! [Initialize network] + dnn::Net net; + importer->populateNet(net); + importer.release(); //We don't need importer anymore + //! [Initialize network] + + //! [Prepare blob] + Mat img = imread(imageFile); + if (img.empty()) + { + std::cerr << "Can't read image from the file: " << imageFile << std::endl; + exit(-1); + } + + resize(img, img, Size(224, 224)); //GoogLeNet accepts only 224x224 RGB-images + dnn::Blob inputBlob = dnn::Blob(img); //Convert Mat to dnn::Blob image batch + //! [Prepare blob] + + //! [Set input blob] + net.setBlob(".data", inputBlob); //set the network input + //! [Set input blob] + + //! [Make forward pass] + net.forward(); //compute output + //! [Make forward pass] + + //! [Gather output] + dnn::Blob prob = net.getBlob("prob"); //gather output of "prob" layer + + int classId; + double classProb; + getMaxClass(prob, &classId, &classProb);//find the best class + //! [Gather output] + + //! [Print results] + std::vector classNames = readClassNames(); + std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl; + std::cout << "Probability: " << classProb * 100 << "%" << std::endl; + //! [Print results] + + return 0; +} //main diff --git a/modules/dnn/samples/space_shuttle.jpg b/modules/dnn/samples/space_shuttle.jpg new file mode 100644 index 000000000..412a91969 Binary files /dev/null and b/modules/dnn/samples/space_shuttle.jpg differ diff --git a/modules/dnn/samples/synset_words.txt b/modules/dnn/samples/synset_words.txt new file mode 100644 index 000000000..a9e8c7f50 --- /dev/null +++ b/modules/dnn/samples/synset_words.txt @@ -0,0 +1,1000 @@ +n01440764 tench, Tinca tinca +n01443537 goldfish, Carassius auratus +n01484850 great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias +n01491361 tiger shark, Galeocerdo cuvieri +n01494475 hammerhead, hammerhead shark +n01496331 electric ray, crampfish, numbfish, torpedo +n01498041 stingray +n01514668 cock +n01514859 hen +n01518878 ostrich, Struthio camelus +n01530575 brambling, Fringilla montifringilla +n01531178 goldfinch, Carduelis carduelis +n01532829 house finch, linnet, Carpodacus mexicanus +n01534433 junco, snowbird +n01537544 indigo bunting, indigo finch, indigo bird, Passerina cyanea +n01558993 robin, American robin, Turdus migratorius +n01560419 bulbul +n01580077 jay +n01582220 magpie +n01592084 chickadee +n01601694 water ouzel, dipper +n01608432 kite +n01614925 bald eagle, American eagle, Haliaeetus leucocephalus +n01616318 vulture +n01622779 great grey owl, great gray owl, Strix nebulosa +n01629819 European fire salamander, Salamandra salamandra +n01630670 common newt, Triturus vulgaris +n01631663 eft +n01632458 spotted salamander, Ambystoma maculatum +n01632777 axolotl, mud puppy, Ambystoma mexicanum +n01641577 bullfrog, Rana catesbeiana +n01644373 tree frog, tree-frog +n01644900 tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui +n01664065 loggerhead, loggerhead turtle, Caretta caretta +n01665541 leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea +n01667114 mud turtle +n01667778 terrapin +n01669191 box turtle, box tortoise +n01675722 banded gecko +n01677366 common iguana, iguana, Iguana iguana +n01682714 American chameleon, anole, Anolis carolinensis +n01685808 whiptail, whiptail lizard +n01687978 agama +n01688243 frilled lizard, Chlamydosaurus kingi +n01689811 alligator lizard +n01692333 Gila monster, Heloderma suspectum +n01693334 green lizard, Lacerta viridis +n01694178 African chameleon, Chamaeleo chamaeleon +n01695060 Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis +n01697457 African crocodile, Nile crocodile, Crocodylus niloticus +n01698640 American alligator, Alligator mississipiensis +n01704323 triceratops +n01728572 thunder snake, worm snake, Carphophis amoenus +n01728920 ringneck snake, ring-necked snake, ring snake +n01729322 hognose snake, puff adder, sand viper +n01729977 green snake, grass snake +n01734418 king snake, kingsnake +n01735189 garter snake, grass snake +n01737021 water snake +n01739381 vine snake +n01740131 night snake, Hypsiglena torquata +n01742172 boa constrictor, Constrictor constrictor +n01744401 rock python, rock snake, Python sebae +n01748264 Indian cobra, Naja naja +n01749939 green mamba +n01751748 sea snake +n01753488 horned viper, cerastes, sand viper, horned asp, Cerastes cornutus +n01755581 diamondback, diamondback rattlesnake, Crotalus adamanteus +n01756291 sidewinder, horned rattlesnake, Crotalus cerastes +n01768244 trilobite +n01770081 harvestman, daddy longlegs, Phalangium opilio +n01770393 scorpion +n01773157 black and gold garden spider, Argiope aurantia +n01773549 barn spider, Araneus cavaticus +n01773797 garden spider, Aranea diademata +n01774384 black widow, Latrodectus mactans +n01774750 tarantula +n01775062 wolf spider, hunting spider +n01776313 tick +n01784675 centipede +n01795545 black grouse +n01796340 ptarmigan +n01797886 ruffed grouse, partridge, Bonasa umbellus +n01798484 prairie chicken, prairie grouse, prairie fowl +n01806143 peacock +n01806567 quail +n01807496 partridge +n01817953 African grey, African gray, Psittacus erithacus +n01818515 macaw +n01819313 sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita +n01820546 lorikeet +n01824575 coucal +n01828970 bee eater +n01829413 hornbill +n01833805 hummingbird +n01843065 jacamar +n01843383 toucan +n01847000 drake +n01855032 red-breasted merganser, Mergus serrator +n01855672 goose +n01860187 black swan, Cygnus atratus +n01871265 tusker +n01872401 echidna, spiny anteater, anteater +n01873310 platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus +n01877812 wallaby, brush kangaroo +n01882714 koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus +n01883070 wombat +n01910747 jellyfish +n01914609 sea anemone, anemone +n01917289 brain coral +n01924916 flatworm, platyhelminth +n01930112 nematode, nematode worm, roundworm +n01943899 conch +n01944390 snail +n01945685 slug +n01950731 sea slug, nudibranch +n01955084 chiton, coat-of-mail shell, sea cradle, polyplacophore +n01968897 chambered nautilus, pearly nautilus, nautilus +n01978287 Dungeness crab, Cancer magister +n01978455 rock crab, Cancer irroratus +n01980166 fiddler crab +n01981276 king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica +n01983481 American lobster, Northern lobster, Maine lobster, Homarus americanus +n01984695 spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish +n01985128 crayfish, crawfish, crawdad, crawdaddy +n01986214 hermit crab +n01990800 isopod +n02002556 white stork, Ciconia ciconia +n02002724 black stork, Ciconia nigra +n02006656 spoonbill +n02007558 flamingo +n02009229 little blue heron, Egretta caerulea +n02009912 American egret, great white heron, Egretta albus +n02011460 bittern +n02012849 crane +n02013706 limpkin, Aramus pictus +n02017213 European gallinule, Porphyrio porphyrio +n02018207 American coot, marsh hen, mud hen, water hen, Fulica americana +n02018795 bustard +n02025239 ruddy turnstone, Arenaria interpres +n02027492 red-backed sandpiper, dunlin, Erolia alpina +n02028035 redshank, Tringa totanus +n02033041 dowitcher +n02037110 oystercatcher, oyster catcher +n02051845 pelican +n02056570 king penguin, Aptenodytes patagonica +n02058221 albatross, mollymawk +n02066245 grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus +n02071294 killer whale, killer, orca, grampus, sea wolf, Orcinus orca +n02074367 dugong, Dugong dugon +n02077923 sea lion +n02085620 Chihuahua +n02085782 Japanese spaniel +n02085936 Maltese dog, Maltese terrier, Maltese +n02086079 Pekinese, Pekingese, Peke +n02086240 Shih-Tzu +n02086646 Blenheim spaniel +n02086910 papillon +n02087046 toy terrier +n02087394 Rhodesian ridgeback +n02088094 Afghan hound, Afghan +n02088238 basset, basset hound +n02088364 beagle +n02088466 bloodhound, sleuthhound +n02088632 bluetick +n02089078 black-and-tan coonhound +n02089867 Walker hound, Walker foxhound +n02089973 English foxhound +n02090379 redbone +n02090622 borzoi, Russian wolfhound +n02090721 Irish wolfhound +n02091032 Italian greyhound +n02091134 whippet +n02091244 Ibizan hound, Ibizan Podenco +n02091467 Norwegian elkhound, elkhound +n02091635 otterhound, otter hound +n02091831 Saluki, gazelle hound +n02092002 Scottish deerhound, deerhound +n02092339 Weimaraner +n02093256 Staffordshire bullterrier, Staffordshire bull terrier +n02093428 American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier +n02093647 Bedlington terrier +n02093754 Border terrier +n02093859 Kerry blue terrier +n02093991 Irish terrier +n02094114 Norfolk terrier +n02094258 Norwich terrier +n02094433 Yorkshire terrier +n02095314 wire-haired fox terrier +n02095570 Lakeland terrier +n02095889 Sealyham terrier, Sealyham +n02096051 Airedale, Airedale terrier +n02096177 cairn, cairn terrier +n02096294 Australian terrier +n02096437 Dandie Dinmont, Dandie Dinmont terrier +n02096585 Boston bull, Boston terrier +n02097047 miniature schnauzer +n02097130 giant schnauzer +n02097209 standard schnauzer +n02097298 Scotch terrier, Scottish terrier, Scottie +n02097474 Tibetan terrier, chrysanthemum dog +n02097658 silky terrier, Sydney silky +n02098105 soft-coated wheaten terrier +n02098286 West Highland white terrier +n02098413 Lhasa, Lhasa apso +n02099267 flat-coated retriever +n02099429 curly-coated retriever +n02099601 golden retriever +n02099712 Labrador retriever +n02099849 Chesapeake Bay retriever +n02100236 German short-haired pointer +n02100583 vizsla, Hungarian pointer +n02100735 English setter +n02100877 Irish setter, red setter +n02101006 Gordon setter +n02101388 Brittany spaniel +n02101556 clumber, clumber spaniel +n02102040 English springer, English springer spaniel +n02102177 Welsh springer spaniel +n02102318 cocker spaniel, English cocker spaniel, cocker +n02102480 Sussex spaniel +n02102973 Irish water spaniel +n02104029 kuvasz +n02104365 schipperke +n02105056 groenendael +n02105162 malinois +n02105251 briard +n02105412 kelpie +n02105505 komondor +n02105641 Old English sheepdog, bobtail +n02105855 Shetland sheepdog, Shetland sheep dog, Shetland +n02106030 collie +n02106166 Border collie +n02106382 Bouvier des Flandres, Bouviers des Flandres +n02106550 Rottweiler +n02106662 German shepherd, German shepherd dog, German police dog, alsatian +n02107142 Doberman, Doberman pinscher +n02107312 miniature pinscher +n02107574 Greater Swiss Mountain dog +n02107683 Bernese mountain dog +n02107908 Appenzeller +n02108000 EntleBucher +n02108089 boxer +n02108422 bull mastiff +n02108551 Tibetan mastiff +n02108915 French bulldog +n02109047 Great Dane +n02109525 Saint Bernard, St Bernard +n02109961 Eskimo dog, husky +n02110063 malamute, malemute, Alaskan malamute +n02110185 Siberian husky +n02110341 dalmatian, coach dog, carriage dog +n02110627 affenpinscher, monkey pinscher, monkey dog +n02110806 basenji +n02110958 pug, pug-dog +n02111129 Leonberg +n02111277 Newfoundland, Newfoundland dog +n02111500 Great Pyrenees +n02111889 Samoyed, Samoyede +n02112018 Pomeranian +n02112137 chow, chow chow +n02112350 keeshond +n02112706 Brabancon griffon +n02113023 Pembroke, Pembroke Welsh corgi +n02113186 Cardigan, Cardigan Welsh corgi +n02113624 toy poodle +n02113712 miniature poodle +n02113799 standard poodle +n02113978 Mexican hairless +n02114367 timber wolf, grey wolf, gray wolf, Canis lupus +n02114548 white wolf, Arctic wolf, Canis lupus tundrarum +n02114712 red wolf, maned wolf, Canis rufus, Canis niger +n02114855 coyote, prairie wolf, brush wolf, Canis latrans +n02115641 dingo, warrigal, warragal, Canis dingo +n02115913 dhole, Cuon alpinus +n02116738 African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus +n02117135 hyena, hyaena +n02119022 red fox, Vulpes vulpes +n02119789 kit fox, Vulpes macrotis +n02120079 Arctic fox, white fox, Alopex lagopus +n02120505 grey fox, gray fox, Urocyon cinereoargenteus +n02123045 tabby, tabby cat +n02123159 tiger cat +n02123394 Persian cat +n02123597 Siamese cat, Siamese +n02124075 Egyptian cat +n02125311 cougar, puma, catamount, mountain lion, painter, panther, Felis concolor +n02127052 lynx, catamount +n02128385 leopard, Panthera pardus +n02128757 snow leopard, ounce, Panthera uncia +n02128925 jaguar, panther, Panthera onca, Felis onca +n02129165 lion, king of beasts, Panthera leo +n02129604 tiger, Panthera tigris +n02130308 cheetah, chetah, Acinonyx jubatus +n02132136 brown bear, bruin, Ursus arctos +n02133161 American black bear, black bear, Ursus americanus, Euarctos americanus +n02134084 ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus +n02134418 sloth bear, Melursus ursinus, Ursus ursinus +n02137549 mongoose +n02138441 meerkat, mierkat +n02165105 tiger beetle +n02165456 ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle +n02167151 ground beetle, carabid beetle +n02168699 long-horned beetle, longicorn, longicorn beetle +n02169497 leaf beetle, chrysomelid +n02172182 dung beetle +n02174001 rhinoceros beetle +n02177972 weevil +n02190166 fly +n02206856 bee +n02219486 ant, emmet, pismire +n02226429 grasshopper, hopper +n02229544 cricket +n02231487 walking stick, walkingstick, stick insect +n02233338 cockroach, roach +n02236044 mantis, mantid +n02256656 cicada, cicala +n02259212 leafhopper +n02264363 lacewing, lacewing fly +n02268443 dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk +n02268853 damselfly +n02276258 admiral +n02277742 ringlet, ringlet butterfly +n02279972 monarch, monarch butterfly, milkweed butterfly, Danaus plexippus +n02280649 cabbage butterfly +n02281406 sulphur butterfly, sulfur butterfly +n02281787 lycaenid, lycaenid butterfly +n02317335 starfish, sea star +n02319095 sea urchin +n02321529 sea cucumber, holothurian +n02325366 wood rabbit, cottontail, cottontail rabbit +n02326432 hare +n02328150 Angora, Angora rabbit +n02342885 hamster +n02346627 porcupine, hedgehog +n02356798 fox squirrel, eastern fox squirrel, Sciurus niger +n02361337 marmot +n02363005 beaver +n02364673 guinea pig, Cavia cobaya +n02389026 sorrel +n02391049 zebra +n02395406 hog, pig, grunter, squealer, Sus scrofa +n02396427 wild boar, boar, Sus scrofa +n02397096 warthog +n02398521 hippopotamus, hippo, river horse, Hippopotamus amphibius +n02403003 ox +n02408429 water buffalo, water ox, Asiatic buffalo, Bubalus bubalis +n02410509 bison +n02412080 ram, tup +n02415577 bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis +n02417914 ibex, Capra ibex +n02422106 hartebeest +n02422699 impala, Aepyceros melampus +n02423022 gazelle +n02437312 Arabian camel, dromedary, Camelus dromedarius +n02437616 llama +n02441942 weasel +n02442845 mink +n02443114 polecat, fitch, foulmart, foumart, Mustela putorius +n02443484 black-footed ferret, ferret, Mustela nigripes +n02444819 otter +n02445715 skunk, polecat, wood pussy +n02447366 badger +n02454379 armadillo +n02457408 three-toed sloth, ai, Bradypus tridactylus +n02480495 orangutan, orang, orangutang, Pongo pygmaeus +n02480855 gorilla, Gorilla gorilla +n02481823 chimpanzee, chimp, Pan troglodytes +n02483362 gibbon, Hylobates lar +n02483708 siamang, Hylobates syndactylus, Symphalangus syndactylus +n02484975 guenon, guenon monkey +n02486261 patas, hussar monkey, Erythrocebus patas +n02486410 baboon +n02487347 macaque +n02488291 langur +n02488702 colobus, colobus monkey +n02489166 proboscis monkey, Nasalis larvatus +n02490219 marmoset +n02492035 capuchin, ringtail, Cebus capucinus +n02492660 howler monkey, howler +n02493509 titi, titi monkey +n02493793 spider monkey, Ateles geoffroyi +n02494079 squirrel monkey, Saimiri sciureus +n02497673 Madagascar cat, ring-tailed lemur, Lemur catta +n02500267 indri, indris, Indri indri, Indri brevicaudatus +n02504013 Indian elephant, Elephas maximus +n02504458 African elephant, Loxodonta africana +n02509815 lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens +n02510455 giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca +n02514041 barracouta, snoek +n02526121 eel +n02536864 coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch +n02606052 rock beauty, Holocanthus tricolor +n02607072 anemone fish +n02640242 sturgeon +n02641379 gar, garfish, garpike, billfish, Lepisosteus osseus +n02643566 lionfish +n02655020 puffer, pufferfish, blowfish, globefish +n02666196 abacus +n02667093 abaya +n02669723 academic gown, academic robe, judge's robe +n02672831 accordion, piano accordion, squeeze box +n02676566 acoustic guitar +n02687172 aircraft carrier, carrier, flattop, attack aircraft carrier +n02690373 airliner +n02692877 airship, dirigible +n02699494 altar +n02701002 ambulance +n02704792 amphibian, amphibious vehicle +n02708093 analog clock +n02727426 apiary, bee house +n02730930 apron +n02747177 ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin +n02749479 assault rifle, assault gun +n02769748 backpack, back pack, knapsack, packsack, rucksack, haversack +n02776631 bakery, bakeshop, bakehouse +n02777292 balance beam, beam +n02782093 balloon +n02783161 ballpoint, ballpoint pen, ballpen, Biro +n02786058 Band Aid +n02787622 banjo +n02788148 bannister, banister, balustrade, balusters, handrail +n02790996 barbell +n02791124 barber chair +n02791270 barbershop +n02793495 barn +n02794156 barometer +n02795169 barrel, cask +n02797295 barrow, garden cart, lawn cart, wheelbarrow +n02799071 baseball +n02802426 basketball +n02804414 bassinet +n02804610 bassoon +n02807133 bathing cap, swimming cap +n02808304 bath towel +n02808440 bathtub, bathing tub, bath, tub +n02814533 beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon +n02814860 beacon, lighthouse, beacon light, pharos +n02815834 beaker +n02817516 bearskin, busby, shako +n02823428 beer bottle +n02823750 beer glass +n02825657 bell cote, bell cot +n02834397 bib +n02835271 bicycle-built-for-two, tandem bicycle, tandem +n02837789 bikini, two-piece +n02840245 binder, ring-binder +n02841315 binoculars, field glasses, opera glasses +n02843684 birdhouse +n02859443 boathouse +n02860847 bobsled, bobsleigh, bob +n02865351 bolo tie, bolo, bola tie, bola +n02869837 bonnet, poke bonnet +n02870880 bookcase +n02871525 bookshop, bookstore, bookstall +n02877765 bottlecap +n02879718 bow +n02883205 bow tie, bow-tie, bowtie +n02892201 brass, memorial tablet, plaque +n02892767 brassiere, bra, bandeau +n02894605 breakwater, groin, groyne, mole, bulwark, seawall, jetty +n02895154 breastplate, aegis, egis +n02906734 broom +n02909870 bucket, pail +n02910353 buckle +n02916936 bulletproof vest +n02917067 bullet train, bullet +n02927161 butcher shop, meat market +n02930766 cab, hack, taxi, taxicab +n02939185 caldron, cauldron +n02948072 candle, taper, wax light +n02950826 cannon +n02951358 canoe +n02951585 can opener, tin opener +n02963159 cardigan +n02965783 car mirror +n02966193 carousel, carrousel, merry-go-round, roundabout, whirligig +n02966687 carpenter's kit, tool kit +n02971356 carton +n02974003 car wheel +n02977058 cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM +n02978881 cassette +n02979186 cassette player +n02980441 castle +n02981792 catamaran +n02988304 CD player +n02992211 cello, violoncello +n02992529 cellular telephone, cellular phone, cellphone, cell, mobile phone +n02999410 chain +n03000134 chainlink fence +n03000247 chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour +n03000684 chain saw, chainsaw +n03014705 chest +n03016953 chiffonier, commode +n03017168 chime, bell, gong +n03018349 china cabinet, china closet +n03026506 Christmas stocking +n03028079 church, church building +n03032252 cinema, movie theater, movie theatre, movie house, picture palace +n03041632 cleaver, meat cleaver, chopper +n03042490 cliff dwelling +n03045698 cloak +n03047690 clog, geta, patten, sabot +n03062245 cocktail shaker +n03063599 coffee mug +n03063689 coffeepot +n03065424 coil, spiral, volute, whorl, helix +n03075370 combination lock +n03085013 computer keyboard, keypad +n03089624 confectionery, confectionary, candy store +n03095699 container ship, containership, container vessel +n03100240 convertible +n03109150 corkscrew, bottle screw +n03110669 cornet, horn, trumpet, trump +n03124043 cowboy boot +n03124170 cowboy hat, ten-gallon hat +n03125729 cradle +n03126707 crane +n03127747 crash helmet +n03127925 crate +n03131574 crib, cot +n03133878 Crock Pot +n03134739 croquet ball +n03141823 crutch +n03146219 cuirass +n03160309 dam, dike, dyke +n03179701 desk +n03180011 desktop computer +n03187595 dial telephone, dial phone +n03188531 diaper, nappy, napkin +n03196217 digital clock +n03197337 digital watch +n03201208 dining table, board +n03207743 dishrag, dishcloth +n03207941 dishwasher, dish washer, dishwashing machine +n03208938 disk brake, disc brake +n03216828 dock, dockage, docking facility +n03218198 dogsled, dog sled, dog sleigh +n03220513 dome +n03223299 doormat, welcome mat +n03240683 drilling platform, offshore rig +n03249569 drum, membranophone, tympan +n03250847 drumstick +n03255030 dumbbell +n03259280 Dutch oven +n03271574 electric fan, blower +n03272010 electric guitar +n03272562 electric locomotive +n03290653 entertainment center +n03291819 envelope +n03297495 espresso maker +n03314780 face powder +n03325584 feather boa, boa +n03337140 file, file cabinet, filing cabinet +n03344393 fireboat +n03345487 fire engine, fire truck +n03347037 fire screen, fireguard +n03355925 flagpole, flagstaff +n03372029 flute, transverse flute +n03376595 folding chair +n03379051 football helmet +n03384352 forklift +n03388043 fountain +n03388183 fountain pen +n03388549 four-poster +n03393912 freight car +n03394916 French horn, horn +n03400231 frying pan, frypan, skillet +n03404251 fur coat +n03417042 garbage truck, dustcart +n03424325 gasmask, respirator, gas helmet +n03425413 gas pump, gasoline pump, petrol pump, island dispenser +n03443371 goblet +n03444034 go-kart +n03445777 golf ball +n03445924 golfcart, golf cart +n03447447 gondola +n03447721 gong, tam-tam +n03450230 gown +n03452741 grand piano, grand +n03457902 greenhouse, nursery, glasshouse +n03459775 grille, radiator grille +n03461385 grocery store, grocery, food market, market +n03467068 guillotine +n03476684 hair slide +n03476991 hair spray +n03478589 half track +n03481172 hammer +n03482405 hamper +n03483316 hand blower, blow dryer, blow drier, hair dryer, hair drier +n03485407 hand-held computer, hand-held microcomputer +n03485794 handkerchief, hankie, hanky, hankey +n03492542 hard disc, hard disk, fixed disk +n03494278 harmonica, mouth organ, harp, mouth harp +n03495258 harp +n03496892 harvester, reaper +n03498962 hatchet +n03527444 holster +n03529860 home theater, home theatre +n03530642 honeycomb +n03532672 hook, claw +n03534580 hoopskirt, crinoline +n03535780 horizontal bar, high bar +n03538406 horse cart, horse-cart +n03544143 hourglass +n03584254 iPod +n03584829 iron, smoothing iron +n03590841 jack-o'-lantern +n03594734 jean, blue jean, denim +n03594945 jeep, landrover +n03595614 jersey, T-shirt, tee shirt +n03598930 jigsaw puzzle +n03599486 jinrikisha, ricksha, rickshaw +n03602883 joystick +n03617480 kimono +n03623198 knee pad +n03627232 knot +n03630383 lab coat, laboratory coat +n03633091 ladle +n03637318 lampshade, lamp shade +n03642806 laptop, laptop computer +n03649909 lawn mower, mower +n03657121 lens cap, lens cover +n03658185 letter opener, paper knife, paperknife +n03661043 library +n03662601 lifeboat +n03666591 lighter, light, igniter, ignitor +n03670208 limousine, limo +n03673027 liner, ocean liner +n03676483 lipstick, lip rouge +n03680355 Loafer +n03690938 lotion +n03691459 loudspeaker, speaker, speaker unit, loudspeaker system, speaker system +n03692522 loupe, jeweler's loupe +n03697007 lumbermill, sawmill +n03706229 magnetic compass +n03709823 mailbag, postbag +n03710193 mailbox, letter box +n03710637 maillot +n03710721 maillot, tank suit +n03717622 manhole cover +n03720891 maraca +n03721384 marimba, xylophone +n03724870 mask +n03729826 matchstick +n03733131 maypole +n03733281 maze, labyrinth +n03733805 measuring cup +n03742115 medicine chest, medicine cabinet +n03743016 megalith, megalithic structure +n03759954 microphone, mike +n03761084 microwave, microwave oven +n03763968 military uniform +n03764736 milk can +n03769881 minibus +n03770439 miniskirt, mini +n03770679 minivan +n03773504 missile +n03775071 mitten +n03775546 mixing bowl +n03776460 mobile home, manufactured home +n03777568 Model T +n03777754 modem +n03781244 monastery +n03782006 monitor +n03785016 moped +n03786901 mortar +n03787032 mortarboard +n03788195 mosque +n03788365 mosquito net +n03791053 motor scooter, scooter +n03792782 mountain bike, all-terrain bike, off-roader +n03792972 mountain tent +n03793489 mouse, computer mouse +n03794056 mousetrap +n03796401 moving van +n03803284 muzzle +n03804744 nail +n03814639 neck brace +n03814906 necklace +n03825788 nipple +n03832673 notebook, notebook computer +n03837869 obelisk +n03838899 oboe, hautboy, hautbois +n03840681 ocarina, sweet potato +n03841143 odometer, hodometer, mileometer, milometer +n03843555 oil filter +n03854065 organ, pipe organ +n03857828 oscilloscope, scope, cathode-ray oscilloscope, CRO +n03866082 overskirt +n03868242 oxcart +n03868863 oxygen mask +n03871628 packet +n03873416 paddle, boat paddle +n03874293 paddlewheel, paddle wheel +n03874599 padlock +n03876231 paintbrush +n03877472 pajama, pyjama, pj's, jammies +n03877845 palace +n03884397 panpipe, pandean pipe, syrinx +n03887697 paper towel +n03888257 parachute, chute +n03888605 parallel bars, bars +n03891251 park bench +n03891332 parking meter +n03895866 passenger car, coach, carriage +n03899768 patio, terrace +n03902125 pay-phone, pay-station +n03903868 pedestal, plinth, footstall +n03908618 pencil box, pencil case +n03908714 pencil sharpener +n03916031 perfume, essence +n03920288 Petri dish +n03924679 photocopier +n03929660 pick, plectrum, plectron +n03929855 pickelhaube +n03930313 picket fence, paling +n03930630 pickup, pickup truck +n03933933 pier +n03935335 piggy bank, penny bank +n03937543 pill bottle +n03938244 pillow +n03942813 ping-pong ball +n03944341 pinwheel +n03947888 pirate, pirate ship +n03950228 pitcher, ewer +n03954731 plane, carpenter's plane, woodworking plane +n03956157 planetarium +n03958227 plastic bag +n03961711 plate rack +n03967562 plow, plough +n03970156 plunger, plumber's helper +n03976467 Polaroid camera, Polaroid Land camera +n03976657 pole +n03977966 police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria +n03980874 poncho +n03982430 pool table, billiard table, snooker table +n03983396 pop bottle, soda bottle +n03991062 pot, flowerpot +n03992509 potter's wheel +n03995372 power drill +n03998194 prayer rug, prayer mat +n04004767 printer +n04005630 prison, prison house +n04008634 projectile, missile +n04009552 projector +n04019541 puck, hockey puck +n04023962 punching bag, punch bag, punching ball, punchball +n04026417 purse +n04033901 quill, quill pen +n04033995 quilt, comforter, comfort, puff +n04037443 racer, race car, racing car +n04039381 racket, racquet +n04040759 radiator +n04041544 radio, wireless +n04044716 radio telescope, radio reflector +n04049303 rain barrel +n04065272 recreational vehicle, RV, R.V. +n04067472 reel +n04069434 reflex camera +n04070727 refrigerator, icebox +n04074963 remote control, remote +n04081281 restaurant, eating house, eating place, eatery +n04086273 revolver, six-gun, six-shooter +n04090263 rifle +n04099969 rocking chair, rocker +n04111531 rotisserie +n04116512 rubber eraser, rubber, pencil eraser +n04118538 rugby ball +n04118776 rule, ruler +n04120489 running shoe +n04125021 safe +n04127249 safety pin +n04131690 saltshaker, salt shaker +n04133789 sandal +n04136333 sarong +n04141076 sax, saxophone +n04141327 scabbard +n04141975 scale, weighing machine +n04146614 school bus +n04147183 schooner +n04149813 scoreboard +n04152593 screen, CRT screen +n04153751 screw +n04154565 screwdriver +n04162706 seat belt, seatbelt +n04179913 sewing machine +n04192698 shield, buckler +n04200800 shoe shop, shoe-shop, shoe store +n04201297 shoji +n04204238 shopping basket +n04204347 shopping cart +n04208210 shovel +n04209133 shower cap +n04209239 shower curtain +n04228054 ski +n04229816 ski mask +n04235860 sleeping bag +n04238763 slide rule, slipstick +n04239074 sliding door +n04243546 slot, one-armed bandit +n04251144 snorkel +n04252077 snowmobile +n04252225 snowplow, snowplough +n04254120 soap dispenser +n04254680 soccer ball +n04254777 sock +n04258138 solar dish, solar collector, solar furnace +n04259630 sombrero +n04263257 soup bowl +n04264628 space bar +n04265275 space heater +n04266014 space shuttle +n04270147 spatula +n04273569 speedboat +n04275548 spider web, spider's web +n04277352 spindle +n04285008 sports car, sport car +n04286575 spotlight, spot +n04296562 stage +n04310018 steam locomotive +n04311004 steel arch bridge +n04311174 steel drum +n04317175 stethoscope +n04325704 stole +n04326547 stone wall +n04328186 stopwatch, stop watch +n04330267 stove +n04332243 strainer +n04335435 streetcar, tram, tramcar, trolley, trolley car +n04336792 stretcher +n04344873 studio couch, day bed +n04346328 stupa, tope +n04347754 submarine, pigboat, sub, U-boat +n04350905 suit, suit of clothes +n04355338 sundial +n04355933 sunglass +n04356056 sunglasses, dark glasses, shades +n04357314 sunscreen, sunblock, sun blocker +n04366367 suspension bridge +n04367480 swab, swob, mop +n04370456 sweatshirt +n04371430 swimming trunks, bathing trunks +n04371774 swing +n04372370 switch, electric switch, electrical switch +n04376876 syringe +n04380533 table lamp +n04389033 tank, army tank, armored combat vehicle, armoured combat vehicle +n04392985 tape player +n04398044 teapot +n04399382 teddy, teddy bear +n04404412 television, television system +n04409515 tennis ball +n04417672 thatch, thatched roof +n04418357 theater curtain, theatre curtain +n04423845 thimble +n04428191 thresher, thrasher, threshing machine +n04429376 throne +n04435653 tile roof +n04442312 toaster +n04443257 tobacco shop, tobacconist shop, tobacconist +n04447861 toilet seat +n04456115 torch +n04458633 totem pole +n04461696 tow truck, tow car, wrecker +n04462240 toyshop +n04465501 tractor +n04467665 trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi +n04476259 tray +n04479046 trench coat +n04482393 tricycle, trike, velocipede +n04483307 trimaran +n04485082 tripod +n04486054 triumphal arch +n04487081 trolleybus, trolley coach, trackless trolley +n04487394 trombone +n04493381 tub, vat +n04501370 turnstile +n04505470 typewriter keyboard +n04507155 umbrella +n04509417 unicycle, monocycle +n04515003 upright, upright piano +n04517823 vacuum, vacuum cleaner +n04522168 vase +n04523525 vault +n04525038 velvet +n04525305 vending machine +n04532106 vestment +n04532670 viaduct +n04536866 violin, fiddle +n04540053 volleyball +n04542943 waffle iron +n04548280 wall clock +n04548362 wallet, billfold, notecase, pocketbook +n04550184 wardrobe, closet, press +n04552348 warplane, military plane +n04553703 washbasin, handbasin, washbowl, lavabo, wash-hand basin +n04554684 washer, automatic washer, washing machine +n04557648 water bottle +n04560804 water jug +n04562935 water tower +n04579145 whiskey jug +n04579432 whistle +n04584207 wig +n04589890 window screen +n04590129 window shade +n04591157 Windsor tie +n04591713 wine bottle +n04592741 wing +n04596742 wok +n04597913 wooden spoon +n04599235 wool, woolen, woollen +n04604644 worm fence, snake fence, snake-rail fence, Virginia fence +n04606251 wreck +n04612504 yawl +n04613696 yurt +n06359193 web site, website, internet site, site +n06596364 comic book +n06785654 crossword puzzle, crossword +n06794110 street sign +n06874185 traffic light, traffic signal, stoplight +n07248320 book jacket, dust cover, dust jacket, dust wrapper +n07565083 menu +n07579787 plate +n07583066 guacamole +n07584110 consomme +n07590611 hot pot, hotpot +n07613480 trifle +n07614500 ice cream, icecream +n07615774 ice lolly, lolly, lollipop, popsicle +n07684084 French loaf +n07693725 bagel, beigel +n07695742 pretzel +n07697313 cheeseburger +n07697537 hotdog, hot dog, red hot +n07711569 mashed potato +n07714571 head cabbage +n07714990 broccoli +n07715103 cauliflower +n07716358 zucchini, courgette +n07716906 spaghetti squash +n07717410 acorn squash +n07717556 butternut squash +n07718472 cucumber, cuke +n07718747 artichoke, globe artichoke +n07720875 bell pepper +n07730033 cardoon +n07734744 mushroom +n07742313 Granny Smith +n07745940 strawberry +n07747607 orange +n07749582 lemon +n07753113 fig +n07753275 pineapple, ananas +n07753592 banana +n07754684 jackfruit, jak, jack +n07760859 custard apple +n07768694 pomegranate +n07802026 hay +n07831146 carbonara +n07836838 chocolate sauce, chocolate syrup +n07860988 dough +n07871810 meat loaf, meatloaf +n07873807 pizza, pizza pie +n07875152 potpie +n07880968 burrito +n07892512 red wine +n07920052 espresso +n07930864 cup +n07932039 eggnog +n09193705 alp +n09229709 bubble +n09246464 cliff, drop, drop-off +n09256479 coral reef +n09288635 geyser +n09332890 lakeside, lakeshore +n09399592 promontory, headland, head, foreland +n09421951 sandbar, sand bar +n09428293 seashore, coast, seacoast, sea-coast +n09468604 valley, vale +n09472597 volcano +n09835506 ballplayer, baseball player +n10148035 groom, bridegroom +n10565667 scuba diver +n11879895 rapeseed +n11939491 daisy +n12057211 yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum +n12144580 corn +n12267677 acorn +n12620546 hip, rose hip, rosehip +n12768682 buckeye, horse chestnut, conker +n12985857 coral fungus +n12998815 agaric +n13037406 gyromitra +n13040303 stinkhorn, carrion fungus +n13044778 earthstar +n13052670 hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa +n13054560 bolete +n13133613 ear, spike, capitulum +n15075141 toilet tissue, toilet paper, bathroom tissue diff --git a/modules/dnn/scripts/download_model.py b/modules/dnn/scripts/download_model.py new file mode 100644 index 000000000..d2951f5ea --- /dev/null +++ b/modules/dnn/scripts/download_model.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +import os +import sys +import time +import urllib +import hashlib +import argparse +import json + + +def reporthook(count, block_size, total_size): + """ + From http://blog.moleculea.com/2012/10/04/urlretrieve-progres-indicator/ + """ + global start_time + global prev_duration + if count == 0: + start_time = time.time() + prev_duration = -1 + return + duration = max(1, time.time() - start_time) + if int(duration) == int(prev_duration): + return + + progress_size = int(count * block_size) + speed = int(progress_size / (1024 * duration)) + percent = int(count * block_size * 100 / total_size) + sys.stdout.write("\r...%d%%, %d MB, %d KB/s, %d seconds passed" % + (percent, progress_size / (1024 * 1024), speed, duration)) + sys.stdout.flush() + prev_duration = duration + + +# Function for checking SHA1. +def model_checks_out(filename, sha1): + with open(filename, 'r') as f: + return hashlib.sha1(f.read()).hexdigest() == sha1 + +def model_download(filename, url, sha1): + # Check if model exists. + if os.path.exists(filename) and model_checks_out(filename, sha1): + print("Model {} already exists.".format(filename)) + return + + # Download and verify model. + urllib.urlretrieve(url, filename, reporthook) + print model_checks_out(filename, sha1) + if not model_checks_out(filename, sha1): + print("ERROR: model {} did not download correctly!".format(url)) + sys.exit(1) + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Downloading trained model binaries.") + parser.add_argument("download_list") + args = parser.parse_args() + + test_dir = os.environ.get("OPENCV_TEST_DATA_PATH") + if not test_dir: + print "ERROR: OPENCV_TEST_DATA_PATH environment not specified" + sys.exit(1) + + try: + with open(args.download_list, 'r') as f: + models_to_download = json.load(f) + except: + print "ERROR: Can't pasrse {}".format(args.download_list) + sys.exit(1) + + for model_name in models_to_download: + model = models_to_download[model_name] + + dst_dir = os.path.join(test_dir, os.path.dirname(model['file'])) + dst_file = os.path.join(test_dir, model['file']) + if not os.path.exists(dst_dir): + print "ERROR: Can't find module testdata path '{}'".format(dst_dir) + sys.exit(1) + + print "Downloading model '{}' to {} from {} ...".format(model_name, dst_file, model['url']) + model_download(dst_file, model['url'], model['sha1']) \ No newline at end of file diff --git a/modules/dnn/scripts/test_models.json b/modules/dnn/scripts/test_models.json new file mode 100644 index 000000000..47b131531 --- /dev/null +++ b/modules/dnn/scripts/test_models.json @@ -0,0 +1,7 @@ +{ + "googlenet": { + "file": "dnn/bvlc_googlenet.caffemodel", + "url": "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel", + "sha1": "405fc5acd08a3bb12de8ee5e23a96bec22f08204" + } +} \ No newline at end of file diff --git a/modules/dnn/src/blob.cpp b/modules/dnn/src/blob.cpp new file mode 100644 index 000000000..1ef47e082 --- /dev/null +++ b/modules/dnn/src/blob.cpp @@ -0,0 +1,218 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "precomp.hpp" + +namespace cv +{ +namespace dnn +{ + + Blob::Blob() + { + int zeros[4] = { 0, 0, 0, 0 }; + m = Mat(4, zeros, CV_32F, NULL); + } + + static inline int getMatChannels(const Mat &mat) + { + return (mat.dims <= 2) ? mat.channels() : mat.size[0]; + } + + static BlobShape getBlobShpae(std::vector &vmat, int requestedCn = -1) + { + BlobShape shape(4); + int cnSum = 0, matCn; + + CV_Assert(vmat.size() > 0); + + for (size_t i = 0; i < vmat.size(); i++) + { + Mat &mat = vmat[i]; + CV_Assert(!mat.empty()); + CV_Assert((mat.dims == 3 && mat.channels() == 1) || mat.dims <= 2); + + matCn = getMatChannels(mat); + cnSum += getMatChannels(mat); + + if (i == 0) + { + shape[-1] = mat.cols; + shape[-2] = mat.rows; + shape[-3] = (requestedCn <= 0) ? matCn : requestedCn; + } + else + { + if (mat.cols != shape[-1] || mat.rows != shape[-2]) + CV_Error(Error::StsError, "Each Mat.size() must be equal"); + + if (requestedCn <= 0 && matCn != shape[-3]) + CV_Error(Error::StsError, "Each Mat.chnannels() (or number of planes) must be equal"); + } + } + + if (cnSum % shape[-3] != 0) + CV_Error(Error::StsError, "Total number of channels in vector is not a multiple of requsted channel number"); + + shape[0] = cnSum / shape[-3]; + return shape; + } + + static std::vector extractMatVector(InputArray in) + { + if (in.isMat() || in.isUMat()) + { + return std::vector(1, in.getMat()); + } + else if (in.isMatVector()) + { + return *static_cast*>(in.getObj()); + } + else if (in.isUMatVector()) + { + std::vector vmat; + in.getMatVector(vmat); + return vmat; + } + else + { + CV_Assert(in.isMat() || in.isMatVector() || in.isUMat() || in.isUMatVector()); + return std::vector(); + } + } + + Blob::Blob(InputArray image, int dstCn) + { + CV_Assert(dstCn == -1 || dstCn > 0); + std::vector inMats = extractMatVector(image); + BlobShape dstShape = getBlobShpae(inMats, dstCn); + + m.create(dstShape.dims(), dstShape.ptr(), CV_32F); + + std::vector wrapBuf(dstShape[-3]); + int elemSize = (int)m.elemSize(); + uchar *ptr = this->ptr(); + for (size_t i = 0; i < inMats.size(); i++) + { + Mat inMat = inMats[i]; + + if (inMat.dims <= 2) + { + inMat.convertTo(inMat, m.type()); + + wrapBuf.resize(0); + for (int cn = 0; cn < inMat.channels(); cn++) + { + wrapBuf.push_back(Mat(inMat.rows, inMat.cols, m.type(), ptr)); + ptr += elemSize * inMat.total(); + } + + cv::split(inMat, wrapBuf); + } + else + { + inMat.convertTo(Mat(inMat.dims, inMat.size, m.type(), ptr), m.type()); + ptr += elemSize * inMat.total(); + } + } + } + + Blob::Blob(const BlobShape &shape, int type) + { + this->create(shape, type); + } + + void Blob::fill(const BlobShape &shape, int type, void *data, bool deepCopy) + { + CV_Assert(type == CV_32F || type == CV_64F); + + if (deepCopy) + { + m.create(shape.dims(), shape.ptr(), type); + memcpy(m.data, data, m.total() * m.elemSize()); + } + else + { + m = Mat(shape.dims(), shape.ptr(), type, data); + } + } + + void Blob::create(const BlobShape &shape, int type) + { + CV_Assert(type == CV_32F || type == CV_64F); + m.create(shape.dims(), shape.ptr(), type); + } + + inline void squeezeShape(const int srcDims, const int *srcSizes, const int dstDims, int *dstSizes) + { + const int m = std::min(dstDims, srcDims); + + //copy common(last) dimensions + for (int i = 0; i < m; i++) + dstSizes[dstDims - 1 - i] = srcSizes[srcDims - 1 - i]; + + //either flatten extra dimensions + for (int i = m; i < srcDims; i++) + dstSizes[0] *= srcSizes[srcDims - 1 - i]; + + //either fill gaps + for (int i = m; i < dstDims; i++) + dstSizes[dstDims - 1 - i] = 1; + } + + Vec4i Blob::shape4() const + { + return Vec4i(num(), channels(), rows(), cols()); + } + + std::ostream &operator<< (std::ostream &stream, const BlobShape &shape) + { + stream << "["; + + for (int i = 0; i < shape.dims() - 1; i++) + stream << shape[i] << ", "; + if (shape.dims() > 0) + stream << shape[-1]; + + return stream << "]"; + } +} +} diff --git a/modules/dnn/src/caffe/caffe.proto b/modules/dnn/src/caffe/caffe.proto new file mode 100644 index 000000000..81098218a --- /dev/null +++ b/modules/dnn/src/caffe/caffe.proto @@ -0,0 +1,1157 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +//COPYRIGHT +// +//All contributions by the University of California: +//Copyright (c) 2014, The Regents of the University of California (Regents) +//All rights reserved. +// +//All other contributions: +//Copyright (c) 2014, the respective contributors +//All rights reserved. +// +//Caffe uses a shared copyright model: each contributor holds copyright over +//their contributions to Caffe. The project versioning records all such +//contribution and copyright details. If a contributor wants to further mark +//their specific copyright on a particular contribution, they should indicate +//their copyright solely in the commit message of the change when it is +//committed. +// +//LICENSE +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +// +//1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +//2. 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. +// +//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. +// +//CONTRIBUTION AGREEMENT +// +//By contributing to the BVLC/caffe repository through pull-request, comment, +//or otherwise, the contributor releases their content to the +//license and copyright terms herein. +// +//M*/ + +syntax = "proto2"; + +package caffe; + +// Specifies the shape (dimensions) of a Blob. +message BlobShape { + repeated int64 dim = 1 [packed = true]; +} + +message BlobProto { + optional BlobShape shape = 7; + repeated float data = 5 [packed = true]; + repeated float diff = 6 [packed = true]; + + // 4D dimensions -- deprecated. Use "shape" instead. + optional int32 num = 1 [default = 0]; + optional int32 channels = 2 [default = 0]; + optional int32 height = 3 [default = 0]; + optional int32 width = 4 [default = 0]; +} + +// The BlobProtoVector is simply a way to pass multiple blobproto instances +// around. +message BlobProtoVector { + repeated BlobProto blobs = 1; +} + +message Datum { + optional int32 channels = 1; + optional int32 height = 2; + optional int32 width = 3; + // the actual image data, in bytes + optional bytes data = 4; + optional int32 label = 5; + // Optionally, the datum could also hold float data. + repeated float float_data = 6; + // If true data contains an encoded image that need to be decoded + optional bool encoded = 7 [default = false]; +} + +message FillerParameter { + // The filler type. + optional string type = 1 [default = 'constant']; + optional float value = 2 [default = 0]; // the value in constant filler + optional float min = 3 [default = 0]; // the min value in uniform filler + optional float max = 4 [default = 1]; // the max value in uniform filler + optional float mean = 5 [default = 0]; // the mean value in Gaussian filler + optional float std = 6 [default = 1]; // the std value in Gaussian filler + // The expected number of non-zero output weights for a given input in + // Gaussian filler -- the default -1 means don't perform sparsification. + optional int32 sparse = 7 [default = -1]; + // Normalize the filler variance by fan_in, fan_out, or their average. + // Applies to 'xavier' and 'msra' fillers. + enum VarianceNorm { + FAN_IN = 0; + FAN_OUT = 1; + AVERAGE = 2; + } + optional VarianceNorm variance_norm = 8 [default = FAN_IN]; +} + +message NetParameter { + optional string name = 1; // consider giving the network a name + // The input blobs to the network. + repeated string input = 3; + // The shape of the input blobs. + repeated BlobShape input_shape = 8; + + // 4D input dimensions -- deprecated. Use "shape" instead. + // If specified, for each input blob there should be four + // values specifying the num, channels, height and width of the input blob. + // Thus, there should be a total of (4 * #input) numbers. + repeated int32 input_dim = 4; + + // Whether the network will force every layer to carry out backward operation. + // If set False, then whether to carry out backward is determined + // automatically according to the net structure and learning rates. + optional bool force_backward = 5 [default = false]; + // The current "state" of the network, including the phase, level, and stage. + // Some layers may be included/excluded depending on this state and the states + // specified in the layers' include and exclude fields. + optional NetState state = 6; + + // Print debugging information about results while running Net::Forward, + // Net::Backward, and Net::Update. + optional bool debug_info = 7 [default = false]; + + // The layers that make up the net. Each of their configurations, including + // connectivity and behavior, is specified as a LayerParameter. + repeated LayerParameter layer = 100; // ID 100 so layers are printed last. + + // DEPRECATED: use 'layer' instead. + repeated V1LayerParameter layers = 2; +} + +// NOTE +// Update the next available ID when you add a new SolverParameter field. +// +// SolverParameter next available ID: 37 (last added: iter_size) +message SolverParameter { + ////////////////////////////////////////////////////////////////////////////// + // Specifying the train and test networks + // + // Exactly one train net must be specified using one of the following fields: + // train_net_param, train_net, net_param, net + // One or more test nets may be specified using any of the following fields: + // test_net_param, test_net, net_param, net + // If more than one test net field is specified (e.g., both net and + // test_net are specified), they will be evaluated in the field order given + // above: (1) test_net_param, (2) test_net, (3) net_param/net. + // A test_iter must be specified for each test_net. + // A test_level and/or a test_stage may also be specified for each test_net. + ////////////////////////////////////////////////////////////////////////////// + + // Proto filename for the train net, possibly combined with one or more + // test nets. + optional string net = 24; + // Inline train net param, possibly combined with one or more test nets. + optional NetParameter net_param = 25; + + optional string train_net = 1; // Proto filename for the train net. + repeated string test_net = 2; // Proto filenames for the test nets. + optional NetParameter train_net_param = 21; // Inline train net params. + repeated NetParameter test_net_param = 22; // Inline test net params. + + // The states for the train/test nets. Must be unspecified or + // specified once per net. + // + // By default, all states will have solver = true; + // train_state will have phase = TRAIN, + // and all test_state's will have phase = TEST. + // Other defaults are set according to the NetState defaults. + optional NetState train_state = 26; + repeated NetState test_state = 27; + + // The number of iterations for each test net. + repeated int32 test_iter = 3; + + // The number of iterations between two testing phases. + optional int32 test_interval = 4 [default = 0]; + optional bool test_compute_loss = 19 [default = false]; + // If true, run an initial test pass before the first iteration, + // ensuring memory availability and printing the starting value of the loss. + optional bool test_initialization = 32 [default = true]; + optional float base_lr = 5; // The base learning rate + // the number of iterations between displaying info. If display = 0, no info + // will be displayed. + optional int32 display = 6; + // Display the loss averaged over the last average_loss iterations + optional int32 average_loss = 33 [default = 1]; + optional int32 max_iter = 7; // the maximum number of iterations + // accumulate gradients over `iter_size` x `batch_size` instances + optional int32 iter_size = 36 [default = 1]; + optional string lr_policy = 8; // The learning rate decay policy. + optional float gamma = 9; // The parameter to compute the learning rate. + optional float power = 10; // The parameter to compute the learning rate. + optional float momentum = 11; // The momentum value. + optional float weight_decay = 12; // The weight decay. + // regularization types supported: L1 and L2 + // controlled by weight_decay + optional string regularization_type = 29 [default = "L2"]; + // the stepsize for learning rate policy "step" + optional int32 stepsize = 13; + // the stepsize for learning rate policy "multistep" + repeated int32 stepvalue = 34; + + // Set clip_gradients to >= 0 to clip parameter gradients to that L2 norm, + // whenever their actual L2 norm is larger. + optional float clip_gradients = 35 [default = -1]; + + optional int32 snapshot = 14 [default = 0]; // The snapshot interval + optional string snapshot_prefix = 15; // The prefix for the snapshot. + // whether to snapshot diff in the results or not. Snapshotting diff will help + // debugging but the final protocol buffer size will be much larger. + optional bool snapshot_diff = 16 [default = false]; + // the mode solver will use: 0 for CPU and 1 for GPU. Use GPU in default. + enum SolverMode { + CPU = 0; + GPU = 1; + } + optional SolverMode solver_mode = 17 [default = GPU]; + // the device_id will that be used in GPU mode. Use device_id = 0 in default. + optional int32 device_id = 18 [default = 0]; + // If non-negative, the seed with which the Solver will initialize the Caffe + // random number generator -- useful for reproducible results. Otherwise, + // (and by default) initialize using a seed derived from the system clock. + optional int64 random_seed = 20 [default = -1]; + + // Solver type + enum SolverType { + SGD = 0; + NESTEROV = 1; + ADAGRAD = 2; + } + optional SolverType solver_type = 30 [default = SGD]; + // numerical stability for AdaGrad + optional float delta = 31 [default = 1e-8]; + + // If true, print information about the state of the net that may help with + // debugging learning problems. + optional bool debug_info = 23 [default = false]; + + // If false, don't save a snapshot after training finishes. + optional bool snapshot_after_train = 28 [default = true]; +} + +// A message that stores the solver snapshots +message SolverState { + optional int32 iter = 1; // The current iteration + optional string learned_net = 2; // The file that stores the learned net. + repeated BlobProto history = 3; // The history for sgd solvers + optional int32 current_step = 4 [default = 0]; // The current step for learning rate +} + +enum Phase { + TRAIN = 0; + TEST = 1; +} + +message NetState { + optional Phase phase = 1 [default = TEST]; + optional int32 level = 2 [default = 0]; + repeated string stage = 3; +} + +message NetStateRule { + // Set phase to require the NetState have a particular phase (TRAIN or TEST) + // to meet this rule. + optional Phase phase = 1; + + // Set the minimum and/or maximum levels in which the layer should be used. + // Leave undefined to meet the rule regardless of level. + optional int32 min_level = 2; + optional int32 max_level = 3; + + // Customizable sets of stages to include or exclude. + // The net must have ALL of the specified stages and NONE of the specified + // "not_stage"s to meet the rule. + // (Use multiple NetStateRules to specify conjunctions of stages.) + repeated string stage = 4; + repeated string not_stage = 5; +} + +// Specifies training parameters (multipliers on global learning constants, +// and the name and other settings used for weight sharing). +message ParamSpec { + // The names of the parameter blobs -- useful for sharing parameters among + // layers, but never required otherwise. To share a parameter between two + // layers, give it a (non-empty) name. + optional string name = 1; + + // Whether to require shared weights to have the same shape, or just the same + // count -- defaults to STRICT if unspecified. + optional DimCheckMode share_mode = 2; + enum DimCheckMode { + // STRICT (default) requires that num, channels, height, width each match. + STRICT = 0; + // PERMISSIVE requires only the count (num*channels*height*width) to match. + PERMISSIVE = 1; + } + + // The multiplier on the global learning rate for this parameter. + optional float lr_mult = 3 [default = 1.0]; + + // The multiplier on the global weight decay for this parameter. + optional float decay_mult = 4 [default = 1.0]; +} + +// NOTE +// Update the next available ID when you add a new LayerParameter field. +// +// LayerParameter next available layer-specific ID: 137 (last added: reduction_param) +message LayerParameter { + optional string name = 1; // the layer name + optional string type = 2; // the layer type + repeated string bottom = 3; // the name of each bottom blob + repeated string top = 4; // the name of each top blob + + // The train / test phase for computation. + optional Phase phase = 10; + + // The amount of weight to assign each top blob in the objective. + // Each layer assigns a default value, usually of either 0 or 1, + // to each top blob. + repeated float loss_weight = 5; + + // Specifies training parameters (multipliers on global learning constants, + // and the name and other settings used for weight sharing). + repeated ParamSpec param = 6; + + // The blobs containing the numeric parameters of the layer. + repeated BlobProto blobs = 7; + + // Specifies on which bottoms the backpropagation should be skipped. + // The size must be either 0 or equal to the number of bottoms. + repeated bool propagate_down = 11; + + // Rules controlling whether and when a layer is included in the network, + // based on the current NetState. You may specify a non-zero number of rules + // to include OR exclude, but not both. If no include or exclude rules are + // specified, the layer is always included. If the current NetState meets + // ANY (i.e., one or more) of the specified rules, the layer is + // included/excluded. + repeated NetStateRule include = 8; + repeated NetStateRule exclude = 9; + + // Parameters for data pre-processing. + optional TransformationParameter transform_param = 100; + + // Parameters shared by loss layers. + optional LossParameter loss_param = 101; + + // Layer type-specific parameters. + // + // Note: certain layers may have more than one computational engine + // for their implementation. These layers include an Engine type and + // engine parameter for selecting the implementation. + // The default for the engine is set by the ENGINE switch at compile-time. + optional AccuracyParameter accuracy_param = 102; + optional ArgMaxParameter argmax_param = 103; + optional ConcatParameter concat_param = 104; + optional ContrastiveLossParameter contrastive_loss_param = 105; + optional ConvolutionParameter convolution_param = 106; + optional DataParameter data_param = 107; + optional DropoutParameter dropout_param = 108; + optional DummyDataParameter dummy_data_param = 109; + optional EltwiseParameter eltwise_param = 110; + optional ExpParameter exp_param = 111; + optional FlattenParameter flatten_param = 135; + optional HDF5DataParameter hdf5_data_param = 112; + optional HDF5OutputParameter hdf5_output_param = 113; + optional HingeLossParameter hinge_loss_param = 114; + optional ImageDataParameter image_data_param = 115; + optional InfogainLossParameter infogain_loss_param = 116; + optional InnerProductParameter inner_product_param = 117; + optional LogParameter log_param = 134; + optional LRNParameter lrn_param = 118; + optional MemoryDataParameter memory_data_param = 119; + optional MVNParameter mvn_param = 120; + optional PoolingParameter pooling_param = 121; + optional PowerParameter power_param = 122; + optional PReLUParameter prelu_param = 131; + optional PythonParameter python_param = 130; + optional ReductionParameter reduction_param = 136; + optional ReLUParameter relu_param = 123; + optional ReshapeParameter reshape_param = 133; + optional SigmoidParameter sigmoid_param = 124; + optional SoftmaxParameter softmax_param = 125; + optional SPPParameter spp_param = 132; + optional SliceParameter slice_param = 126; + optional TanHParameter tanh_param = 127; + optional ThresholdParameter threshold_param = 128; + optional WindowDataParameter window_data_param = 129; +} + +// Message that stores parameters used to apply transformation +// to the data layer's data +message TransformationParameter { + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 1 [default = 1]; + // Specify if we want to randomly mirror data. + optional bool mirror = 2 [default = false]; + // Specify if we would like to randomly crop an image. + optional uint32 crop_size = 3 [default = 0]; + // mean_file and mean_value cannot be specified at the same time + optional string mean_file = 4; + // if specified can be repeated once (would substract it from all the channels) + // or can be repeated the same number of times as channels + // (would subtract them from the corresponding channel) + repeated float mean_value = 5; + // Force the decoded image to have 3 color channels. + optional bool force_color = 6 [default = false]; + // Force the decoded image to have 1 color channels. + optional bool force_gray = 7 [default = false]; +} + +// Message that stores parameters shared by loss layers +message LossParameter { + // If specified, ignore instances with the given label. + optional int32 ignore_label = 1; + // If true, normalize each batch across all instances (including spatial + // dimesions, but not ignored instances); else, divide by batch size only. + optional bool normalize = 2 [default = true]; +} + +// Messages that store parameters used by individual layer types follow, in +// alphabetical order. + +message AccuracyParameter { + // When computing accuracy, count as correct by comparing the true label to + // the top k scoring classes. By default, only compare to the top scoring + // class (i.e. argmax). + optional uint32 top_k = 1 [default = 1]; + + // The "label" axis of the prediction blob, whose argmax corresponds to the + // predicted label -- may be negative to index from the end (e.g., -1 for the + // last axis). For example, if axis == 1 and the predictions are + // (N x C x H x W), the label blob is expected to contain N*H*W ground truth + // labels with integer values in {0, 1, ..., C-1}. + optional int32 axis = 2 [default = 1]; + + // If specified, ignore instances with the given label. + optional int32 ignore_label = 3; +} + +message ArgMaxParameter { + // If true produce pairs (argmax, maxval) + optional bool out_max_val = 1 [default = false]; + optional uint32 top_k = 2 [default = 1]; +} + +message ConcatParameter { + // The axis along which to concatenate -- may be negative to index from the + // end (e.g., -1 for the last axis). Other axes must have the + // same dimension for all the bottom blobs. + // By default, ConcatLayer concatenates blobs along the "channels" axis (1). + optional int32 axis = 2 [default = 1]; + + // DEPRECATED: alias for "axis" -- does not support negative indexing. + optional uint32 concat_dim = 1 [default = 1]; +} + +message ContrastiveLossParameter { + // margin for dissimilar pair + optional float margin = 1 [default = 1.0]; + // The first implementation of this cost did not exactly match the cost of + // Hadsell et al 2006 -- using (margin - d^2) instead of (margin - d)^2. + // legacy_version = false (the default) uses (margin - d)^2 as proposed in the + // Hadsell paper. New models should probably use this version. + // legacy_version = true uses (margin - d^2). This is kept to support / + // reproduce existing models and results + optional bool legacy_version = 2 [default = false]; +} + +message ConvolutionParameter { + optional uint32 num_output = 1; // The number of outputs for the layer + optional bool bias_term = 2 [default = true]; // whether to have bias terms + // Pad, kernel size, and stride are all given as a single value for equal + // dimensions in height and width or as Y, X pairs. + optional uint32 pad = 3 [default = 0]; // The padding size (equal in Y, X) + optional uint32 pad_h = 9 [default = 0]; // The padding height + optional uint32 pad_w = 10 [default = 0]; // The padding width + optional uint32 kernel_size = 4; // The kernel size (square) + optional uint32 kernel_h = 11; // The kernel height + optional uint32 kernel_w = 12; // The kernel width + optional uint32 group = 5 [default = 1]; // The group size for group conv + optional uint32 stride = 6 [default = 1]; // The stride (equal in Y, X) + optional uint32 stride_h = 13; // The stride height + optional uint32 stride_w = 14; // The stride width + optional FillerParameter weight_filler = 7; // The filler for the weight + optional FillerParameter bias_filler = 8; // The filler for the bias + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 15 [default = DEFAULT]; +} + +message DataParameter { + enum DB { + LEVELDB = 0; + LMDB = 1; + } + // Specify the data source. + optional string source = 1; + // Specify the batch size. + optional uint32 batch_size = 4; + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the database. + optional uint32 rand_skip = 7 [default = 0]; + optional DB backend = 8 [default = LEVELDB]; + // DEPRECATED. See TransformationParameter. For data pre-processing, we can do + // simple scaling and subtracting the data mean, if provided. Note that the + // mean subtraction is always carried out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // DEPRECATED. See TransformationParameter. Specify if we would like to randomly + // crop an image. + optional uint32 crop_size = 5 [default = 0]; + // DEPRECATED. See TransformationParameter. Specify if we want to randomly mirror + // data. + optional bool mirror = 6 [default = false]; + // Force the encoded image to have 3 color channels + optional bool force_encoded_color = 9 [default = false]; +} + +message DropoutParameter { + optional float dropout_ratio = 1 [default = 0.5]; // dropout ratio +} + +// DummyDataLayer fills any number of arbitrarily shaped blobs with random +// (or constant) data generated by "Fillers" (see "message FillerParameter"). +message DummyDataParameter { + // This layer produces N >= 1 top blobs. DummyDataParameter must specify 1 or N + // shape fields, and 0, 1 or N data_fillers. + // + // If 0 data_fillers are specified, ConstantFiller with a value of 0 is used. + // If 1 data_filler is specified, it is applied to all top blobs. If N are + // specified, the ith is applied to the ith top blob. + repeated FillerParameter data_filler = 1; + repeated BlobShape shape = 6; + + // 4D dimensions -- deprecated. Use "shape" instead. + repeated uint32 num = 2; + repeated uint32 channels = 3; + repeated uint32 height = 4; + repeated uint32 width = 5; +} + +message EltwiseParameter { + enum EltwiseOp { + PROD = 0; + SUM = 1; + MAX = 2; + } + optional EltwiseOp operation = 1 [default = SUM]; // element-wise operation + repeated float coeff = 2; // blob-wise coefficient for SUM operation + + // Whether to use an asymptotically slower (for >2 inputs) but stabler method + // of computing the gradient for the PROD operation. (No effect for SUM op.) + optional bool stable_prod_grad = 3 [default = true]; +} + +message ExpParameter { + // ExpLayer computes outputs y = base ^ (shift + scale * x), for base > 0. + // Or if base is set to the default (-1), base is set to e, + // so y = exp(shift + scale * x). + optional float base = 1 [default = -1.0]; + optional float scale = 2 [default = 1.0]; + optional float shift = 3 [default = 0.0]; +} + +/// Message that stores parameters used by FlattenLayer +message FlattenParameter { + // The first axis to flatten: all preceding axes are retained in the output. + // May be negative to index from the end (e.g., -1 for the last axis). + optional int32 axis = 1 [default = 1]; + + // The last axis to flatten: all following axes are retained in the output. + // May be negative to index from the end (e.g., the default -1 for the last + // axis). + optional int32 end_axis = 2 [default = -1]; +} + +// Message that stores parameters used by HDF5DataLayer +message HDF5DataParameter { + // Specify the data source. + optional string source = 1; + // Specify the batch size. + optional uint32 batch_size = 2; + + // Specify whether to shuffle the data. + // If shuffle == true, the ordering of the HDF5 files is shuffled, + // and the ordering of data within any given HDF5 file is shuffled, + // but data between different files are not interleaved; all of a file's + // data are output (in a random order) before moving onto another file. + optional bool shuffle = 3 [default = false]; +} + +message HDF5OutputParameter { + optional string file_name = 1; +} + +message HingeLossParameter { + enum Norm { + L1 = 1; + L2 = 2; + } + // Specify the Norm to use L1 or L2 + optional Norm norm = 1 [default = L1]; +} + +message ImageDataParameter { + // Specify the data source. + optional string source = 1; + // Specify the batch size. + optional uint32 batch_size = 4; + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the database. + optional uint32 rand_skip = 7 [default = 0]; + // Whether or not ImageLayer should shuffle the list of files at every epoch. + optional bool shuffle = 8 [default = false]; + // It will also resize images if new_height or new_width are not zero. + optional uint32 new_height = 9 [default = 0]; + optional uint32 new_width = 10 [default = 0]; + // Specify if the images are color or gray + optional bool is_color = 11 [default = true]; + // DEPRECATED. See TransformationParameter. For data pre-processing, we can do + // simple scaling and subtracting the data mean, if provided. Note that the + // mean subtraction is always carried out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // DEPRECATED. See TransformationParameter. Specify if we would like to randomly + // crop an image. + optional uint32 crop_size = 5 [default = 0]; + // DEPRECATED. See TransformationParameter. Specify if we want to randomly mirror + // data. + optional bool mirror = 6 [default = false]; + optional string root_folder = 12 [default = ""]; +} + +message InfogainLossParameter { + // Specify the infogain matrix source. + optional string source = 1; +} + +message InnerProductParameter { + optional uint32 num_output = 1; // The number of outputs for the layer + optional bool bias_term = 2 [default = true]; // whether to have bias terms + optional FillerParameter weight_filler = 3; // The filler for the weight + optional FillerParameter bias_filler = 4; // The filler for the bias + + // The first axis to be lumped into a single inner product computation; + // all preceding axes are retained in the output. + // May be negative to index from the end (e.g., -1 for the last axis). + optional int32 axis = 5 [default = 1]; +} + +// Message that stores parameters used by LogLayer +message LogParameter { + // LogLayer computes outputs y = log_base(shift + scale * x), for base > 0. + // Or if base is set to the default (-1), base is set to e, + // so y = ln(shift + scale * x) = log_e(shift + scale * x) + optional float base = 1 [default = -1.0]; + optional float scale = 2 [default = 1.0]; + optional float shift = 3 [default = 0.0]; +} + +// Message that stores parameters used by LRNLayer +message LRNParameter { + optional uint32 local_size = 1 [default = 5]; + optional float alpha = 2 [default = 1.]; + optional float beta = 3 [default = 0.75]; + enum NormRegion { + ACROSS_CHANNELS = 0; + WITHIN_CHANNEL = 1; + } + optional NormRegion norm_region = 4 [default = ACROSS_CHANNELS]; + optional float k = 5 [default = 1.]; +} + +message MemoryDataParameter { + optional uint32 batch_size = 1; + optional uint32 channels = 2; + optional uint32 height = 3; + optional uint32 width = 4; +} + +message MVNParameter { + // This parameter can be set to false to normalize mean only + optional bool normalize_variance = 1 [default = true]; + + // This parameter can be set to true to perform DNN-like MVN + optional bool across_channels = 2 [default = false]; + + // Epsilon for not dividing by zero while normalizing variance + optional float eps = 3 [default = 1e-9]; +} + +message PoolingParameter { + enum PoolMethod { + MAX = 0; + AVE = 1; + STOCHASTIC = 2; + } + optional PoolMethod pool = 1 [default = MAX]; // The pooling method + // Pad, kernel size, and stride are all given as a single value for equal + // dimensions in height and width or as Y, X pairs. + optional uint32 pad = 4 [default = 0]; // The padding size (equal in Y, X) + optional uint32 pad_h = 9 [default = 0]; // The padding height + optional uint32 pad_w = 10 [default = 0]; // The padding width + optional uint32 kernel_size = 2; // The kernel size (square) + optional uint32 kernel_h = 5; // The kernel height + optional uint32 kernel_w = 6; // The kernel width + optional uint32 stride = 3 [default = 1]; // The stride (equal in Y, X) + optional uint32 stride_h = 7; // The stride height + optional uint32 stride_w = 8; // The stride width + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 11 [default = DEFAULT]; + // If global_pooling then it will pool over the size of the bottom by doing + // kernel_h = bottom->height and kernel_w = bottom->width + optional bool global_pooling = 12 [default = false]; +} + +message PowerParameter { + // PowerLayer computes outputs y = (shift + scale * x) ^ power. + optional float power = 1 [default = 1.0]; + optional float scale = 2 [default = 1.0]; + optional float shift = 3 [default = 0.0]; +} + +message PythonParameter { + optional string module = 1; + optional string layer = 2; +} + +// Message that stores parameters used by ReductionLayer +message ReductionParameter { + enum ReductionOp { + SUM = 1; + ASUM = 2; + SUMSQ = 3; + MEAN = 4; + } + + optional ReductionOp operation = 1 [default = SUM]; // reduction operation + + // The first axis to reduce to a scalar -- may be negative to index from the + // end (e.g., -1 for the last axis). + // (Currently, only reduction along ALL "tail" axes is supported; reduction + // of axis M through N, where N < num_axes - 1, is unsupported.) + // Suppose we have an n-axis bottom Blob with shape: + // (d0, d1, d2, ..., d(m-1), dm, d(m+1), ..., d(n-1)). + // If axis == m, the output Blob will have shape + // (d0, d1, d2, ..., d(m-1)), + // and the ReductionOp operation is performed (d0 * d1 * d2 * ... * d(m-1)) + // times, each including (dm * d(m+1) * ... * d(n-1)) individual data. + // If axis == 0 (the default), the output Blob always has the empty shape + // (count 1), performing reduction across the entire input -- + // often useful for creating new loss functions. + optional int32 axis = 2 [default = 0]; + + optional float coeff = 3 [default = 1.0]; // coefficient for output +} + +// Message that stores parameters used by ReLULayer +message ReLUParameter { + // Allow non-zero slope for negative inputs to speed up optimization + // Described in: + // Maas, A. L., Hannun, A. Y., & Ng, A. Y. (2013). Rectifier nonlinearities + // improve neural network acoustic models. In ICML Workshop on Deep Learning + // for Audio, Speech, and Language Processing. + optional float negative_slope = 1 [default = 0]; + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 2 [default = DEFAULT]; +} + +message ReshapeParameter { + // Specify the output dimensions. If some of the dimensions are set to 0, + // the corresponding dimension from the bottom layer is used (unchanged). + // Exactly one dimension may be set to -1, in which case its value is + // inferred from the count of the bottom blob and the remaining dimensions. + // For example, suppose we want to reshape a 2D blob "input" with shape 2 x 8: + // + // layer { + // type: "Reshape" bottom: "input" top: "output" + // reshape_param { ... } + // } + // + // If "input" is 2D with shape 2 x 8, then the following reshape_param + // specifications are all equivalent, producing a 3D blob "output" with shape + // 2 x 2 x 4: + // + // reshape_param { shape { dim: 2 dim: 2 dim: 4 } } + // reshape_param { shape { dim: 0 dim: 2 dim: 4 } } + // reshape_param { shape { dim: 0 dim: 2 dim: -1 } } + // reshape_param { shape { dim: -1 dim: 0 dim: 2 } } + // + optional BlobShape shape = 1; + + // axis and num_axes control the portion of the bottom blob's shape that are + // replaced by (included in) the reshape. By default (axis == 0 and + // num_axes == -1), the entire bottom blob shape is included in the reshape, + // and hence the shape field must specify the entire output shape. + // + // axis may be non-zero to retain some portion of the beginning of the input + // shape (and may be negative to index from the end; e.g., -1 to begin the + // reshape after the last axis, including nothing in the reshape, + // -2 to include only the last axis, etc.). + // + // For example, suppose "input" is a 2D blob with shape 2 x 8. + // Then the following ReshapeLayer specifications are all equivalent, + // producing a blob "output" with shape 2 x 2 x 4: + // + // reshape_param { shape { dim: 2 dim: 2 dim: 4 } } + // reshape_param { shape { dim: 2 dim: 4 } axis: 1 } + // reshape_param { shape { dim: 2 dim: 4 } axis: -3 } + // + // num_axes specifies the extent of the reshape. + // If num_axes >= 0 (and axis >= 0), the reshape will be performed only on + // input axes in the range [axis, axis+num_axes]. + // num_axes may also be -1, the default, to include all remaining axes + // (starting from axis). + // + // For example, suppose "input" is a 2D blob with shape 2 x 8. + // Then the following ReshapeLayer specifications are equivalent, + // producing a blob "output" with shape 1 x 2 x 8. + // + // reshape_param { shape { dim: 1 dim: 2 dim: 8 } } + // reshape_param { shape { dim: 1 dim: 2 } num_axes: 1 } + // reshape_param { shape { dim: 1 } num_axes: 0 } + // + // On the other hand, these would produce output blob shape 2 x 1 x 8: + // + // reshape_param { shape { dim: 2 dim: 1 dim: 8 } } + // reshape_param { shape { dim: 1 } axis: 1 num_axes: 0 } + // + optional int32 axis = 2 [default = 0]; + optional int32 num_axes = 3 [default = -1]; +} + +message SigmoidParameter { + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 1 [default = DEFAULT]; +} + +message SliceParameter { + // The axis along which to slice -- may be negative to index from the end + // (e.g., -1 for the last axis). + // By default, SliceLayer concatenates blobs along the "channels" axis (1). + optional int32 axis = 3 [default = 1]; + repeated uint32 slice_point = 2; + + // DEPRECATED: alias for "axis" -- does not support negative indexing. + optional uint32 slice_dim = 1 [default = 1]; +} + +// Message that stores parameters used by SoftmaxLayer, SoftmaxWithLossLayer +message SoftmaxParameter { + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 1 [default = DEFAULT]; + + // The axis along which to perform the softmax -- may be negative to index + // from the end (e.g., -1 for the last axis). + // Any other axes will be evaluated as independent softmaxes. + optional int32 axis = 2 [default = 1]; +} + +message TanHParameter { + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 1 [default = DEFAULT]; +} + +message ThresholdParameter { + optional float threshold = 1 [default = 0]; // Strictly positive values +} + +message WindowDataParameter { + // Specify the data source. + optional string source = 1; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 2 [default = 1]; + optional string mean_file = 3; + // Specify the batch size. + optional uint32 batch_size = 4; + // Specify if we would like to randomly crop an image. + optional uint32 crop_size = 5 [default = 0]; + // Specify if we want to randomly mirror data. + optional bool mirror = 6 [default = false]; + // Foreground (object) overlap threshold + optional float fg_threshold = 7 [default = 0.5]; + // Background (non-object) overlap threshold + optional float bg_threshold = 8 [default = 0.5]; + // Fraction of batch that should be foreground objects + optional float fg_fraction = 9 [default = 0.25]; + // Amount of contextual padding to add around a window + // (used only by the window_data_layer) + optional uint32 context_pad = 10 [default = 0]; + // Mode for cropping out a detection window + // warp: cropped window is warped to a fixed size and aspect ratio + // square: the tightest square around the window is cropped + optional string crop_mode = 11 [default = "warp"]; + // cache_images: will load all images in memory for faster access + optional bool cache_images = 12 [default = false]; + // append root_folder to locate images + optional string root_folder = 13 [default = ""]; +} + +message SPPParameter { + enum PoolMethod { + MAX = 0; + AVE = 1; + STOCHASTIC = 2; + } + optional uint32 pyramid_height = 1; + optional PoolMethod pool = 2 [default = MAX]; // The pooling method + enum Engine { + DEFAULT = 0; + CAFFE = 1; + CUDNN = 2; + } + optional Engine engine = 6 [default = DEFAULT]; +} + +// DEPRECATED: use LayerParameter. +message V1LayerParameter { + repeated string bottom = 2; + repeated string top = 3; + optional string name = 4; + repeated NetStateRule include = 32; + repeated NetStateRule exclude = 33; + enum LayerType { + NONE = 0; + ABSVAL = 35; + ACCURACY = 1; + ARGMAX = 30; + BNLL = 2; + CONCAT = 3; + CONTRASTIVE_LOSS = 37; + CONVOLUTION = 4; + DATA = 5; + DECONVOLUTION = 39; + DROPOUT = 6; + DUMMY_DATA = 32; + EUCLIDEAN_LOSS = 7; + ELTWISE = 25; + EXP = 38; + FLATTEN = 8; + HDF5_DATA = 9; + HDF5_OUTPUT = 10; + HINGE_LOSS = 28; + IM2COL = 11; + IMAGE_DATA = 12; + INFOGAIN_LOSS = 13; + INNER_PRODUCT = 14; + LRN = 15; + MEMORY_DATA = 29; + MULTINOMIAL_LOGISTIC_LOSS = 16; + MVN = 34; + POOLING = 17; + POWER = 26; + RELU = 18; + SIGMOID = 19; + SIGMOID_CROSS_ENTROPY_LOSS = 27; + SILENCE = 36; + SOFTMAX = 20; + SOFTMAX_LOSS = 21; + SPLIT = 22; + SLICE = 33; + TANH = 23; + WINDOW_DATA = 24; + THRESHOLD = 31; + } + optional LayerType type = 5; + repeated BlobProto blobs = 6; + repeated string param = 1001; + repeated DimCheckMode blob_share_mode = 1002; + enum DimCheckMode { + STRICT = 0; + PERMISSIVE = 1; + } + repeated float blobs_lr = 7; + repeated float weight_decay = 8; + repeated float loss_weight = 35; + optional AccuracyParameter accuracy_param = 27; + optional ArgMaxParameter argmax_param = 23; + optional ConcatParameter concat_param = 9; + optional ContrastiveLossParameter contrastive_loss_param = 40; + optional ConvolutionParameter convolution_param = 10; + optional DataParameter data_param = 11; + optional DropoutParameter dropout_param = 12; + optional DummyDataParameter dummy_data_param = 26; + optional EltwiseParameter eltwise_param = 24; + optional ExpParameter exp_param = 41; + optional HDF5DataParameter hdf5_data_param = 13; + optional HDF5OutputParameter hdf5_output_param = 14; + optional HingeLossParameter hinge_loss_param = 29; + optional ImageDataParameter image_data_param = 15; + optional InfogainLossParameter infogain_loss_param = 16; + optional InnerProductParameter inner_product_param = 17; + optional LRNParameter lrn_param = 18; + optional MemoryDataParameter memory_data_param = 22; + optional MVNParameter mvn_param = 34; + optional PoolingParameter pooling_param = 19; + optional PowerParameter power_param = 21; + optional ReLUParameter relu_param = 30; + optional SigmoidParameter sigmoid_param = 38; + optional SoftmaxParameter softmax_param = 39; + optional SliceParameter slice_param = 31; + optional TanHParameter tanh_param = 37; + optional ThresholdParameter threshold_param = 25; + optional WindowDataParameter window_data_param = 20; + optional TransformationParameter transform_param = 36; + optional LossParameter loss_param = 42; + optional V0LayerParameter layer = 1; +} + +// DEPRECATED: V0LayerParameter is the old way of specifying layer parameters +// in Caffe. We keep this message type around for legacy support. +message V0LayerParameter { + optional string name = 1; // the layer name + optional string type = 2; // the string to specify the layer type + + // Parameters to specify layers with inner products. + optional uint32 num_output = 3; // The number of outputs for the layer + optional bool biasterm = 4 [default = true]; // whether to have bias terms + optional FillerParameter weight_filler = 5; // The filler for the weight + optional FillerParameter bias_filler = 6; // The filler for the bias + + optional uint32 pad = 7 [default = 0]; // The padding size + optional uint32 kernelsize = 8; // The kernel size + optional uint32 group = 9 [default = 1]; // The group size for group conv + optional uint32 stride = 10 [default = 1]; // The stride + enum PoolMethod { + MAX = 0; + AVE = 1; + STOCHASTIC = 2; + } + optional PoolMethod pool = 11 [default = MAX]; // The pooling method + optional float dropout_ratio = 12 [default = 0.5]; // dropout ratio + + optional uint32 local_size = 13 [default = 5]; // for local response norm + optional float alpha = 14 [default = 1.]; // for local response norm + optional float beta = 15 [default = 0.75]; // for local response norm + optional float k = 22 [default = 1.]; + + // For data layers, specify the data source + optional string source = 16; + // For data pre-processing, we can do simple scaling and subtracting the + // data mean, if provided. Note that the mean subtraction is always carried + // out before scaling. + optional float scale = 17 [default = 1]; + optional string meanfile = 18; + // For data layers, specify the batch size. + optional uint32 batchsize = 19; + // For data layers, specify if we would like to randomly crop an image. + optional uint32 cropsize = 20 [default = 0]; + // For data layers, specify if we want to randomly mirror data. + optional bool mirror = 21 [default = false]; + + // The blobs containing the numeric parameters of the layer + repeated BlobProto blobs = 50; + // The ratio that is multiplied on the global learning rate. If you want to + // set the learning ratio for one blob, you need to set it for all blobs. + repeated float blobs_lr = 51; + // The weight decay that is multiplied on the global weight decay. + repeated float weight_decay = 52; + + // The rand_skip variable is for the data layer to skip a few data points + // to avoid all asynchronous sgd clients to start at the same point. The skip + // point would be set as rand_skip * rand(0,1). Note that rand_skip should not + // be larger than the number of keys in the database. + optional uint32 rand_skip = 53 [default = 0]; + + // Fields related to detection (det_*) + // foreground (object) overlap threshold + optional float det_fg_threshold = 54 [default = 0.5]; + // background (non-object) overlap threshold + optional float det_bg_threshold = 55 [default = 0.5]; + // Fraction of batch that should be foreground objects + optional float det_fg_fraction = 56 [default = 0.25]; + + // optional bool OBSOLETE_can_clobber = 57 [default = true]; + + // Amount of contextual padding to add around a window + // (used only by the window_data_layer) + optional uint32 det_context_pad = 58 [default = 0]; + + // Mode for cropping out a detection window + // warp: cropped window is warped to a fixed size and aspect ratio + // square: the tightest square around the window is cropped + optional string det_crop_mode = 59 [default = "warp"]; + + // For ReshapeLayer, one needs to specify the new dimensions. + optional int32 new_num = 60 [default = 0]; + optional int32 new_channels = 61 [default = 0]; + optional int32 new_height = 62 [default = 0]; + optional int32 new_width = 63 [default = 0]; + + // Whether or not ImageLayer should shuffle the list of files at every epoch. + // It will also resize images if new_height or new_width are not zero. + optional bool shuffle_images = 64 [default = false]; + + // For ConcatLayer, one needs to specify the dimension for concatenation, and + // the other dimensions must be the same for all the bottom blobs. + // By default it will concatenate blobs along the channels dimension. + optional uint32 concat_dim = 65 [default = 1]; + + optional HDF5OutputParameter hdf5_output_param = 1001; +} + +message PReLUParameter { + // Parametric ReLU described in K. He et al, Delving Deep into Rectifiers: + // Surpassing Human-Level Performance on ImageNet Classification, 2015. + + // Initial value of a_i. Default is a_i=0.25 for all i. + optional FillerParameter filler = 1; + // Whether or not slope paramters are shared across channels. + optional bool channel_shared = 2 [default = false]; +} diff --git a/modules/dnn/src/caffe/caffe_importer.cpp b/modules/dnn/src/caffe/caffe_importer.cpp new file mode 100644 index 000000000..59a656f5c --- /dev/null +++ b/modules/dnn/src/caffe/caffe_importer.cpp @@ -0,0 +1,355 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "precomp.hpp" +using namespace cv; +using namespace cv::dnn; + +#if HAVE_PROTOBUF +#include "caffe.pb.h" + +#include +#include +#include +#include +#include +#include +#include "caffe_io.hpp" + +using ::google::protobuf::RepeatedField; +using ::google::protobuf::RepeatedPtrField; +using ::google::protobuf::Message; +using ::google::protobuf::Descriptor; +using ::google::protobuf::FieldDescriptor; +using ::google::protobuf::Reflection; + +namespace +{ + class CaffeImporter : public Importer + { + caffe::NetParameter net; + caffe::NetParameter netBinary; + + public: + + CaffeImporter(const char *pototxt, const char *caffeModel) + { + ReadNetParamsFromTextFileOrDie(pototxt, &net); + + if (caffeModel && caffeModel[0]) + ReadNetParamsFromBinaryFileOrDie(caffeModel, &netBinary); + } + + void addParam(const Message &msg, const FieldDescriptor *field, cv::dnn::LayerParams ¶ms) + { + const Reflection *refl = msg.GetReflection(); + int type = field->cpp_type(); + bool isRepeated = field->is_repeated(); + const std::string &name = field->name(); + + #define SET_UP_FILED(getter, arrayConstr, gtype) \ + if (isRepeated) { \ + const RepeatedField &v = refl->GetRepeatedField(msg, field); \ + params.set(name, DictValue::arrayConstr(v.begin(), (int)v.size())); \ + } \ + else { \ + params.set(name, refl->getter(msg, field)); \ + } + + switch (type) + { + case FieldDescriptor::CPPTYPE_INT32: + SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int32); + break; + case FieldDescriptor::CPPTYPE_UINT32: + SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint32); + break; + case FieldDescriptor::CPPTYPE_INT64: + SET_UP_FILED(GetInt32, arrayInt, ::google::protobuf::int64); + break; + case FieldDescriptor::CPPTYPE_UINT64: + SET_UP_FILED(GetUInt32, arrayInt, ::google::protobuf::uint64); + break; + case FieldDescriptor::CPPTYPE_BOOL: + SET_UP_FILED(GetBool, arrayInt, bool); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + SET_UP_FILED(GetDouble, arrayReal, double); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + SET_UP_FILED(GetFloat, arrayReal, float); + break; + case FieldDescriptor::CPPTYPE_STRING: + if (isRepeated) { + const RepeatedPtrField &v = refl->GetRepeatedPtrField(msg, field); + params.set(name, DictValue::arrayString(v.begin(), (int)v.size())); + } + else { + params.set(name, refl->GetString(msg, field)); + } + break; + case FieldDescriptor::CPPTYPE_ENUM: + if (isRepeated) { + int size = refl->FieldSize(msg, field); + std::vector buf(size); + for (int i = 0; i < size; i++) + buf[i] = refl->GetRepeatedEnum(msg, field, i)->name(); + params.set(name, DictValue::arrayString(buf.begin(), size)); + } + else { + params.set(name, refl->GetEnum(msg, field)->name()); + } + break; + default: + CV_Error(Error::StsError, "Unknown type \"" + String(field->type_name()) + "\" in prototxt"); + break; + } + } + + inline static bool ends_with_param(const std::string &str) + { + static const std::string _param("_param"); + return (str.size() >= _param.size()) && str.compare(str.size() - _param.size(), _param.size(), _param) == 0; + } + + void extractLayerParams(const Message &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false) + { + const Descriptor *msgDesc = msg.GetDescriptor(); + const Reflection *msgRefl = msg.GetReflection(); + + for (int fieldId = 0; fieldId < msgDesc->field_count(); fieldId++) + { + const FieldDescriptor *fd = msgDesc->field(fieldId); + + if (!isInternal && !ends_with_param(fd->name())) + continue; + + bool hasData = fd->is_required() || + (fd->is_optional() && msgRefl->HasField(msg, fd)) || + (fd->is_repeated() && msgRefl->FieldSize(msg, fd) > 0); + if (!hasData) + continue; + + if (fd->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) + { + if (fd->is_repeated()) //Extract only first item! + extractLayerParams(msgRefl->GetRepeatedMessage(msg, fd, 0), params, true); + else + extractLayerParams(msgRefl->GetMessage(msg, fd), params, true); + } + else + { + addParam(msg, fd, params); + } + } + } + + BlobShape blobShapeFromProto(const caffe::BlobProto &pbBlob) + { + if (pbBlob.has_num() || pbBlob.has_channels() || pbBlob.has_height() || pbBlob.has_width()) + { + return BlobShape(pbBlob.num(), pbBlob.channels(), pbBlob.height(), pbBlob.width()); + } + else if (pbBlob.has_shape()) + { + const caffe::BlobShape &_shape = pbBlob.shape(); + BlobShape shape(_shape.dim_size()); + + for (int i = 0; i < _shape.dim_size(); i++) + shape[i] = (int)_shape.dim(i); + + return shape; + } + else + { + CV_Error(Error::StsError, "Unknown shape of input blob"); + return BlobShape(-1); + } + } + + void blobFromProto(const caffe::BlobProto &pbBlob, cv::dnn::Blob &dstBlob) + { + BlobShape shape = blobShapeFromProto(pbBlob); + + dstBlob.create(shape, CV_32F); + CV_Assert(pbBlob.data_size() == (int)dstBlob.matRefConst().total()); + + CV_DbgAssert(pbBlob.GetDescriptor()->FindFieldByLowercaseName("data")->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT); + float *dstData = dstBlob.matRef().ptr(); + + for (int i = 0; i < pbBlob.data_size(); i++) + dstData[i] = pbBlob.data(i); + } + + void extractBinaryLayerParms(const caffe::LayerParameter& layer, LayerParams& layerParams) + { + const std::string &name = layer.name(); + + int li; + for (li = 0; li != netBinary.layer_size(); li++) + { + if (netBinary.layer(li).name() == name) + break; + } + + if (li == netBinary.layer_size() || netBinary.layer(li).blobs_size() == 0) + return; + + const caffe::LayerParameter &binLayer = netBinary.layer(li); + layerParams.blobs.resize(binLayer.blobs_size()); + for (int bi = 0; bi < binLayer.blobs_size(); bi++) + { + blobFromProto(binLayer.blobs(bi), layerParams.blobs[bi]); + } + } + + struct BlobNote + { + BlobNote(const std::string &_name, int _layerId, int _outNum) : + name(_name.c_str()), layerId(_layerId), outNum(_outNum) {} + + const char *name; + int layerId, outNum; + }; + + void populateNet(Net dstNet) + { + int layersSize = net.layer_size(); + std::vector addedBlobs; + addedBlobs.reserve(layersSize + 1); + + //setup input layer names + { + std::vector netInputs(net.input_size()); + for (int inNum = 0; inNum < net.input_size(); inNum++) + { + addedBlobs.push_back(BlobNote(net.input(inNum), 0, inNum)); + netInputs[inNum] = net.input(inNum); + } + dstNet.setNetInputs(netInputs); + } + + for (int li = 0; li < layersSize; li++) + { + const caffe::LayerParameter &layer = net.layer(li); + String name = layer.name(); + String type = layer.type(); + LayerParams layerParams; + + extractLayerParams(layer, layerParams); + extractBinaryLayerParms(layer, layerParams); + + int id = dstNet.addLayer(name, type, layerParams); + + for (int inNum = 0; inNum < layer.bottom_size(); inNum++) + addInput(layer.bottom(inNum), id, inNum, dstNet, addedBlobs); + + for (int outNum = 0; outNum < layer.top_size(); outNum++) + addOutput(layer, id, outNum, addedBlobs); + } + } + + void addOutput(const caffe::LayerParameter &layer, int layerId, int outNum, std::vector &addedBlobs) + { + const std::string &name = layer.top(outNum); + + bool haveDups = false; + for (int idx = (int)addedBlobs.size() - 1; idx >= 0; idx--) + { + if (addedBlobs[idx].name == name) + { + haveDups = true; + break; + } + } + + if (haveDups) + { + bool isInplace = layer.bottom_size() > outNum && layer.bottom(outNum) == name; + if (!isInplace) + CV_Error(Error::StsBadArg, "Duplicate blobs produced by multiple sources"); + } + + addedBlobs.push_back(BlobNote(name, layerId, outNum)); + } + + void addInput(const std::string &name, int layerId, int inNum, Net &dstNet, std::vector &addedBlobs) + { + int idx; + for (idx = (int)addedBlobs.size() - 1; idx >= 0; idx--) + { + if (addedBlobs[idx].name == name) + break; + } + + if (idx < 0) + { + CV_Error(Error::StsObjectNotFound, "Can't found output blob \"" + name + "\""); + return; + } + + dstNet.connect(addedBlobs[idx].layerId, addedBlobs[idx].outNum, layerId, inNum); + } + + ~CaffeImporter() + { + + } + + + }; + +} + +Ptr cv::dnn::createCaffeImporter(const String &prototxt, const String &caffeModel) +{ + return Ptr(new CaffeImporter(prototxt.c_str(), caffeModel.c_str())); +} + +#else //HAVE_PROTOBUF + +Ptr cv::dnn::createCaffeImporter(const String&, const String&) +{ + CV_Error(cv::Error::StsNotImplemented, "libprotobuf required to import data from Caffe models"); + return Ptr(); +} + +#endif //HAVE_PROTOBUF diff --git a/modules/dnn/src/caffe/caffe_io.cpp b/modules/dnn/src/caffe/caffe_io.cpp new file mode 100644 index 000000000..986271cd1 --- /dev/null +++ b/modules/dnn/src/caffe/caffe_io.cpp @@ -0,0 +1,1115 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +/*M/////////////////////////////////////////////////////////////////////////////////////// +//COPYRIGHT +// +//All contributions by the University of California: +//Copyright (c) 2014, The Regents of the University of California (Regents) +//All rights reserved. +// +//All other contributions: +//Copyright (c) 2014, the respective contributors +//All rights reserved. +// +//Caffe uses a shared copyright model: each contributor holds copyright over +//their contributions to Caffe. The project versioning records all such +//contribution and copyright details. If a contributor wants to further mark +//their specific copyright on a particular contribution, they should indicate +//their copyright solely in the commit message of the change when it is +//committed. +// +//LICENSE +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +// +//1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +//2. 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. +// +//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. +// +//CONTRIBUTION AGREEMENT +// +//By contributing to the BVLC/caffe repository through pull-request, comment, +//or otherwise, the contributor releases their content to the +//license and copyright terms herein. +// +//M*/ + +#if HAVE_PROTOBUF +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "caffe.pb.h" +#include "caffe_io.hpp" +#include "glog_emulator.hpp" + +namespace cv { +namespace dnn { + +using std::string; +using std::map; +using namespace caffe; +using namespace ::google::protobuf; +using namespace ::google::protobuf::io; + +// Return true iff the net is not the current version. +bool NetNeedsUpgrade(const NetParameter& net_param); + +// Return true iff any layer contains parameters specified using +// deprecated V0LayerParameter. +bool NetNeedsV0ToV1Upgrade(const NetParameter& net_param); + +// Perform all necessary transformations to upgrade a V0NetParameter into a +// NetParameter (including upgrading padding layers and LayerParameters). +bool UpgradeV0Net(const NetParameter& v0_net_param, NetParameter* net_param); + +// Upgrade NetParameter with padding layers to pad-aware conv layers. +// For any padding layer, remove it and put its pad parameter in any layers +// taking its top blob as input. +// Error if any of these above layers are not-conv layers. +void UpgradeV0PaddingLayers(const NetParameter& param, + NetParameter* param_upgraded_pad); + +// Upgrade a single V0LayerConnection to the V1LayerParameter format. +bool UpgradeV0LayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param); + +V1LayerParameter_LayerType UpgradeV0LayerType(const string& type); + +// Return true iff any layer contains deprecated data transformation parameters. +bool NetNeedsDataUpgrade(const NetParameter& net_param); + +// Perform all necessary transformations to upgrade old transformation fields +// into a TransformationParameter. +void UpgradeNetDataTransformation(NetParameter* net_param); + +// Return true iff the Net contains any layers specified as V1LayerParameters. +bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param); + +// Perform all necessary transformations to upgrade a NetParameter with +// deprecated V1LayerParameters. +bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param); + +bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, + LayerParameter* layer_param); + +const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type); + +// Check for deprecations and upgrade the NetParameter as needed. +bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param); + + +bool NetNeedsUpgrade(const NetParameter& net_param) { + return NetNeedsV0ToV1Upgrade(net_param) || NetNeedsV1ToV2Upgrade(net_param); +} + +bool NetNeedsV0ToV1Upgrade(const NetParameter& net_param) { + for (int i = 0; i < net_param.layers_size(); ++i) { + if (net_param.layers(i).has_layer()) { + return true; + } + } + return false; +} + +bool NetNeedsV1ToV2Upgrade(const NetParameter& net_param) { + return net_param.layers_size() > 0; +} + +bool UpgradeV0Net(const NetParameter& v0_net_param_padding_layers, + NetParameter* net_param) { + // First upgrade padding layers to padded conv layers. + NetParameter v0_net_param; + UpgradeV0PaddingLayers(v0_net_param_padding_layers, &v0_net_param); + // Now upgrade layer parameters. + bool is_fully_compatible = true; + net_param->Clear(); + if (v0_net_param.has_name()) { + net_param->set_name(v0_net_param.name()); + } + for (int i = 0; i < v0_net_param.layers_size(); ++i) { + is_fully_compatible &= UpgradeV0LayerParameter(v0_net_param.layers(i), + net_param->add_layers()); + } + for (int i = 0; i < v0_net_param.input_size(); ++i) { + net_param->add_input(v0_net_param.input(i)); + } + for (int i = 0; i < v0_net_param.input_dim_size(); ++i) { + net_param->add_input_dim(v0_net_param.input_dim(i)); + } + if (v0_net_param.has_force_backward()) { + net_param->set_force_backward(v0_net_param.force_backward()); + } + return is_fully_compatible; +} + +void UpgradeV0PaddingLayers(const NetParameter& param, + NetParameter* param_upgraded_pad) { + // Copy everything other than the layers from the original param. + param_upgraded_pad->Clear(); + param_upgraded_pad->CopyFrom(param); + param_upgraded_pad->clear_layers(); + // Figure out which layer each bottom blob comes from. + map blob_name_to_last_top_idx; + for (int i = 0; i < param.input_size(); ++i) { + const string& blob_name = param.input(i); + blob_name_to_last_top_idx[blob_name] = -1; + } + for (int i = 0; i < param.layers_size(); ++i) { + const V1LayerParameter& layer_connection = param.layers(i); + const V0LayerParameter& layer_param = layer_connection.layer(); + // Add the layer to the new net, unless it's a padding layer. + if (layer_param.type() != "padding") { + param_upgraded_pad->add_layers()->CopyFrom(layer_connection); + } + for (int j = 0; j < layer_connection.bottom_size(); ++j) { + const string& blob_name = layer_connection.bottom(j); + if (blob_name_to_last_top_idx.find(blob_name) == + blob_name_to_last_top_idx.end()) { + LOG(FATAL) << "Unknown blob input " << blob_name << " to layer " << j; + } + const int top_idx = blob_name_to_last_top_idx[blob_name]; + if (top_idx == -1) { + continue; + } + const V1LayerParameter& source_layer = param.layers(top_idx); + if (source_layer.layer().type() == "padding") { + // This layer has a padding layer as input -- check that it is a conv + // layer or a pooling layer and takes only one input. Also check that + // the padding layer input has only one input and one output. Other + // cases have undefined behavior in Caffe. + CHECK((layer_param.type() == "conv") || (layer_param.type() == "pool")) + << "Padding layer input to " + "non-convolutional / non-pooling layer type " + << layer_param.type(); + CHECK_EQ(layer_connection.bottom_size(), 1) + << "Conv Layer takes a single blob as input."; + CHECK_EQ(source_layer.bottom_size(), 1) + << "Padding Layer takes a single blob as input."; + CHECK_EQ(source_layer.top_size(), 1) + << "Padding Layer produces a single blob as output."; + int layer_index = param_upgraded_pad->layers_size() - 1; + param_upgraded_pad->mutable_layers(layer_index)->mutable_layer() + ->set_pad(source_layer.layer().pad()); + param_upgraded_pad->mutable_layers(layer_index) + ->set_bottom(j, source_layer.bottom(0)); + } + } + for (int j = 0; j < layer_connection.top_size(); ++j) { + const string& blob_name = layer_connection.top(j); + blob_name_to_last_top_idx[blob_name] = i; + } + } +} + +bool UpgradeV0LayerParameter(const V1LayerParameter& v0_layer_connection, + V1LayerParameter* layer_param) { + bool is_fully_compatible = true; + layer_param->Clear(); + for (int i = 0; i < v0_layer_connection.bottom_size(); ++i) { + layer_param->add_bottom(v0_layer_connection.bottom(i)); + } + for (int i = 0; i < v0_layer_connection.top_size(); ++i) { + layer_param->add_top(v0_layer_connection.top(i)); + } + if (v0_layer_connection.has_layer()) { + const V0LayerParameter& v0_layer_param = v0_layer_connection.layer(); + if (v0_layer_param.has_name()) { + layer_param->set_name(v0_layer_param.name()); + } + const string& type = v0_layer_param.type(); + if (v0_layer_param.has_type()) { + layer_param->set_type(UpgradeV0LayerType(type)); + } + for (int i = 0; i < v0_layer_param.blobs_size(); ++i) { + layer_param->add_blobs()->CopyFrom(v0_layer_param.blobs(i)); + } + for (int i = 0; i < v0_layer_param.blobs_lr_size(); ++i) { + layer_param->add_blobs_lr(v0_layer_param.blobs_lr(i)); + } + for (int i = 0; i < v0_layer_param.weight_decay_size(); ++i) { + layer_param->add_weight_decay(v0_layer_param.weight_decay(i)); + } + if (v0_layer_param.has_num_output()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_num_output( + v0_layer_param.num_output()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()->set_num_output( + v0_layer_param.num_output()); + } else { + LOG(ERROR) << "Unknown parameter num_output for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_biasterm()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_bias_term( + v0_layer_param.biasterm()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()->set_bias_term( + v0_layer_param.biasterm()); + } else { + LOG(ERROR) << "Unknown parameter biasterm for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_weight_filler()) { + if (type == "conv") { + layer_param->mutable_convolution_param()-> + mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()-> + mutable_weight_filler()->CopyFrom(v0_layer_param.weight_filler()); + } else { + LOG(ERROR) << "Unknown parameter weight_filler for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_bias_filler()) { + if (type == "conv") { + layer_param->mutable_convolution_param()-> + mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler()); + } else if (type == "innerproduct") { + layer_param->mutable_inner_product_param()-> + mutable_bias_filler()->CopyFrom(v0_layer_param.bias_filler()); + } else { + LOG(ERROR) << "Unknown parameter bias_filler for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_pad()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_pad(v0_layer_param.pad()); + } else if (type == "pool") { + layer_param->mutable_pooling_param()->set_pad(v0_layer_param.pad()); + } else { + LOG(ERROR) << "Unknown parameter pad for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_kernelsize()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_kernel_size( + v0_layer_param.kernelsize()); + } else if (type == "pool") { + layer_param->mutable_pooling_param()->set_kernel_size( + v0_layer_param.kernelsize()); + } else { + LOG(ERROR) << "Unknown parameter kernelsize for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_group()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_group( + v0_layer_param.group()); + } else { + LOG(ERROR) << "Unknown parameter group for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_stride()) { + if (type == "conv") { + layer_param->mutable_convolution_param()->set_stride( + v0_layer_param.stride()); + } else if (type == "pool") { + layer_param->mutable_pooling_param()->set_stride( + v0_layer_param.stride()); + } else { + LOG(ERROR) << "Unknown parameter stride for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_pool()) { + if (type == "pool") { + V0LayerParameter_PoolMethod pool = v0_layer_param.pool(); + switch (pool) { + case V0LayerParameter_PoolMethod_MAX: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_MAX); + break; + case V0LayerParameter_PoolMethod_AVE: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_AVE); + break; + case V0LayerParameter_PoolMethod_STOCHASTIC: + layer_param->mutable_pooling_param()->set_pool( + PoolingParameter_PoolMethod_STOCHASTIC); + break; + default: + LOG(ERROR) << "Unknown pool method " << pool; + is_fully_compatible = false; + } + } else { + LOG(ERROR) << "Unknown parameter pool for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_dropout_ratio()) { + if (type == "dropout") { + layer_param->mutable_dropout_param()->set_dropout_ratio( + v0_layer_param.dropout_ratio()); + } else { + LOG(ERROR) << "Unknown parameter dropout_ratio for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_local_size()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_local_size( + v0_layer_param.local_size()); + } else { + LOG(ERROR) << "Unknown parameter local_size for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_alpha()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_alpha(v0_layer_param.alpha()); + } else { + LOG(ERROR) << "Unknown parameter alpha for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_beta()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_beta(v0_layer_param.beta()); + } else { + LOG(ERROR) << "Unknown parameter beta for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_k()) { + if (type == "lrn") { + layer_param->mutable_lrn_param()->set_k(v0_layer_param.k()); + } else { + LOG(ERROR) << "Unknown parameter k for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_source()) { + if (type == "data") { + layer_param->mutable_data_param()->set_source(v0_layer_param.source()); + } else if (type == "hdf5_data") { + layer_param->mutable_hdf5_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_source( + v0_layer_param.source()); + } else if (type == "infogain_loss") { + layer_param->mutable_infogain_loss_param()->set_source( + v0_layer_param.source()); + } else { + LOG(ERROR) << "Unknown parameter source for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_scale()) { + layer_param->mutable_transform_param()-> + set_scale(v0_layer_param.scale()); + } + if (v0_layer_param.has_meanfile()) { + layer_param->mutable_transform_param()-> + set_mean_file(v0_layer_param.meanfile()); + } + if (v0_layer_param.has_batchsize()) { + if (type == "data") { + layer_param->mutable_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "hdf5_data") { + layer_param->mutable_hdf5_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else if (type == "window_data") { + layer_param->mutable_window_data_param()->set_batch_size( + v0_layer_param.batchsize()); + } else { + LOG(ERROR) << "Unknown parameter batchsize for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_cropsize()) { + layer_param->mutable_transform_param()-> + set_crop_size(v0_layer_param.cropsize()); + } + if (v0_layer_param.has_mirror()) { + layer_param->mutable_transform_param()-> + set_mirror(v0_layer_param.mirror()); + } + if (v0_layer_param.has_rand_skip()) { + if (type == "data") { + layer_param->mutable_data_param()->set_rand_skip( + v0_layer_param.rand_skip()); + } else if (type == "images") { + layer_param->mutable_image_data_param()->set_rand_skip( + v0_layer_param.rand_skip()); + } else { + LOG(ERROR) << "Unknown parameter rand_skip for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_shuffle_images()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_shuffle( + v0_layer_param.shuffle_images()); + } else { + LOG(ERROR) << "Unknown parameter shuffle for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_new_height()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_new_height( + v0_layer_param.new_height()); + } else { + LOG(ERROR) << "Unknown parameter new_height for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_new_width()) { + if (type == "images") { + layer_param->mutable_image_data_param()->set_new_width( + v0_layer_param.new_width()); + } else { + LOG(ERROR) << "Unknown parameter new_width for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_concat_dim()) { + if (type == "concat") { + layer_param->mutable_concat_param()->set_concat_dim( + v0_layer_param.concat_dim()); + } else { + LOG(ERROR) << "Unknown parameter concat_dim for layer type " << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_fg_threshold()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_fg_threshold( + v0_layer_param.det_fg_threshold()); + } else { + LOG(ERROR) << "Unknown parameter det_fg_threshold for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_bg_threshold()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_bg_threshold( + v0_layer_param.det_bg_threshold()); + } else { + LOG(ERROR) << "Unknown parameter det_bg_threshold for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_fg_fraction()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_fg_fraction( + v0_layer_param.det_fg_fraction()); + } else { + LOG(ERROR) << "Unknown parameter det_fg_fraction for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_context_pad()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_context_pad( + v0_layer_param.det_context_pad()); + } else { + LOG(ERROR) << "Unknown parameter det_context_pad for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_det_crop_mode()) { + if (type == "window_data") { + layer_param->mutable_window_data_param()->set_crop_mode( + v0_layer_param.det_crop_mode()); + } else { + LOG(ERROR) << "Unknown parameter det_crop_mode for layer type " + << type; + is_fully_compatible = false; + } + } + if (v0_layer_param.has_hdf5_output_param()) { + if (type == "hdf5_output") { + layer_param->mutable_hdf5_output_param()->CopyFrom( + v0_layer_param.hdf5_output_param()); + } else { + LOG(ERROR) << "Unknown parameter hdf5_output_param for layer type " + << type; + is_fully_compatible = false; + } + } + } + return is_fully_compatible; +} + +V1LayerParameter_LayerType UpgradeV0LayerType(const string& type) { + if (type == "accuracy") { + return V1LayerParameter_LayerType_ACCURACY; + } else if (type == "bnll") { + return V1LayerParameter_LayerType_BNLL; + } else if (type == "concat") { + return V1LayerParameter_LayerType_CONCAT; + } else if (type == "conv") { + return V1LayerParameter_LayerType_CONVOLUTION; + } else if (type == "data") { + return V1LayerParameter_LayerType_DATA; + } else if (type == "dropout") { + return V1LayerParameter_LayerType_DROPOUT; + } else if (type == "euclidean_loss") { + return V1LayerParameter_LayerType_EUCLIDEAN_LOSS; + } else if (type == "flatten") { + return V1LayerParameter_LayerType_FLATTEN; + } else if (type == "hdf5_data") { + return V1LayerParameter_LayerType_HDF5_DATA; + } else if (type == "hdf5_output") { + return V1LayerParameter_LayerType_HDF5_OUTPUT; + } else if (type == "im2col") { + return V1LayerParameter_LayerType_IM2COL; + } else if (type == "images") { + return V1LayerParameter_LayerType_IMAGE_DATA; + } else if (type == "infogain_loss") { + return V1LayerParameter_LayerType_INFOGAIN_LOSS; + } else if (type == "innerproduct") { + return V1LayerParameter_LayerType_INNER_PRODUCT; + } else if (type == "lrn") { + return V1LayerParameter_LayerType_LRN; + } else if (type == "multinomial_logistic_loss") { + return V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS; + } else if (type == "pool") { + return V1LayerParameter_LayerType_POOLING; + } else if (type == "relu") { + return V1LayerParameter_LayerType_RELU; + } else if (type == "sigmoid") { + return V1LayerParameter_LayerType_SIGMOID; + } else if (type == "softmax") { + return V1LayerParameter_LayerType_SOFTMAX; + } else if (type == "softmax_loss") { + return V1LayerParameter_LayerType_SOFTMAX_LOSS; + } else if (type == "split") { + return V1LayerParameter_LayerType_SPLIT; + } else if (type == "tanh") { + return V1LayerParameter_LayerType_TANH; + } else if (type == "window_data") { + return V1LayerParameter_LayerType_WINDOW_DATA; + } else { + LOG(FATAL) << "Unknown layer name: " << type; + return V1LayerParameter_LayerType_NONE; + } +} + +bool NetNeedsDataUpgrade(const NetParameter& net_param) { + for (int i = 0; i < net_param.layers_size(); ++i) { + if (net_param.layers(i).type() == V1LayerParameter_LayerType_DATA) { + DataParameter layer_param = net_param.layers(i).data_param(); + if (layer_param.has_scale()) { return true; } + if (layer_param.has_mean_file()) { return true; } + if (layer_param.has_crop_size()) { return true; } + if (layer_param.has_mirror()) { return true; } + } + if (net_param.layers(i).type() == V1LayerParameter_LayerType_IMAGE_DATA) { + ImageDataParameter layer_param = net_param.layers(i).image_data_param(); + if (layer_param.has_scale()) { return true; } + if (layer_param.has_mean_file()) { return true; } + if (layer_param.has_crop_size()) { return true; } + if (layer_param.has_mirror()) { return true; } + } + if (net_param.layers(i).type() == V1LayerParameter_LayerType_WINDOW_DATA) { + WindowDataParameter layer_param = net_param.layers(i).window_data_param(); + if (layer_param.has_scale()) { return true; } + if (layer_param.has_mean_file()) { return true; } + if (layer_param.has_crop_size()) { return true; } + if (layer_param.has_mirror()) { return true; } + } + } + return false; +} + +#define CONVERT_LAYER_TRANSFORM_PARAM(TYPE, Name, param_name) \ + do { \ + if (net_param->layers(i).type() == V1LayerParameter_LayerType_##TYPE) { \ + Name##Parameter* layer_param = \ + net_param->mutable_layers(i)->mutable_##param_name##_param(); \ + TransformationParameter* transform_param = \ + net_param->mutable_layers(i)->mutable_transform_param(); \ + if (layer_param->has_scale()) { \ + transform_param->set_scale(layer_param->scale()); \ + layer_param->clear_scale(); \ + } \ + if (layer_param->has_mean_file()) { \ + transform_param->set_mean_file(layer_param->mean_file()); \ + layer_param->clear_mean_file(); \ + } \ + if (layer_param->has_crop_size()) { \ + transform_param->set_crop_size(layer_param->crop_size()); \ + layer_param->clear_crop_size(); \ + } \ + if (layer_param->has_mirror()) { \ + transform_param->set_mirror(layer_param->mirror()); \ + layer_param->clear_mirror(); \ + } \ + } \ + } while (0) + +void UpgradeNetDataTransformation(NetParameter* net_param) { + for (int i = 0; i < net_param->layers_size(); ++i) { + CONVERT_LAYER_TRANSFORM_PARAM(DATA, Data, data); + CONVERT_LAYER_TRANSFORM_PARAM(IMAGE_DATA, ImageData, image_data); + CONVERT_LAYER_TRANSFORM_PARAM(WINDOW_DATA, WindowData, window_data); + } +} + +bool UpgradeNetAsNeeded(const string& param_file, NetParameter* param) { + bool success = true; + if (NetNeedsV0ToV1Upgrade(*param)) { + // NetParameter was specified using the old style (V0LayerParameter); try to + // upgrade it. + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "V0LayerParameter: " << param_file; + NetParameter original_param(*param); + if (!UpgradeV0Net(original_param, param)) { + success = false; + LOG(ERROR) << "Warning: had one or more problems upgrading " + << "V0NetParameter to NetParameter (see above); continuing anyway."; + } else { + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "V0LayerParameter"; + } + LOG(ERROR) << "Note that future Caffe releases will not support " + << "V0NetParameter; use ./build/tools/upgrade_net_proto_text for " + << "prototxt and ./build/tools/upgrade_net_proto_binary for model " + << "weights upgrade this and any other net protos to the new format."; + } + // NetParameter uses old style data transformation fields; try to upgrade it. + if (NetNeedsDataUpgrade(*param)) { + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "transformation parameters: " << param_file; + UpgradeNetDataTransformation(param); + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "data transformation parameters."; + LOG(ERROR) << "Note that future Caffe releases will only support " + << "transform_param messages for transformation fields."; + } + if (NetNeedsV1ToV2Upgrade(*param)) { + LOG(ERROR) << "Attempting to upgrade input file specified using deprecated " + << "V1LayerParameter: " << param_file; + NetParameter original_param(*param); + if (!UpgradeV1Net(original_param, param)) { + success = false; + LOG(ERROR) << "Warning: had one or more problems upgrading " + << "V1LayerParameter (see above); continuing anyway."; + } else { + LOG(INFO) << "Successfully upgraded file specified using deprecated " + << "V1LayerParameter"; + } + } + return success; +} + +bool UpgradeV1Net(const NetParameter& v1_net_param, NetParameter* net_param) { + bool is_fully_compatible = true; + if (v1_net_param.layer_size() > 0) { + LOG(ERROR) << "Input NetParameter to be upgraded already specifies 'layer' " + << "fields; these will be ignored for the upgrade."; + is_fully_compatible = false; + } + net_param->CopyFrom(v1_net_param); + net_param->clear_layers(); + net_param->clear_layer(); + for (int i = 0; i < v1_net_param.layers_size(); ++i) { + if (!UpgradeV1LayerParameter(v1_net_param.layers(i), + net_param->add_layer())) { + LOG(ERROR) << "Upgrade of input layer " << i << " failed."; + is_fully_compatible = false; + } + } + return is_fully_compatible; +} + +bool UpgradeV1LayerParameter(const V1LayerParameter& v1_layer_param, + LayerParameter* layer_param) { + layer_param->Clear(); + bool is_fully_compatible = true; + for (int i = 0; i < v1_layer_param.bottom_size(); ++i) { + layer_param->add_bottom(v1_layer_param.bottom(i)); + } + for (int i = 0; i < v1_layer_param.top_size(); ++i) { + layer_param->add_top(v1_layer_param.top(i)); + } + if (v1_layer_param.has_name()) { + layer_param->set_name(v1_layer_param.name()); + } + for (int i = 0; i < v1_layer_param.include_size(); ++i) { + layer_param->add_include()->CopyFrom(v1_layer_param.include(i)); + } + for (int i = 0; i < v1_layer_param.exclude_size(); ++i) { + layer_param->add_exclude()->CopyFrom(v1_layer_param.exclude(i)); + } + if (v1_layer_param.has_type()) { + layer_param->set_type(UpgradeV1LayerType(v1_layer_param.type())); + } + for (int i = 0; i < v1_layer_param.blobs_size(); ++i) { + layer_param->add_blobs()->CopyFrom(v1_layer_param.blobs(i)); + } + for (int i = 0; i < v1_layer_param.param_size(); ++i) { + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_name(v1_layer_param.param(i)); + } + ParamSpec_DimCheckMode mode; + for (int i = 0; i < v1_layer_param.blob_share_mode_size(); ++i) { + while (layer_param->param_size() <= i) { layer_param->add_param(); } + switch (v1_layer_param.blob_share_mode(i)) { + case V1LayerParameter_DimCheckMode_STRICT: + mode = ParamSpec_DimCheckMode_STRICT; + break; + case V1LayerParameter_DimCheckMode_PERMISSIVE: + mode = ParamSpec_DimCheckMode_PERMISSIVE; + break; + default: + LOG(FATAL) << "Unknown blob_share_mode: " + << v1_layer_param.blob_share_mode(i); + break; + } + layer_param->mutable_param(i)->set_share_mode(mode); + } + for (int i = 0; i < v1_layer_param.blobs_lr_size(); ++i) { + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_lr_mult(v1_layer_param.blobs_lr(i)); + } + for (int i = 0; i < v1_layer_param.weight_decay_size(); ++i) { + while (layer_param->param_size() <= i) { layer_param->add_param(); } + layer_param->mutable_param(i)->set_decay_mult( + v1_layer_param.weight_decay(i)); + } + for (int i = 0; i < v1_layer_param.loss_weight_size(); ++i) { + layer_param->add_loss_weight(v1_layer_param.loss_weight(i)); + } + if (v1_layer_param.has_accuracy_param()) { + layer_param->mutable_accuracy_param()->CopyFrom( + v1_layer_param.accuracy_param()); + } + if (v1_layer_param.has_argmax_param()) { + layer_param->mutable_argmax_param()->CopyFrom( + v1_layer_param.argmax_param()); + } + if (v1_layer_param.has_concat_param()) { + layer_param->mutable_concat_param()->CopyFrom( + v1_layer_param.concat_param()); + } + if (v1_layer_param.has_contrastive_loss_param()) { + layer_param->mutable_contrastive_loss_param()->CopyFrom( + v1_layer_param.contrastive_loss_param()); + } + if (v1_layer_param.has_convolution_param()) { + layer_param->mutable_convolution_param()->CopyFrom( + v1_layer_param.convolution_param()); + } + if (v1_layer_param.has_data_param()) { + layer_param->mutable_data_param()->CopyFrom( + v1_layer_param.data_param()); + } + if (v1_layer_param.has_dropout_param()) { + layer_param->mutable_dropout_param()->CopyFrom( + v1_layer_param.dropout_param()); + } + if (v1_layer_param.has_dummy_data_param()) { + layer_param->mutable_dummy_data_param()->CopyFrom( + v1_layer_param.dummy_data_param()); + } + if (v1_layer_param.has_eltwise_param()) { + layer_param->mutable_eltwise_param()->CopyFrom( + v1_layer_param.eltwise_param()); + } + if (v1_layer_param.has_exp_param()) { + layer_param->mutable_exp_param()->CopyFrom( + v1_layer_param.exp_param()); + } + if (v1_layer_param.has_hdf5_data_param()) { + layer_param->mutable_hdf5_data_param()->CopyFrom( + v1_layer_param.hdf5_data_param()); + } + if (v1_layer_param.has_hdf5_output_param()) { + layer_param->mutable_hdf5_output_param()->CopyFrom( + v1_layer_param.hdf5_output_param()); + } + if (v1_layer_param.has_hinge_loss_param()) { + layer_param->mutable_hinge_loss_param()->CopyFrom( + v1_layer_param.hinge_loss_param()); + } + if (v1_layer_param.has_image_data_param()) { + layer_param->mutable_image_data_param()->CopyFrom( + v1_layer_param.image_data_param()); + } + if (v1_layer_param.has_infogain_loss_param()) { + layer_param->mutable_infogain_loss_param()->CopyFrom( + v1_layer_param.infogain_loss_param()); + } + if (v1_layer_param.has_inner_product_param()) { + layer_param->mutable_inner_product_param()->CopyFrom( + v1_layer_param.inner_product_param()); + } + if (v1_layer_param.has_lrn_param()) { + layer_param->mutable_lrn_param()->CopyFrom( + v1_layer_param.lrn_param()); + } + if (v1_layer_param.has_memory_data_param()) { + layer_param->mutable_memory_data_param()->CopyFrom( + v1_layer_param.memory_data_param()); + } + if (v1_layer_param.has_mvn_param()) { + layer_param->mutable_mvn_param()->CopyFrom( + v1_layer_param.mvn_param()); + } + if (v1_layer_param.has_pooling_param()) { + layer_param->mutable_pooling_param()->CopyFrom( + v1_layer_param.pooling_param()); + } + if (v1_layer_param.has_power_param()) { + layer_param->mutable_power_param()->CopyFrom( + v1_layer_param.power_param()); + } + if (v1_layer_param.has_relu_param()) { + layer_param->mutable_relu_param()->CopyFrom( + v1_layer_param.relu_param()); + } + if (v1_layer_param.has_sigmoid_param()) { + layer_param->mutable_sigmoid_param()->CopyFrom( + v1_layer_param.sigmoid_param()); + } + if (v1_layer_param.has_softmax_param()) { + layer_param->mutable_softmax_param()->CopyFrom( + v1_layer_param.softmax_param()); + } + if (v1_layer_param.has_slice_param()) { + layer_param->mutable_slice_param()->CopyFrom( + v1_layer_param.slice_param()); + } + if (v1_layer_param.has_tanh_param()) { + layer_param->mutable_tanh_param()->CopyFrom( + v1_layer_param.tanh_param()); + } + if (v1_layer_param.has_threshold_param()) { + layer_param->mutable_threshold_param()->CopyFrom( + v1_layer_param.threshold_param()); + } + if (v1_layer_param.has_window_data_param()) { + layer_param->mutable_window_data_param()->CopyFrom( + v1_layer_param.window_data_param()); + } + if (v1_layer_param.has_transform_param()) { + layer_param->mutable_transform_param()->CopyFrom( + v1_layer_param.transform_param()); + } + if (v1_layer_param.has_loss_param()) { + layer_param->mutable_loss_param()->CopyFrom( + v1_layer_param.loss_param()); + } + if (v1_layer_param.has_layer()) { + LOG(ERROR) << "Input NetParameter has V0 layer -- ignoring."; + is_fully_compatible = false; + } + return is_fully_compatible; +} + +const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) { + switch (type) { + case V1LayerParameter_LayerType_NONE: + return ""; + case V1LayerParameter_LayerType_ABSVAL: + return "AbsVal"; + case V1LayerParameter_LayerType_ACCURACY: + return "Accuracy"; + case V1LayerParameter_LayerType_ARGMAX: + return "ArgMax"; + case V1LayerParameter_LayerType_BNLL: + return "BNLL"; + case V1LayerParameter_LayerType_CONCAT: + return "Concat"; + case V1LayerParameter_LayerType_CONTRASTIVE_LOSS: + return "ContrastiveLoss"; + case V1LayerParameter_LayerType_CONVOLUTION: + return "Convolution"; + case V1LayerParameter_LayerType_DECONVOLUTION: + return "Deconvolution"; + case V1LayerParameter_LayerType_DATA: + return "Data"; + case V1LayerParameter_LayerType_DROPOUT: + return "Dropout"; + case V1LayerParameter_LayerType_DUMMY_DATA: + return "DummyData"; + case V1LayerParameter_LayerType_EUCLIDEAN_LOSS: + return "EuclideanLoss"; + case V1LayerParameter_LayerType_ELTWISE: + return "Eltwise"; + case V1LayerParameter_LayerType_EXP: + return "Exp"; + case V1LayerParameter_LayerType_FLATTEN: + return "Flatten"; + case V1LayerParameter_LayerType_HDF5_DATA: + return "HDF5Data"; + case V1LayerParameter_LayerType_HDF5_OUTPUT: + return "HDF5Output"; + case V1LayerParameter_LayerType_HINGE_LOSS: + return "HingeLoss"; + case V1LayerParameter_LayerType_IM2COL: + return "Im2col"; + case V1LayerParameter_LayerType_IMAGE_DATA: + return "ImageData"; + case V1LayerParameter_LayerType_INFOGAIN_LOSS: + return "InfogainLoss"; + case V1LayerParameter_LayerType_INNER_PRODUCT: + return "InnerProduct"; + case V1LayerParameter_LayerType_LRN: + return "LRN"; + case V1LayerParameter_LayerType_MEMORY_DATA: + return "MemoryData"; + case V1LayerParameter_LayerType_MULTINOMIAL_LOGISTIC_LOSS: + return "MultinomialLogisticLoss"; + case V1LayerParameter_LayerType_MVN: + return "MVN"; + case V1LayerParameter_LayerType_POOLING: + return "Pooling"; + case V1LayerParameter_LayerType_POWER: + return "Power"; + case V1LayerParameter_LayerType_RELU: + return "ReLU"; + case V1LayerParameter_LayerType_SIGMOID: + return "Sigmoid"; + case V1LayerParameter_LayerType_SIGMOID_CROSS_ENTROPY_LOSS: + return "SigmoidCrossEntropyLoss"; + case V1LayerParameter_LayerType_SILENCE: + return "Silence"; + case V1LayerParameter_LayerType_SOFTMAX: + return "Softmax"; + case V1LayerParameter_LayerType_SOFTMAX_LOSS: + return "SoftmaxWithLoss"; + case V1LayerParameter_LayerType_SPLIT: + return "Split"; + case V1LayerParameter_LayerType_SLICE: + return "Slice"; + case V1LayerParameter_LayerType_TANH: + return "TanH"; + case V1LayerParameter_LayerType_WINDOW_DATA: + return "WindowData"; + case V1LayerParameter_LayerType_THRESHOLD: + return "Threshold"; + default: + LOG(FATAL) << "Unknown V1LayerParameter layer type: " << type; + return ""; + } +} + +const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte. + +bool ReadProtoFromTextFile(const char* filename, Message* proto) { + std::ifstream fs(filename, std::ifstream::in); + CHECK(fs.is_open()) << "Can't open \"" << filename << "\""; + IstreamInputStream input(&fs); + bool success = google::protobuf::TextFormat::Parse(&input, proto); + fs.close(); + return success; +} + +bool ReadProtoFromBinaryFile(const char* filename, Message* proto) { + std::ifstream fs(filename, std::ifstream::in | std::ifstream::binary); + CHECK(fs.is_open()) << "Can't open \"" << filename << "\""; + ZeroCopyInputStream* raw_input = new IstreamInputStream(&fs); + CodedInputStream* coded_input = new CodedInputStream(raw_input); + coded_input->SetTotalBytesLimit(kProtoReadBytesLimit, 536870912); + + bool success = proto->ParseFromCodedStream(coded_input); + + delete coded_input; + delete raw_input; + fs.close(); + return success; +} + +void ReadNetParamsFromTextFileOrDie(const char* param_file, + NetParameter* param) { + CHECK(ReadProtoFromTextFile(param_file, param)) + << "Failed to parse NetParameter file: " << param_file; + UpgradeNetAsNeeded(param_file, param); +} + +void ReadNetParamsFromBinaryFileOrDie(const char* param_file, + NetParameter* param) { + CHECK(ReadProtoFromBinaryFile(param_file, param)) + << "Failed to parse NetParameter file: " << param_file; + UpgradeNetAsNeeded(param_file, param); +} + +} +} +#endif diff --git a/modules/dnn/src/caffe/caffe_io.hpp b/modules/dnn/src/caffe/caffe_io.hpp new file mode 100644 index 000000000..fa1661289 --- /dev/null +++ b/modules/dnn/src/caffe/caffe_io.hpp @@ -0,0 +1,108 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +/*M/////////////////////////////////////////////////////////////////////////////////////// +//COPYRIGHT +// +//All contributions by the University of California: +//Copyright (c) 2014, The Regents of the University of California (Regents) +//All rights reserved. +// +//All other contributions: +//Copyright (c) 2014, the respective contributors +//All rights reserved. +// +//Caffe uses a shared copyright model: each contributor holds copyright over +//their contributions to Caffe. The project versioning records all such +//contribution and copyright details. If a contributor wants to further mark +//their specific copyright on a particular contribution, they should indicate +//their copyright solely in the commit message of the change when it is +//committed. +// +//LICENSE +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +// +//1. Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +//2. 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. +// +//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. +// +//CONTRIBUTION AGREEMENT +// +//By contributing to the BVLC/caffe repository through pull-request, comment, +//or otherwise, the contributor releases their content to the +//license and copyright terms herein. +// +//M*/ + +#ifndef __OPENCV_DNN_CAFFE_IO_HPP__ +#define __OPENCV_DNN_CAFFE_IO_HPP__ +#if HAVE_PROTOBUF + +#include "caffe.pb.h" + +namespace cv { +namespace dnn { + +// Read parameters from a file into a NetParameter proto message. +void ReadNetParamsFromTextFileOrDie(const char* param_file, + caffe::NetParameter* param); +void ReadNetParamsFromBinaryFileOrDie(const char* param_file, + caffe::NetParameter* param); + +} +} +#endif +#endif diff --git a/modules/dnn/src/caffe/compiled/caffe.tar.gz b/modules/dnn/src/caffe/compiled/caffe.tar.gz new file mode 100644 index 000000000..c66784dc9 Binary files /dev/null and b/modules/dnn/src/caffe/compiled/caffe.tar.gz differ diff --git a/modules/dnn/src/caffe/glog_emulator.hpp b/modules/dnn/src/caffe/glog_emulator.hpp new file mode 100644 index 000000000..39d1615c4 --- /dev/null +++ b/modules/dnn/src/caffe/glog_emulator.hpp @@ -0,0 +1,97 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__ +#define __OPENCV_DNN_CAFFE_GLOG_EMULATOR_HPP__ +#include +#include +#include +#include + +#define CHECK(cond) cv::GLogWrapper(__FILE__, CV_Func, __LINE__, "CHECK", #cond, cond) +#define CHECK_EQ(a, b) cv::GLogWrapper(__FILE__, CV_Func, __LINE__, "CHECK", #a"="#b, ((a) == (b))) +#define LOG(TYPE) cv::GLogWrapper(__FILE__, CV_Func, __LINE__, #TYPE) + +namespace cv +{ + +class GLogWrapper +{ + std::stringstream stream; + const char *file, *func, *type, *cond_str; + int line; + bool cond_staus; + +public: + + GLogWrapper(const char *_file, const char *_func, int _line, + const char *_type, + const char *_cond_str = NULL, bool _cond_status = true + ) : + file(_file), func(_func), type(_type), cond_str(_cond_str), + line(_line), cond_staus(_cond_status) {} + + template + GLogWrapper &operator<<(const T &v) + { + if (!cond_str || cond_str && !cond_staus) + stream << v; + return *this; + } + + ~GLogWrapper() + { + if (cond_str && !cond_staus) + { + cv::error(cv::Error::StsError, "FAILED: " + String(cond_str) + "." + stream.str(), func, file, line); + } + else if (!cond_str && strcmp(type, "CHECK")) + { + if (!std::strcmp(type, "INFO")) + std::cout << stream.str() << std::endl; + else + std::cerr << stream.str() << std::endl; + } + } +}; + +} +#endif diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp new file mode 100644 index 000000000..7616aa85c --- /dev/null +++ b/modules/dnn/src/dnn.cpp @@ -0,0 +1,606 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "precomp.hpp" +#include +#include +#include +#include + +using namespace cv; +using namespace cv::dnn; + +using std::vector; +using std::map; +using std::make_pair; +using std::set; + +namespace cv +{ +namespace dnn +{ + +template +String toString(const T &v) +{ + std::ostringstream ss; + ss << v; + return ss.str(); +} + +struct LayerPin +{ + int lid; + int oid; + + LayerPin(int layerId = -1, int outputId = -1) + : lid(layerId), oid(outputId) {} + + bool valid() const + { + return (lid >= 0 && oid >= 0); + } + + bool equal(const LayerPin &r) const + { + return (lid == r.lid && oid == r.oid); + } +}; + +struct LayerData +{ + LayerData() {} + LayerData(int _id, const String &_name, const String &_type, LayerParams &_params) + : id(_id), name(_name), type(_type), params(_params) + { + //add logging info + params.name = name; + params.type = type; + } + + int id; + String name; + String type; + LayerParams params; + + std::vector inputBlobsId; + std::set inputLayersId; + std::set requiredOutputs; + + Ptr layerInstance; + std::vector outputBlobs; + std::vector inputBlobs; + + int flag; + + Ptr getLayerInstance() + { + if (layerInstance) + return layerInstance; + + layerInstance = LayerFactory::createLayerInstance(type, params); + if (!layerInstance) + { + CV_Error(Error::StsError, "Can't create layer \"" + name + "\" of type \"" + type + "\""); + } + + return layerInstance; + } +}; + +//fake layer containing network input blobs +struct NetInputLayer : public Layer +{ + void allocate(const std::vector&, std::vector&) {} + void forward(std::vector&, std::vector&) {} + + int outputNameToIndex(String tgtName) + { + int idx = (int)(std::find(outNames.begin(), outNames.end(), tgtName) - outNames.begin()); + return (idx < (int)outNames.size()) ? idx : -1; + } + + void setNames(const std::vector &names) + { + outNames.assign(names.begin(), names.end()); + } + +private: + std::vector outNames; +}; + +struct Net::Impl +{ + Impl() + { + //allocate fake net input layer + netInputLayer = Ptr(new NetInputLayer()); + LayerData &inpl = layers.insert( make_pair(0, LayerData()) ).first->second; + inpl.id = 0; + inpl.name = "_input"; + inpl.type = "__NetInputLayer__"; + inpl.layerInstance = netInputLayer; + + lastLayerId = 1; + netWasAllocated = false; + } + + Ptr netInputLayer; + std::vector netOutputs; + + typedef std::map MapIdToLayerData; + std::map layers; + std::map layerNameToId; + + int lastLayerId; + + bool netWasAllocated; + + void setUpNet() + { + if (!netWasAllocated) + { + allocateLayers(); + computeNetOutputLayers(); + + netWasAllocated = true; + } + } + + int getLayerId(const String &layerName) + { + std::map::iterator it = layerNameToId.find(layerName); + return (it != layerNameToId.end()) ? it->second : -1; + } + + int getLayerId(int id) + { + MapIdToLayerData::iterator it = layers.find(id); + return (it != layers.end()) ? id : -1; + } + + int getLayerId(DictValue &layerDesc) + { + if (layerDesc.isInt()) + return getLayerId(layerDesc.get()); + else if (layerDesc.isString()) + return getLayerId(layerDesc.get()); + + CV_Assert(layerDesc.isInt() || layerDesc.isString()); + return -1; + } + + String getLayerName(int id) + { + MapIdToLayerData::iterator it = layers.find(id); + return (it != layers.end()) ? it->second.name : "(unknown layer)"; + } + + LayerData& getLayerData(int id) + { + MapIdToLayerData::iterator it = layers.find(id); + + if (it == layers.end()) + CV_Error(Error::StsObjectNotFound, format("Layer with requested id=%d not found", id)); + + return it->second; + } + + LayerData& getLayerData(const String &layerName) + { + int id = getLayerId(layerName); + + if (id < 0) + CV_Error(Error::StsError, "Requsted layer \"" + layerName + "\" not found"); + + return getLayerData(id); + } + + LayerData& getLayerData(const DictValue &layerDesc) + { + if (layerDesc.isInt()) + return getLayerData(layerDesc.get()); + else if (layerDesc.isString()) + return getLayerData(layerDesc.get()); + + CV_Assert(layerDesc.isInt() || layerDesc.isString()); + return *((LayerData*)NULL); + } + + static void addLayerInput(LayerData &ld, int inNum, LayerPin from) + { + if ((int)ld.inputBlobsId.size() <= inNum) + { + ld.inputBlobsId.resize(inNum + 1); + } + else + { + LayerPin storedFrom = ld.inputBlobsId[inNum]; + if (storedFrom.valid() && !storedFrom.equal(from)) + CV_Error(Error::StsError, "Input #" + toString(inNum) + "of layer \"" + ld.name + "\" already was connected"); + } + + ld.inputBlobsId[inNum] = from; + } + + static void splitPin(const String &pinAlias, String &layerName, String &outName) + { + size_t delimPos = pinAlias.find('.'); + layerName = pinAlias.substr(0, delimPos); + outName = (delimPos == String::npos) ? String() : pinAlias.substr(delimPos + 1); + } + + int resolvePinOutputName(LayerData &ld, const String &outName, bool isOutPin) + { + if (outName.empty()) + return 0; + + if (std::isdigit(outName[0])) + { + char *lastChar; + long inum = std::strtol(outName.c_str(), &lastChar, 10); + + if (*lastChar == 0) + { + CV_Assert(inum == (int)inum); + return (int)inum; + } + } + + if (isOutPin) + return ld.getLayerInstance()->outputNameToIndex(outName); + else + return ld.getLayerInstance()->inputNameToIndex(outName); + } + + LayerPin getPinByAlias(const String &pinAlias, bool isOutPin = true) + { + LayerPin pin; + String layerName, outName; + splitPin(pinAlias, layerName, outName); + + pin.lid = (layerName.empty()) ? 0 : getLayerId(layerName); + + if (pin.lid >= 0) + pin.oid = resolvePinOutputName(getLayerData(pin.lid), outName, isOutPin); + + return pin; + } + + void connect(int outLayerId, int outNum, int inLayerId, int inNum) + { + LayerData &ldOut = getLayerData(outLayerId); + LayerData &ldInp = getLayerData(inLayerId); + + addLayerInput(ldInp, inNum, LayerPin(outLayerId, outNum)); + ldOut.requiredOutputs.insert(outNum); + } + + void computeNetOutputLayers() + { + netOutputs.clear(); + + MapIdToLayerData::iterator it; + for (it = layers.begin(); it != layers.end(); it++) + { + int lid = it->first; + LayerData &ld = it->second; + + if (ld.requiredOutputs.size() == 0) + netOutputs.push_back(lid); + } + + std::cout << "\nNet Outputs(" << netOutputs.size() << "):\n"; + for (size_t i = 0; i < netOutputs.size(); i++) + std::cout << layers[netOutputs[i]].name << std::endl; + } + + void allocateLayer(int lid) + { + LayerData &ld = layers[lid]; + + //already allocated + if (ld.flag) + return; + + //determine parent layers + for (size_t i = 0; i < ld.inputBlobsId.size(); i++) + ld.inputLayersId.insert(ld.inputBlobsId[i].lid); + + //allocate parents + for (set::iterator i = ld.inputLayersId.begin(); i != ld.inputLayersId.end(); i++) + allocateLayer(*i); + + //bind inputs + ld.inputBlobs.resize(ld.inputBlobsId.size()); + for (size_t i = 0; i < ld.inputBlobsId.size(); i++) + { + LayerPin from = ld.inputBlobsId[i]; + CV_Assert(from.valid()); + CV_DbgAssert(layers.count(from.lid) && (int)layers[from.lid].outputBlobs.size() > from.oid); + ld.inputBlobs[i] = &layers[from.lid].outputBlobs[from.oid]; + } + + //allocate layer + ld.outputBlobs.resize(std::max((size_t)1, ld.requiredOutputs.size())); //layer produce at least one output blob + ld.getLayerInstance()->allocate(ld.inputBlobs, ld.outputBlobs); + + ld.flag = 1; + } + + void allocateLayers() + { + MapIdToLayerData::iterator it; + for (it = layers.begin(); it != layers.end(); it++) + it->second.flag = 0; + + for (it = layers.begin(); it != layers.end(); it++) + { + int lid = it->first; + allocateLayer(lid); + } + } + + void forwardLayer(LayerData &ld, bool clearFlags = true) + { + if (clearFlags) + { + MapIdToLayerData::iterator it; + for (it = layers.begin(); it != layers.end(); it++) + it->second.flag = 0; + } + + //already was forwarded + if (ld.flag) + return; + + //forward parents + for (set::iterator i = ld.inputLayersId.begin(); i != ld.inputLayersId.end(); i++) + { + forwardLayer(layers[*i], false); + } + + //forward itself + ld.layerInstance->forward(ld.inputBlobs, ld.outputBlobs); + + ld.flag = 1; + } + + void forwardAll() + { + MapIdToLayerData::iterator it; + for (it = layers.begin(); it != layers.end(); it++) + it->second.flag = 0; + + for (it = layers.begin(); it != layers.end(); it++) + forwardLayer(it->second, false); + } +}; + +Net::Net() : impl(new Net::Impl) +{ + +} + +Net::~Net() +{ + +} + +int Net::addLayer(const String &name, const String &type, LayerParams ¶ms) +{ + if (name.find('.') != String::npos) + { + CV_Error(Error::StsBadArg, "Added layer name \"" + name + "\" must not contain dot symbol"); + return -1; + } + + if (impl->getLayerId(name) >= 0) + { + CV_Error(Error::StsBadArg, "Layer \"" + name + "\" already into net"); + return -1; + } + + int id = ++impl->lastLayerId; + impl->layerNameToId.insert(std::make_pair(name, id)); + impl->layers.insert(std::make_pair(id, LayerData(id, name, type, params))); + + return id; +} + +int Net::addLayerToPrev(const String &name, const String &type, LayerParams ¶ms) +{ + int prvLid = impl->lastLayerId; + int newLid = this->addLayer(name, type, params); + this->connect(prvLid, 0, newLid, 0); + return newLid; +} + +void Net::connect(int outLayerId, int outNum, int inpLayerId, int inpNum) +{ + impl->connect(outLayerId, outNum, inpLayerId, inpNum); +} + +void Net::connect(String _outPin, String _inPin) +{ + LayerPin outPin = impl->getPinByAlias(_outPin); + LayerPin inpPin = impl->getPinByAlias(_inPin); + + CV_Assert(outPin.valid() && inpPin.valid()); + + impl->connect(outPin.lid, outPin.oid, inpPin.lid, inpPin.oid); +} + +void Net::forward() +{ + impl->setUpNet(); + impl->forwardAll(); +} + +void Net::forward(LayerId toLayer) +{ + impl->setUpNet(); + impl->forwardLayer(impl->getLayerData(toLayer)); +} + +void Net::setNetInputs(const std::vector &inputBlobNames) +{ + impl->netInputLayer->setNames(inputBlobNames); +} + +void Net::setBlob(String outputName, const Blob &blob) +{ + LayerPin pin = impl->getPinByAlias(outputName); + if (!pin.valid()) + CV_Error(Error::StsObjectNotFound, "Requested blob \"" + outputName + "\" not found"); + + LayerData &ld = impl->layers[pin.lid]; + ld.outputBlobs.resize( std::max(pin.oid+1, (int)ld.requiredOutputs.size()) ); + ld.outputBlobs[pin.oid] = blob; +} + +Blob Net::getBlob(String outputName) +{ + LayerPin pin = impl->getPinByAlias(outputName); + if (!pin.valid()) + CV_Error(Error::StsObjectNotFound, "Requested blob \"" + outputName + "\" not found"); + + LayerData &ld = impl->layers[pin.lid]; + if ((size_t)pin.oid >= ld.outputBlobs.size()) + { + CV_Error(Error::StsOutOfRange, "Layer \"" + ld.name + "\" produce only " + toString(ld.outputBlobs.size()) + + " outputs, the #" + toString(pin.oid) + " was requsted"); + } + return ld.outputBlobs[pin.oid]; +} + +Blob Net::getParam(LayerId layer, int numParam) +{ + LayerData &ld = impl->getLayerData(layer); + + std::vector &layerBlobs = ld.layerInstance->blobs; + CV_Assert(numParam < (int)layerBlobs.size()); + return layerBlobs[numParam]; +} + +int Net::getLayerId(const String &layer) +{ + return impl->getLayerId(layer); +} + +void Net::deleteLayer(LayerId) +{ + CV_Error(Error::StsNotImplemented, ""); +} + +////////////////////////////////////////////////////////////////////////// + +Importer::~Importer() {} + +Layer::Layer() {} + +Layer::Layer(const LayerParams ¶ms) + : blobs(params.blobs), name(params.name), type(params.type) +{ + +} + +int Layer::inputNameToIndex(String) +{ + return -1; +} + +int Layer::outputNameToIndex(String) +{ + return -1; +} + +Layer::~Layer() {} + +////////////////////////////////////////////////////////////////////////// + +struct LayerFactory::Impl : public std::map +{ +}; + +Ptr LayerFactory::impl () +{ + // allocate on first use + static Ptr impl_(new LayerFactory::Impl()); + return impl_; +} + +void LayerFactory::registerLayer(const String &_type, Constuctor constructor) +{ + String type = _type.toLowerCase(); + Impl::iterator it = impl()->find(type); + + if (it != impl()->end() && it->second != constructor) + { + CV_Error(cv::Error::StsBadArg, "Layer \"" + type + "\" already was registered"); + } + + impl()->insert(std::make_pair(type, constructor)); +} + +void LayerFactory::unregisterLayer(const String &_type) +{ + String type = _type.toLowerCase(); + impl()->erase(type); +} + +Ptr LayerFactory::createLayerInstance(const String &_type, LayerParams& params) +{ + String type = _type.toLowerCase(); + Impl::const_iterator it = LayerFactory::impl()->find(type); + + if (it != impl()->end()) + { + return it->second(params); + } + else + { + return Ptr(); //NULL + } +} + +} +} diff --git a/modules/dnn/src/init.cpp b/modules/dnn/src/init.cpp new file mode 100644 index 000000000..3d951e125 --- /dev/null +++ b/modules/dnn/src/init.cpp @@ -0,0 +1,105 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "precomp.hpp" + +#include "layers/concat_layer.hpp" +#include "layers/convolution_layer.hpp" +#include "layers/blank_layer.hpp" +#include "layers/elementwise_layers.hpp" +#include "layers/fully_connected_layer.hpp" +#include "layers/lrn_layer.hpp" +#include "layers/mvn_layer.hpp" +#include "layers/pooling_layer.hpp" +#include "layers/reshape_layer.hpp" +#include "layers/slice_layer.hpp" +#include "layers/softmax_layer.hpp" +#include "layers/split_layer.hpp" + +namespace cv +{ +namespace dnn +{ + +struct AutoInitializer +{ + bool status; + + AutoInitializer() : status(false) + { + cv::dnn::initModule(); + } +}; + +static AutoInitializer init; + +void initModule() +{ + if (init.status) + return; + + REG_RUNTIME_LAYER_CLASS(Slice, SliceLayer) + REG_RUNTIME_LAYER_CLASS(Softmax, SoftMaxLayer) + REG_RUNTIME_LAYER_CLASS(Split, SplitLayer) + REG_RUNTIME_LAYER_CLASS(Reshape, ReshapeLayer) + REG_STATIC_LAYER_FUNC(Flatten, createFlattenLayer) + REG_RUNTIME_LAYER_CLASS(Pooling, PoolingLayer) + REG_RUNTIME_LAYER_CLASS(MVN, MVNLayer) + REG_RUNTIME_LAYER_CLASS(LRN, LRNLayer) + REG_RUNTIME_LAYER_CLASS(InnerProduct, FullyConnectedLayer) + + REG_RUNTIME_LAYER_CLASS(ReLU, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(TanH, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(BNLL, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(Power, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(AbsVal, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(Sigmoid, ElementWiseLayer) + REG_RUNTIME_LAYER_CLASS(Dropout, BlankLayer) + + REG_RUNTIME_LAYER_CLASS(Convolution, ConvolutionLayer) + REG_RUNTIME_LAYER_CLASS(Deconvolution, DeConvolutionLayer) + REG_RUNTIME_LAYER_CLASS(Concat, ConcatLayer) + + init.status = true; +} + +} +} diff --git a/modules/dnn/src/layers/blank_layer.hpp b/modules/dnn/src/layers/blank_layer.hpp new file mode 100644 index 000000000..6d93f278a --- /dev/null +++ b/modules/dnn/src/layers/blank_layer.hpp @@ -0,0 +1,74 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_BLANK_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_BLANK_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class BlankLayer : public Layer + { + public: + + BlankLayer(LayerParams&) + { + + } + + void allocate(const std::vector &inputs, std::vector &outputs) + { + outputs.resize(inputs.size()); + for (size_t i = 0; i < inputs.size(); i++) + outputs[i].shareFrom(*inputs[i]); + } + + void forward(std::vector &inputs, std::vector &outputs) + { + for (size_t i = 0; i < inputs.size(); i++) + outputs[i] = *inputs[i]; + } + }; +} +} +#endif diff --git a/modules/dnn/src/layers/concat_layer.cpp b/modules/dnn/src/layers/concat_layer.cpp new file mode 100644 index 000000000..24ef4fd8b --- /dev/null +++ b/modules/dnn/src/layers/concat_layer.cpp @@ -0,0 +1,101 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "concat_layer.hpp" + +namespace cv +{ +namespace dnn +{ + ConcatLayer::ConcatLayer(LayerParams ¶ms) : Layer(params) + { + axis = params.get("axis", 1); + CV_Assert(axis >= 0); + } + + void ConcatLayer::allocate(const std::vector &inputs, std::vector &outputs) + { + CV_Assert(inputs.size() > 0); + + int refType = inputs[0]->type(); + BlobShape refShape = inputs[0]->shape(); + CV_Assert(axis < refShape.dims()); + + int axisSum = 0; + for (size_t i = 0; i < inputs.size(); i++) + { + BlobShape curShape = inputs[i]->shape(); + + CV_Assert(curShape.dims() == refShape.dims() && inputs[i]->type() == refType); + for (int axisId = 0; axisId < refShape.dims(); axisId++) + { + if (axisId != axis && refShape[axisId] != curShape[axisId]) + CV_Error(Error::StsBadSize, "Inconsitent shape for ConcatLayer"); + } + + axisSum += curShape[axis]; + } + + refShape[axis] = axisSum; + outputs.resize(1); + outputs[0].create(refShape); + } + + void ConcatLayer::forward(std::vector &inputs, std::vector &outputs) + { + const Mat& outMat = outputs[0].matRef(); + std::vector ranges(outputs[0].dims(), Range::all()); + int sizeStart = 0; + for (size_t i = 0; i < inputs.size(); i++) + { + int sizeEnd = sizeStart + inputs[i]->size(axis); + ranges[axis] = Range(sizeStart, sizeEnd); + + Mat outSubMat = outMat(&ranges[0]); + inputs[i]->matRef().copyTo(outSubMat); + + sizeStart = sizeEnd; + } + } +} +} diff --git a/modules/dnn/src/layers/concat_layer.hpp b/modules/dnn/src/layers/concat_layer.hpp new file mode 100644 index 000000000..fbc491ce2 --- /dev/null +++ b/modules/dnn/src/layers/concat_layer.hpp @@ -0,0 +1,61 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_CONCAT_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_CONCAT_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class ConcatLayer : public Layer + { + int axis; + + public: + ConcatLayer(LayerParams& params); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp new file mode 100644 index 000000000..13bc1911b --- /dev/null +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -0,0 +1,251 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include +#include "layers_common.hpp" +#include "convolution_layer.hpp" +#include "im2col.hpp" +#include + +namespace cv +{ +namespace dnn +{ + ConvolutionLayer::ConvolutionLayer(LayerParams ¶ms) : Layer(params) + { + getKernelParams(params, kerH, kerW, padH, padW, strideH, strideW); + + numOutput = params.get("num_output"); + bias = params.get("bias_term", true); + group = params.get("group", 1); + CV_Assert(numOutput % group == 0); + + CV_Assert(!bias || blobs.size() == 2); + CV_Assert( bias || blobs.size() == 1); + + const Blob &wgtBlob = blobs[0]; + CV_Assert(wgtBlob.dims() == 4 && wgtBlob.cols() == kerW && wgtBlob.rows() == kerH); + + if (bias) + { + Blob &biasBlob = blobs[1]; + CV_Assert(biasBlob.total() == (size_t)numOutput); + } + + //TBD + useOpenCL = params.has("use_opencl"); + } + + void ConvolutionLayer::allocate(const std::vector &inputs, std::vector &outputs) + { + CV_Assert(inputs.size() > 0); + + const Blob &inpBlob = *inputs[0]; + CV_Assert(inpBlob.dims() == 4 && inpBlob.type() == CV_32F); + computeInpOutShape(inpBlob); + + CV_Assert(inpCn % group == 0 && outCn % group == 0); + CV_Assert(blobs[0].num() == outCn && blobs[0].channels() == inpCn / group); + + outGroupCn = outCn / group; + inpGroupCn = inpCn / group; + ksize = inpGroupCn * kerH * kerW; + + outputs.resize(inputs.size()); + for (size_t i = 0; i < inputs.size(); i++) + { + CV_Assert(inputs[i]->type() == inpBlob.type()); + CV_Assert(inputs[i]->dims() == 4 && inputs[i]->channels() == inpBlob.channels()); + CV_Assert(inputs[i]->rows() == inpBlob.rows() && inputs[i]->cols() == inpBlob.cols()); + + outputs[i].create(BlobShape(inputs[i]->num(), topCn, topH, topW)); + } + + if (!is1x1()) + colMat.create(ksize, outH * outW, inpBlob.type()); + + if (bias) + biasOnesMat = Mat::ones(1, topH * topW, inpBlob.type()); + } + + inline bool ConvolutionLayer::is1x1() const + { + return (kerH == 1 && kerW == 1); + } + + void ConvolutionLayer::forward(std::vector &inputs, std::vector &outputs) + { + Blob &wgtBlob = blobs[0]; + + for (size_t ii = 0; ii < outputs.size(); ii++) + { + Blob &inpBlob = *inputs[ii]; + Blob &outBlob = outputs[ii]; + + for (int n = 0; n < inpBlob.num(); n++) + { + for (int g = 0; g < group; g++) + { + im2col(inpBlob, n, g); + + Mat kerMat(outGroupCn, ksize, wgtBlob.type(), wgtBlob.ptr(g*outGroupCn)); + Mat dstMat(outGroupCn, outH*outW, outBlob.type(), outBlob.ptr(n, g*outGroupCn)); + + cv::gemm(kerMat, colMat, 1, noArray(), 0, dstMat); + + if (bias) + { + float *biasPtr = blobs[1].ptrf() + g*outGroupCn; + Mat biasMat(outGroupCn, 1, CV_32F, biasPtr); + cv::gemm(biasMat, biasOnesMat, 1, dstMat, 1, dstMat); + } + } + } + } + } + + void ConvolutionLayer::im2col(Blob &inpBlob, int imNum, int cnGroup) + { + uchar *srcPtr = inpBlob.ptr(imNum, cnGroup*inpGroupCn); + + if (is1x1()) + { + colMat = Mat(ksize, inpBlob.rows()*inpBlob.cols(), inpBlob.type(), srcPtr); + return; + } + +#ifdef HAVE_OPENCL + if (useOpenCL && ocl::useOpenCL() && inpBlob.type() == CV_32F && !is1x1()) + { + std::vector ranges(4, Range::all()); + ranges[0] = Range(imNum, imNum+1); + ranges[1] = Range(cnGroup*inpGroupCn, (cnGroup + 1)*inpGroupCn); + + UMat src = inpBlob.matRef()(&ranges[0]).getUMat(ACCESS_READ); + UMat dst(colMat.size(), colMat.type()); + im2col_ocl(src, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, dst); + dst.copyTo(colMat); + return; + } +#endif // HAVE_OPENCL + + if (inpBlob.type() == CV_32F) + im2col_cpu((float *)srcPtr, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, (float *)colMat.ptr()); + if (inpBlob.type() == CV_64F) + im2col_cpu((double*)srcPtr, inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, (double*)colMat.ptr()); + } + + void ConvolutionLayer::computeInpOutShape(const Blob &inpBlob) + { + inpH = inpBlob.rows(); + inpW = inpBlob.cols(); + inpCn = inpBlob.channels(); + + outH = (inpH + 2 * padH - kerH) / strideH + 1; + outW = (inpW + 2 * padW - kerW) / strideW + 1; + outCn = numOutput; + + topH = outH; topW = outW; topCn = outCn; + } + + DeConvolutionLayer::DeConvolutionLayer(LayerParams ¶ms) + : ConvolutionLayer(params) {} + + void DeConvolutionLayer::computeInpOutShape(const Blob &inpBlob) + { + outH = inpBlob.rows(); + outW = inpBlob.cols(); + outCn = inpBlob.channels(); + + inpH = strideH * (outH - 1) + kerH - 2 * padH; + inpW = strideW * (outW - 1) + kerW - 2 * padW; + inpCn = numOutput; + + topH = inpH; topW = inpW; topCn = inpCn; + } + + void DeConvolutionLayer::forward(std::vector &inputs, std::vector &outputs) + { + Blob &wghtBlob = blobs[0]; + + for (size_t ii = 0; ii < outputs.size(); ii++) + { + Blob &convBlob = *inputs[ii]; + Blob &decnBlob = outputs[ii]; + + for (int n = 0; n < convBlob.num(); n++) + { + for (int g = 0; g < group; g++) + { + Mat dstMat(inpGroupCn, inpH*inpW, decnBlob.type(), decnBlob.ptr(n, g*inpGroupCn)); + + if (is1x1()) + colMat = dstMat; + + Mat convMat(outGroupCn, outH*outW, convBlob.type(), convBlob.ptr(n, g*outGroupCn)); + Mat wghtMat(outGroupCn, ksize, wghtBlob.type(), wghtBlob.ptr(g*outGroupCn)); + cv::gemm(wghtMat, convMat, 1, noArray(), 0, colMat, GEMM_1_T); + + col2im(dstMat); + + if (bias) + { + float *biasPtr = blobs[1].ptrf() + g*inpGroupCn; + Mat biasMat(inpGroupCn, 1, CV_32F, biasPtr); + cv::gemm(biasMat, biasOnesMat, 1, dstMat, 1, dstMat); + } + } + } + } + } + + void DeConvolutionLayer::col2im(Mat &dstMat) + { + if (is1x1()) return; + + if (dstMat.type() == CV_32F) + col2im_cpu((float*)colMat.ptr(), inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, (float*)dstMat.ptr()); + if (dstMat.type() == CV_64F) + col2im_cpu((double*)colMat.ptr(), inpGroupCn, inpH, inpW, kerH, kerW, padH, padW, strideH, strideW, (double*)dstMat.ptr()); + } +} +} diff --git a/modules/dnn/src/layers/convolution_layer.hpp b/modules/dnn/src/layers/convolution_layer.hpp new file mode 100644 index 000000000..0598217af --- /dev/null +++ b/modules/dnn/src/layers/convolution_layer.hpp @@ -0,0 +1,92 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_CONVOLUTION_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_CONVOLUTION_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + //TODO: simultaneously convolution and bias addition for cache optimization + class ConvolutionLayer : public Layer + { + protected: + bool bias; + int numOutput, group; + int padH, padW; + int kerH, kerW; + int strideH, strideW; + + int inpH, inpW, inpCn; + int outH, outW, outCn; + int topH, topW, topCn; //switched between inp/out on deconv/conv + int inpGroupCn, outGroupCn; + int ksize; + + bool useOpenCL; + Mat colMat, biasOnesMat; + + inline bool is1x1() const; + virtual void computeInpOutShape(const Blob &inpBlob); + void im2col(Blob &inpBlob, int imNum, int cnGroup); + + public: + ConvolutionLayer() {} + ConvolutionLayer(LayerParams ¶ms); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); + }; + + class DeConvolutionLayer : public ConvolutionLayer + { + protected: + void computeInpOutShape(const Blob &inpBlob); + void col2im(Mat &dstMat); + + public: + DeConvolutionLayer(LayerParams ¶ms); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/elementwise_layers.hpp b/modules/dnn/src/layers/elementwise_layers.hpp new file mode 100644 index 000000000..e66066189 --- /dev/null +++ b/modules/dnn/src/layers/elementwise_layers.hpp @@ -0,0 +1,184 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_ELEMENTWISE_LAYERS_HPP__ +#define __OPENCV_DNN_LAYERS_ELEMENTWISE_LAYERS_HPP__ +#include "../precomp.hpp" +#include "layers_common.hpp" +#include + +namespace cv +{ +namespace dnn +{ + +using std::abs; +using std::exp; +using std::tanh; +using std::pow; + + template + class ElementWiseLayer : public Layer + { + Func func; + public: + + ElementWiseLayer(LayerParams &_params) : func(_params) {} + + void allocate(const std::vector &inputs, std::vector &outputs) + { + outputs.resize(inputs.size()); + for (size_t i = 0; i < inputs.size(); i++) + outputs[i].shareFrom(*inputs[i]); //no data copy + } + + void forward(std::vector &inputs, std::vector &outputs) + { + for (size_t i = 0; i < inputs.size(); i++) + { + CV_Assert(inputs[i]->ptr() == outputs[i].ptr() && inputs[i]->type() == outputs[i].type()); + + size_t size = outputs[i].total(); + + if (outputs[i].type() == CV_32F) + { + float *data = outputs[i].ptrf(); + for (size_t j = 0; j < size; j++) + data[j] = func(data[j]); + } + else if (outputs[i].type() == CV_64F) + { + double *data = outputs[i].ptr(); + for (size_t j = 0; j < size; j++) + data[j] = func(data[j]); + } + else + { + CV_Error(Error::StsNotImplemented, "Only CV_32F and CV_64F blobs are supported"); + } + } + } + }; + + + struct ReLUFunctor + { + float negative_slope; + + ReLUFunctor(LayerParams ¶ms) + { + if (params.has("negative_slope")) + negative_slope = params.get("negative_slope"); + else + negative_slope = 0.f; + } + + template + inline TFloat operator()(TFloat x) + { + return (x >= (TFloat)0) ? x : negative_slope * x; + } + }; + + struct TanHFunctor + { + TanHFunctor(LayerParams&) {} + + template + inline TFloat operator()(TFloat x) + { + return tanh(x); + } + }; + + struct SigmoidFunctor + { + SigmoidFunctor(LayerParams&) {} + + template + inline TFloat operator()(TFloat x) + { + return (TFloat)1 / ((TFloat)1 + exp(-x)); + } + }; + + struct AbsValFunctor + { + AbsValFunctor(LayerParams&) {} + + template + inline TFloat operator()(TFloat x) + { + return abs(x); + } + }; + + struct PowerFunctor + { + float power, scale, shift; + + PowerFunctor(LayerParams ¶ms) + { + power = params.get("power", 1.0f); + scale = params.get("scale", 1.0f); + shift = params.get("shift", 0.0f); + } + + template + inline TFloat operator()(TFloat x) + { + return pow((TFloat)shift + (TFloat)scale * x, (TFloat)power); + } + }; + + struct BNLLFunctor + { + BNLLFunctor(LayerParams&) {} + + template + inline TFloat operator()(TFloat x) + { + return log((TFloat)1 + exp(-abs(x))); + } + }; +} +} +#endif diff --git a/modules/dnn/src/layers/fully_connected_layer.cpp b/modules/dnn/src/layers/fully_connected_layer.cpp new file mode 100644 index 000000000..848080b66 --- /dev/null +++ b/modules/dnn/src/layers/fully_connected_layer.cpp @@ -0,0 +1,114 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "fully_connected_layer.hpp" + +namespace cv +{ +namespace dnn +{ + FullyConnectedLayer::FullyConnectedLayer(LayerParams ¶ms) : Layer(params) + { + numOutputs = params.get("num_output"); + bias = params.get("bias_term", true); + axis_ = params.get("axis", 1); + + CV_Assert(blobs.size() == (bias ? 2U : 1U)); + CV_Assert(blobs[0].dims() >= 2 && blobs[0].total() >= (size_t)numOutputs); + CV_Assert(!bias || blobs[1].total() == (size_t)numOutputs); + } + + void FullyConnectedLayer::allocate(const std::vector &input, std::vector &output) + { + CV_Assert(input.size() > 0); + + axis = input[0]->canonicalAxis(axis_); + innerSize = (int)input[0]->total(axis); + + CV_Assert((size_t)innerSize * (size_t)numOutputs == blobs[0].total()); + CV_Assert(blobs[0].size(-2) == numOutputs && blobs[0].size(-1) == innerSize); + + output.resize(input.size()); + for (size_t i = 0; i < input.size(); i++) + { + if (i != 0) + CV_Assert(input[i]->equalShape(*input[0])); + + this->reshape(*input[i], output[i]); + } + } + + void FullyConnectedLayer::reshape(const Blob &inp, Blob &out) + { + BlobShape inpShape = inp.shape(); + BlobShape outShape(axis+1, inpShape.ptr()); + outShape[axis] = numOutputs; + + out.create(outShape, inp.type()); + } + + void FullyConnectedLayer::forward(std::vector &input, std::vector &output) + { + for (size_t i = 0; i < input.size(); i++) + { + int M = (int)input[i]->total(0, axis); + int N = numOutputs; + int K = innerSize; + + Mat srcMat(M, K, input[i]->type(), input[i]->ptrf()); + Mat weight(N, K, blobs[0].type(), blobs[0].ptrf()); + Mat dstMat(M, N, output[i].type(), output[i].ptrf()); + + //important: Caffe stores weights as transposed array + cv::gemm(srcMat, weight, 1, noArray(), 0, dstMat, GEMM_2_T); + + if (bias) + { + Mat biasOnesMat = Mat::ones(M, 1, CV_32F); + Mat biasMat(1, N, CV_32F, blobs[1].ptrf()); + cv::gemm(biasOnesMat, biasMat, 1, dstMat, 1, dstMat); + } + } + } +} +} diff --git a/modules/dnn/src/layers/fully_connected_layer.hpp b/modules/dnn/src/layers/fully_connected_layer.hpp new file mode 100644 index 000000000..5213b98d8 --- /dev/null +++ b/modules/dnn/src/layers/fully_connected_layer.hpp @@ -0,0 +1,67 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_FULLY_CONNECTED_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_FULLY_CONNECTED_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class FullyConnectedLayer : public Layer + { + bool bias; + int numOutputs; + int axis_, axis; + + int innerSize; + + void reshape(const Blob &inp, Blob &out); + + public: + FullyConnectedLayer(LayerParams ¶ms); + void allocate(const std::vector &input, std::vector &output); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/im2col.cpp b/modules/dnn/src/layers/im2col.cpp new file mode 100644 index 000000000..a4f9e7675 --- /dev/null +++ b/modules/dnn/src/layers/im2col.cpp @@ -0,0 +1,85 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include +#include "im2col.hpp" +#include "opencl_kernels_dnn.hpp" + +namespace cv +{ +namespace dnn +{ + +#ifdef HAVE_OPENCL +void im2col_ocl(UMat &img, + int channels, int height, int width, + int kernel_h, int kernel_w, + int pad_h, int pad_w, + int stride_h, int stride_w, + UMat &col) +{ + int h_out = (height + 2 * pad_h - kernel_h) / stride_h + 1; + int w_out = (width + 2 * pad_w - kernel_w) / stride_w + 1; + + CV_Assert(img.isContinuous() && col.isContinuous()); + CV_Assert(img.total() == (size_t)channels * height * width); + CV_Assert(col.total() == (size_t)channels * kernel_h * kernel_w * h_out * w_out); + + ocl::Kernel im2col_ker("im2col", ocl::dnn::im2col_oclsrc); + CV_Assert(!im2col_ker.empty()); + + im2col_ker.args(ocl::KernelArg::PtrReadOnly(img), (int)img.offset, + channels, height, width, + kernel_h, kernel_w, pad_h, pad_w, stride_h, stride_w, + h_out, w_out, + ocl::KernelArg::PtrWriteOnly(col), (int)col.offset + ); + + size_t localSize = ocl::Device::getDefault().maxWorkGroupSize(); + size_t globalSize = (size_t)channels * h_out * w_out; + + CV_Assert(im2col_ker.run(1, &globalSize, &localSize, true)); +} +#endif // HAVE_OPENCL + +} +} diff --git a/modules/dnn/src/layers/im2col.hpp b/modules/dnn/src/layers/im2col.hpp new file mode 100644 index 000000000..d3353e332 --- /dev/null +++ b/modules/dnn/src/layers/im2col.hpp @@ -0,0 +1,126 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_IM2COL_HPP__ +#define __OPENCV_DNN_LAYERS_IM2COL_HPP__ + +namespace cv +{ +namespace dnn +{ + +template +void im2col_cpu(const Dtype* data_im, + int channels, int height, int width, + int kernel_h, int kernel_w, + int pad_h, int pad_w, + int stride_h, int stride_w, + Dtype* data_col) +{ + int height_col = (height + 2 * pad_h - kernel_h) / stride_h + 1; + int width_col = (width + 2 * pad_w - kernel_w) / stride_w + 1; + int channels_col = channels * kernel_h * kernel_w; + for (int c = 0; c < channels_col; ++c) { + int w_offset = c % kernel_w; + int h_offset = (c / kernel_w) % kernel_h; + int c_im = c / kernel_h / kernel_w; + for (int h = 0; h < height_col; ++h) { + for (int w = 0; w < width_col; ++w) { + int h_pad = h * stride_h - pad_h + h_offset; + int w_pad = w * stride_w - pad_w + w_offset; + if (h_pad >= 0 && h_pad < height && w_pad >= 0 && w_pad < width) + data_col[(c * height_col + h) * width_col + w] = + data_im[(c_im * height + h_pad) * width + w_pad]; + else + data_col[(c * height_col + h) * width_col + w] = 0; + } + } + } +} + +template +void col2im_cpu(const Dtype* data_col, + int channels, int height, int width, + int patch_h, int patch_w, + int pad_h, int pad_w, + int stride_h, int stride_w, + Dtype* data_im) +{ + memset(data_im, 0, height * width * channels * sizeof(Dtype)); + + int height_col = (height + 2 * pad_h - patch_h) / stride_h + 1; + int width_col = (width + 2 * pad_w - patch_w) / stride_w + 1; + int channels_col = channels * patch_h * patch_w; + + for (int c = 0; c < channels_col; ++c) + { + int w_offset = c % patch_w; + int h_offset = (c / patch_w) % patch_h; + int c_im = c / patch_h / patch_w; + + for (int h = 0; h < height_col; ++h) + { + for (int w = 0; w < width_col; ++w) + { + int h_pad = h * stride_h - pad_h + h_offset; + int w_pad = w * stride_w - pad_w + w_offset; + + if (h_pad >= 0 && h_pad < height && w_pad >= 0 && w_pad < width) + data_im[(c_im * height + h_pad) * width + w_pad] += + data_col[(c * height_col + h) * width_col + w]; + } + } + } +} + +#ifdef HAVE_OPENCL +void im2col_ocl(UMat &img, + int channels, int height, int width, + int kernel_h, int kernel_w, + int pad_h, int pad_w, + int stride_h, int stride_w, + UMat &col); +#endif + +} +} + +#endif diff --git a/modules/dnn/src/layers/layers_common.cpp b/modules/dnn/src/layers/layers_common.cpp new file mode 100644 index 000000000..e3fedd983 --- /dev/null +++ b/modules/dnn/src/layers/layers_common.cpp @@ -0,0 +1,89 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "layers_common.hpp" + +namespace cv +{ +namespace dnn +{ + +void getKernelParams(LayerParams ¶ms, int &kernelH, int &kernelW, int &padH, int &padW, int &strideH, int &strideW) +{ + if (params.has("kernel_h") && params.has("kernel_w")) + { + kernelH = params.get("kernel_h"); + kernelW = params.get("kernel_w"); + } + else if (params.has("kernel_size")) + { + kernelH = kernelW = params.get("kernel_size"); + } + else + { + CV_Error(cv::Error::StsBadArg, "kernel_size (or kernel_h and kernel_w) not specified"); + } + + if (params.has("pad_h") && params.has("pad_w")) + { + padH = params.get("pad_h"); + padW = params.get("pad_w"); + } + else + { + padH = padW = params.get("pad", 0); + } + + if (params.has("stride_h") && params.has("stride_w")) + { + strideH = params.get("stride_h"); + strideW = params.get("stride_w"); + } + else + { + strideH = strideW = params.get("stride", 1); + } + + CV_Assert(kernelH > 0 && kernelW > 0 && padH >= 0 && padW >= 0 && strideH > 0 && strideW > 0); +} + +} +} diff --git a/modules/dnn/src/layers/layers_common.hpp b/modules/dnn/src/layers/layers_common.hpp new file mode 100644 index 000000000..1637bd84d --- /dev/null +++ b/modules/dnn/src/layers/layers_common.hpp @@ -0,0 +1,56 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_LAYERS_COMMON_HPP__ +#define __OPENCV_DNN_LAYERS_LAYERS_COMMON_HPP__ +#include + +namespace cv +{ +namespace dnn +{ + +void getKernelParams(LayerParams ¶ms, int &kernelH, int &kernelW, int &padH, int &padW, int &strideH, int &strideW); + +} +} + +#endif diff --git a/modules/dnn/src/layers/lrn_layer.cpp b/modules/dnn/src/layers/lrn_layer.cpp new file mode 100644 index 000000000..a55d8fe01 --- /dev/null +++ b/modules/dnn/src/layers/lrn_layer.cpp @@ -0,0 +1,164 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "lrn_layer.hpp" +#include +#include + +namespace cv +{ +namespace dnn +{ + LRNLayer::LRNLayer(LayerParams ¶ms) : Layer(params) + { + String nrmType = params.get("norm_region", "ACROSS_CHANNELS"); + if (nrmType == "ACROSS_CHANNELS") + type = CHANNEL_NRM; + else if (nrmType == "WITHIN_CHANNEL") + type = SPATIAL_NRM; + else + CV_Error(Error::StsBadArg, "Unknown region type \"" + nrmType + "\""); + + size = params.get("local_size", 5); + if (size % 2 != 1 || size <= 0) + CV_Error(Error::StsBadArg, "LRN layer supports only positive odd values for local_size"); + + alpha = params.get("alpha", 1); + beta = params.get("beta", 0.75); + } + + void LRNLayer::allocate(const std::vector &inputs, std::vector &outputs) + { + CV_Assert(inputs.size() == 1); + outputs.resize(1); + + Vec4i shape = inputs[0]->shape4(); + outputs[0].create(shape); + + shape[0] = 1; //maybe make shape[0] = 1 too + bufBlob.create(shape); + } + + void LRNLayer::forward(std::vector &inputs, std::vector &outputs) + { + Blob &src = *inputs[0]; + Blob &dst = outputs[0]; + + switch (type) + { + case CHANNEL_NRM: + channelNoramlization(src, dst); + break; + case SPATIAL_NRM: + spatialNormalization(src, dst); + break; + default: + CV_Error(cv::Error::StsNotImplemented, "Unimplemented mode of LRN layer"); + break; + } + } + + void LRNLayer::channelNoramlization(Blob &srcBlob, Blob &dstBlob) + { + CV_DbgAssert(srcBlob.ptr() != dstBlob.ptr()); + + int num = srcBlob.num(); + int channels = srcBlob.channels(); + int ksize = (size - 1) / 2; + + for (int n = 0; n < num; n++) + { + Mat accum = dstBlob.getPlane(n, channels-1); //trick for memory saving + accum.setTo(0); + + for (int cn = 0; cn < std::min(ksize, channels); cn++) + cv::accumulateSquare(srcBlob.getPlane(n, cn), accum); + + for (int cn = 0; cn < channels; cn++) + { + if (cn + ksize < channels) + { + cv::accumulateSquare(srcBlob.getPlane(n, cn + ksize), accum); + } + + if (cn - ksize - 1 >= 0) + { + Mat left = srcBlob.getPlane(n, cn - ksize - 1); + cv::subtract(accum, left.mul(left), accum); //subtractSquare + } + + Mat dst = dstBlob.getPlane(n, cn); + accum.convertTo(dst, dst.type(), alpha/size, 1); + cv::pow(dst, beta, dst); + cv::divide(srcBlob.getPlane(n, cn), dst, dst); + } + } + } + + void LRNLayer::spatialNormalization(Blob &srcBlob, Blob &dstBlob) + { + int num = srcBlob.num(); + int channels = srcBlob.channels(); + + for (int n = 0; n < num; n++) + { + for (int cn = 0; cn < channels; cn++) + { + Mat src = srcBlob.getPlane(n, cn); + Mat dst = dstBlob.getPlane(n, cn); + uchar *dataDst0 = dst.data; + + cv::pow(srcBlob.getPlane(n, cn), 2, dst); + //TODO: check border type + cv::boxFilter(dst, dst, dst.depth(), cv::Size(size, size), cv::Point(-1, -1), false, cv::BORDER_CONSTANT); + dst.convertTo(dst, dst.type(), alpha/(size*size), 1); + cv::pow(dst, beta, dst); + cv::divide(src, dst, dst); + + CV_Assert(dataDst0 == dst.data); //debug + } + } + } + +} +} diff --git a/modules/dnn/src/layers/lrn_layer.hpp b/modules/dnn/src/layers/lrn_layer.hpp new file mode 100644 index 000000000..c207e634e --- /dev/null +++ b/modules/dnn/src/layers/lrn_layer.hpp @@ -0,0 +1,75 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_LRN_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_LRN_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class LRNLayer : public Layer + { + enum + { + CHANNEL_NRM, + SPATIAL_NRM, + SPATIAL_CONTRAST_NRM //cuda-convnet feature + } type; + + int size; + double alpha, beta; + + Blob bufBlob; + + void channelNoramlization(Blob &src, Blob &dst); + void spatialNormalization(Blob &src, Blob &dst); + + public: + + LRNLayer(LayerParams ¶ms); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/mvn_layer.cpp b/modules/dnn/src/layers/mvn_layer.cpp new file mode 100644 index 000000000..eb9a7b558 --- /dev/null +++ b/modules/dnn/src/layers/mvn_layer.cpp @@ -0,0 +1,97 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "mvn_layer.hpp" + +namespace cv +{ +namespace dnn +{ + +MVNLayer::MVNLayer(LayerParams ¶ms) : Layer(params) +{ + eps = params.get("eps", 1e-9); + acrossChannels = params.get("across_channels", false); + normalizeVariance = params.get("normalize_variance", true); +} + +void MVNLayer::allocate(const std::vector &inputs, std::vector &outputs) +{ + outputs.resize(inputs.size()); + for (size_t i = 0; i < inputs.size(); i++) + { + CV_Assert(!acrossChannels || inputs[i]->dims() >= 2); + outputs[i].create(inputs[i]->shape(), inputs[i]->type()); + } +} + +void MVNLayer::forward(std::vector &inputs, std::vector &outputs) +{ + for (size_t inpIdx = 0; inpIdx < inputs.size(); inpIdx++) + { + Blob &inpBlob = *inputs[inpIdx]; + Blob &outBlob = outputs[inpIdx]; + + int workSize[2]; + int splitDim = (acrossChannels) ? 1 : 2; + workSize[0] = (int)inpBlob.total(0, splitDim); + workSize[1] = (int)inpBlob.total(splitDim); + + Mat inpMat = inpBlob.matRef().reshape(1, 2, workSize); + Mat outMat = outBlob.matRef().reshape(1, 2, workSize); + + Scalar mean, dev; + for (int i = 0; i < workSize[0]; i++) + { + Mat inpRow = inpMat.row(i); + Mat outRow = outMat.row(i); + + cv::meanStdDev(inpRow, mean, (normalizeVariance) ? dev : noArray()); + double alpha = (normalizeVariance) ? 1/(eps + dev[0]) : 1; + inpRow.convertTo(outRow, outRow.type(), alpha, -mean[0] * alpha); + } + } +} + +} +} diff --git a/modules/dnn/src/layers/mvn_layer.hpp b/modules/dnn/src/layers/mvn_layer.hpp new file mode 100644 index 000000000..431db7caa --- /dev/null +++ b/modules/dnn/src/layers/mvn_layer.hpp @@ -0,0 +1,65 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_MVN_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + +class MVNLayer : public Layer +{ + double eps; + bool acrossChannels, normalizeVariance; + +public: + + MVNLayer(LayerParams ¶ms); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); +}; + +} +} +#endif diff --git a/modules/dnn/src/layers/pooling_layer.cpp b/modules/dnn/src/layers/pooling_layer.cpp new file mode 100644 index 000000000..840b85f19 --- /dev/null +++ b/modules/dnn/src/layers/pooling_layer.cpp @@ -0,0 +1,207 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "pooling_layer.hpp" +#include +#include +using std::max; +using std::min; + +namespace cv +{ +namespace dnn +{ +//TODO: add ceil_mode param + + PoolingLayer::PoolingLayer(LayerParams ¶ms) : Layer(params) + { + if (params.has("pool")) + { + String pool = params.get("pool").toLowerCase(); + if (pool == "max") + type = MAX; + else if (pool == "ave") + type = AVE; + else if (pool == "stochastic") + type = STOCHASTIC; + else + CV_Error(cv::Error::StsBadArg, "Unknown pooling type \"" + pool + "\""); + } + else + { + type = MAX; + } + + getKernelParams(params, kernelH, kernelW, padH, padW, strideH, strideW); + } + + void PoolingLayer::allocate(const std::vector &inputs, std::vector &outputs) + { + CV_Assert(inputs.size() > 0); + + inpW = inputs[0]->cols(); + inpH = inputs[0]->rows(); + computeOutputShape(inpH, inpW); + + outputs.resize(inputs.size()); + for (size_t i = 0; i < inputs.size(); i++) + { + CV_Assert(inputs[i]->rows() == inpH && inputs[i]->cols() == inpW); + outputs[i].create(BlobShape(inputs[i]->num(), inputs[i]->channels(), outH, outW)); + } + } + + void PoolingLayer::forward(std::vector &inputs, std::vector &outputs) + { + for (size_t ii = 0; ii < inputs.size(); ii++) + { + switch (type) + { + case MAX: + maxPooling(*inputs[ii], outputs[ii]); + break; + case AVE: + avePooling(*inputs[ii], outputs[ii]); + break; + default: + CV_Error(cv::Error::StsNotImplemented, "Not implemented"); + break; + } + } + } + + void PoolingLayer::maxPooling(Blob &input, Blob &output) + { + CV_DbgAssert(output.rows() == outH && output.cols() == outW); + + for (int n = 0; n < input.num(); ++n) + { + for (int c = 0; c < input.channels(); ++c) + { + float *srcData = input.ptrf(n, c); + float *dstData = output.ptrf(n, c); + + for (int ph = 0; ph < outH; ++ph) + { + for (int pw = 0; pw < outW; ++pw) + { + int hstart = ph * strideH - padH; + int wstart = pw * strideW - padW; + int hend = min(hstart + kernelH, inpH); + int wend = min(wstart + kernelW, inpW); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + const int poolIndex = ph * outW + pw; + float max_val = -FLT_MAX; + + for (int h = hstart; h < hend; ++h) + for (int w = wstart; w < wend; ++w) + { + const int index = h * inpW + w; + if (srcData[index] > max_val) + max_val = srcData[index]; + } + + dstData[poolIndex] = max_val; + } + } + } + } + } + + void PoolingLayer::avePooling(Blob &input, Blob &output) + { + for (int n = 0; n < input.num(); ++n) + { + for (int c = 0; c < input.channels(); ++c) + { + float *srcData = input.ptrf(n, c); + float *dstData = output.ptrf(n, c); + + for (int ph = 0; ph < outH; ++ph) + { + for (int pw = 0; pw < outW; ++pw) + { + int hstart = ph * strideH - padH; + int wstart = pw * strideW - padW; + int hend = min(hstart + kernelH, inpH + padH); + int wend = min(wstart + kernelW, inpW + padW); + int poolSize = (hend - hstart) * (wend - wstart); + hstart = max(hstart, 0); + wstart = max(wstart, 0); + hend = min(hend, inpH); + wend = min(wend, inpW); + + dstData[ph * outW + pw] = 0.f; + + for (int h = hstart; h < hend; ++h) + for (int w = wstart; w < wend; ++w) + dstData[ph * outW + pw] += srcData[h * inpW + w]; + + dstData[ph * outW + pw] /= poolSize; + } + } + } + } + } + + void PoolingLayer::computeOutputShape(int inH, int inW) + { + //Yeah, something strange Caffe scheme-) + outH = static_cast(ceil(static_cast(inH + 2 * padH - kernelH) / strideH)) + 1; + outW = static_cast(ceil(static_cast(inW + 2 * padW - kernelW) / strideW)) + 1; + + if (padH || padW) + { + // If we have padding, ensure that the last pooling starts strictly + // inside the image (instead of at the padding); otherwise clip the last. + if ((outH - 1) * strideH >= inH + padH) + --outH; + if ((outW - 1) * strideW >= inW + padW) + --outW; + CV_Assert((outH - 1) * strideH < inH + padH); + CV_Assert((outW - 1) * strideW < inW + padW); + } + } +} +} diff --git a/modules/dnn/src/layers/pooling_layer.hpp b/modules/dnn/src/layers/pooling_layer.hpp new file mode 100644 index 000000000..1f1a22183 --- /dev/null +++ b/modules/dnn/src/layers/pooling_layer.hpp @@ -0,0 +1,78 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_POOLING_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_POOLING_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class PoolingLayer : public Layer + { + enum + { + MAX, + AVE, + STOCHASTIC + }; + + int type; + int padH, padW; + int strideH, strideW; + int kernelH, kernelW; + + int inpH, inpW; + int outH, outW; + + void computeOutputShape(int inpH, int inpW); + void maxPooling(Blob &input, Blob &output); + void avePooling(Blob &input, Blob &output); + + public: + PoolingLayer(LayerParams ¶ms); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/reshape_layer.cpp b/modules/dnn/src/layers/reshape_layer.cpp new file mode 100644 index 000000000..f5d4b1c21 --- /dev/null +++ b/modules/dnn/src/layers/reshape_layer.cpp @@ -0,0 +1,166 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "reshape_layer.hpp" + +namespace cv +{ +namespace dnn +{ + +ReshapeLayer::ReshapeLayer(LayerParams ¶ms) : Layer(params) +{ + inAxis = params.get("axis", 0); + inNumAxes = params.get("num_axes", -1); + CV_Assert(inNumAxes >= -1); + + autoAxisIdx = -1; + + if (!params.has("dim")) + { + shapeDesc = BlobShape(0); + return; + } + + DictValue paramShape = params.get("dim"); + shapeDesc = BlobShape(paramShape.size()); + + for (int i = 0; i < paramShape.size(); i++) + { + int dim = paramShape.get(i); + CV_Assert(dim >= -1); + + if (dim == -1) + { + if (autoAxisIdx != -1) + CV_Error(Error::StsBadArg, "New shape contains multiple -1 dims"); + autoAxisIdx = i; + } + + shapeDesc[i] = dim; + } +} + +void ReshapeLayer::allocate(const std::vector &inputs, std::vector &outputs) +{ + outputs.resize(inputs.size()); + + for (size_t i = 0; i < inputs.size(); i++) + { + Blob &inpBlob = *inputs[i]; + Blob &outBlob = outputs[i]; + BlobShape inpShape = inpBlob.shape(); + + int startAxis = (inAxis >= 0) ? inAxis : inpShape.dims() + 1 + inAxis; + int endAxis = (inNumAxes == -1) ? inpShape.dims() : startAxis + inNumAxes; + CV_Assert(0 <= startAxis && startAxis <= inpShape.dims()); + CV_Assert(0 <= endAxis && endAxis <= inpShape.dims()); + + int newDims = inpShape.dims() - (endAxis - startAxis) + shapeDesc.dims(); + BlobShape outShape(newDims); + + computeOutputShape(startAxis, endAxis, inpShape, outShape); + + outBlob.shareFrom(inpBlob); + outBlob.reshape(outShape); + } +} + +void ReshapeLayer::computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape) +{ + int idx = 0; + for (int i = 0; i < startAxis; i++) + outShape[idx++] = inpShape[i]; + + for (int i = 0; i < shapeDesc.dims(); i++) + { + if (shapeDesc[i] == 0) + { + int inpAxisIdx = startAxis + i; + if (inpAxisIdx < 0 || inpShape.dims() <= inpAxisIdx) + CV_Error(Error::StsOutOfRange, "copy dimension (which has zero size) is not presented into reshaped blob"); + outShape[idx++] = inpShape[startAxis + i]; + } + else + { + outShape[idx++] = (shapeDesc[i] > 0) ? shapeDesc[i] : 1; + } + } + + for (int i = endAxis; i < inpShape.dims(); i++) + outShape[idx++] = inpShape[i]; + + if (autoAxisIdx >= 0) + { + size_t total = inpShape.total(); + size_t curTotal = 1; + for (int i = 0; i < outShape.dims(); i++) + { + if (i != startAxis + autoAxisIdx) + curTotal *= outShape[i]; + } + + CV_DbgAssert(curTotal <= total && total % curTotal == 0); + + outShape[startAxis + autoAxisIdx] = (int)(total / curTotal); + } + + if (inpShape.total() != outShape.total()) + { + CV_Error(Error::StsUnmatchedSizes, "Mismatch between input and output blob elements count"); + } +} + + +Ptr createFlattenLayer(LayerParams&) +{ + LayerParams params; + + int shapeDesc[] = {0, -1}; + params.set("dim", DictValue::arrayInt(shapeDesc, 2)); + + return Ptr(new ReshapeLayer(params)); +} + +} +} diff --git a/modules/dnn/src/layers/reshape_layer.hpp b/modules/dnn/src/layers/reshape_layer.hpp new file mode 100644 index 000000000..0c3881c12 --- /dev/null +++ b/modules/dnn/src/layers/reshape_layer.hpp @@ -0,0 +1,71 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_RESHAPE_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + +class ReshapeLayer : public Layer +{ +public: + ReshapeLayer(LayerParams ¶ms); + + void allocate(const std::vector &inputs, std::vector &outputs); + + void forward(std::vector&, std::vector&) {} + +protected: + BlobShape shapeDesc; + int inAxis, inNumAxes, autoAxisIdx; + + void computeOutputShape(int startAxis, int endAxis, BlobShape &inpShape, BlobShape &outShape); +}; + +Ptr createFlattenLayer(LayerParams&); + +} +} +#endif diff --git a/modules/dnn/src/layers/slice_layer.cpp b/modules/dnn/src/layers/slice_layer.cpp new file mode 100644 index 000000000..68051e8bc --- /dev/null +++ b/modules/dnn/src/layers/slice_layer.cpp @@ -0,0 +1,130 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "slice_layer.hpp" + +namespace cv +{ +namespace dnn +{ + +SliceLayer::SliceLayer(LayerParams ¶ms) : Layer(params) +{ + inAxis = params.get("axis", 1); + + if (!params.has("slice_point")) + return; + + const DictValue &_slicePoints = params.get("slice_point"); + slicePoints.resize(_slicePoints.size()); + for (int i = 0; i < _slicePoints.size(); i++) + { + slicePoints[i] = _slicePoints.get(i); + CV_Assert(slicePoints[i] > 0 && (i == 0 || slicePoints[i-1] < slicePoints[i])); + } +} + +void SliceLayer::allocate(const std::vector &inputs, std::vector &outputs) +{ + CV_Assert(inputs.size() == 1); + + const Blob inpBlob = *inputs[0]; + int axis = inpBlob.canonicalAxis(inAxis); + int axisSize = inpBlob.size(axis); + BlobShape inpShape = inpBlob.shape(); + + if (slicePoints.size()) //divide blob with respect to passed parameters + { + std::vector outAxisSize; + int prevSlice = 0; + + for (size_t i = 0; i < slicePoints.size(); i++) + { + CV_Assert(prevSlice < slicePoints[i] && slicePoints[i] < axisSize); + outAxisSize.push_back(slicePoints[i] - prevSlice); + prevSlice = slicePoints[i]; + } + outAxisSize.push_back(axisSize - prevSlice); + + outputs.resize(outAxisSize.size()); + for (size_t i = 0; i < outAxisSize.size(); i++) + { + inpShape[axis] = outAxisSize[i]; + outputs[i].create(inpShape, inpBlob.type()); + } + } + else //divide blob with respect to count of output blobs + { + CV_Assert(outputs.size() > 0 && axisSize % outputs.size() == 0); + int outAxisSize = axisSize / (int)outputs.size(); + + for (size_t i = 0; i < outputs.size(); i++) + { + inpShape[axis] = outAxisSize; + outputs[i].create(inpShape, inpBlob.type()); + } + } +} + +void SliceLayer::forward(std::vector &inputs, std::vector &outputs) +{ + Blob &inpBlob = *inputs[0]; + const int axis = inpBlob.canonicalAxis(inAxis); + const Mat& inpMat = inpBlob.matRef(); + + std::vector ranges(inpBlob.dims(), Range::all()); + int sizeStart = 0; + for (size_t i = 0; i < outputs.size(); i++) + { + int sizeEnd = sizeStart + outputs[i].size(axis); + ranges[axis] = Range(sizeStart, sizeEnd); + + Mat inpSubMat = inpMat(&ranges[0]); + inpSubMat.copyTo(outputs[i].matRef()); + + sizeStart = sizeEnd; + } +} + +} +} diff --git a/modules/dnn/src/layers/slice_layer.hpp b/modules/dnn/src/layers/slice_layer.hpp new file mode 100644 index 000000000..9f1584049 --- /dev/null +++ b/modules/dnn/src/layers/slice_layer.hpp @@ -0,0 +1,67 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_SLICE_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_SLICE_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + +class SliceLayer : public Layer +{ +public: + SliceLayer(LayerParams ¶ms); + + void allocate(const std::vector &inputs, std::vector &outputs); + + void forward(std::vector &inputs, std::vector &outputs); + +private: + int inAxis; + std::vector slicePoints; +}; + +} +} +#endif diff --git a/modules/dnn/src/layers/softmax_layer.cpp b/modules/dnn/src/layers/softmax_layer.cpp new file mode 100644 index 000000000..e90a590ec --- /dev/null +++ b/modules/dnn/src/layers/softmax_layer.cpp @@ -0,0 +1,144 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "softmax_layer.hpp" +#include +#include +using std::max; + +namespace cv +{ +namespace dnn +{ + //TODO: set default axis number to 1, and add custom shape length in FullyConnected + SoftMaxLayer::SoftMaxLayer(LayerParams ¶ms) : Layer(params) + { + //hotfix!!! + axis_ = params.get("axis", 1); + } + + void SoftMaxLayer::allocate(const std::vector &inputs, std::vector &outputs) + { + CV_Assert(inputs.size() == 1); + axis = inputs[0]->canonicalAxis(axis_); + + BlobShape shape = inputs[0]->shape(); + outputs.resize(1); + outputs[0].create(shape); + + shape[axis] = 1; + maxAggregator.create(shape); + } + + void SoftMaxLayer::forward(std::vector &inputs, std::vector &outputs) + { + Blob &src = *inputs[0]; + Blob &dst = outputs[0]; + + float *srcPtr = src.ptrf(); + float *dstPtr = dst.ptrf(); + float *bufPtr = maxAggregator.ptrf(); + + size_t outerSize = src.total(0, axis); + size_t channels = src.size(axis); + size_t innerSize = src.total(axis + 1); + + size_t outerStep = src.total(axis); + size_t cnStep = src.total(axis + 1); + + //compute max along axis + for (size_t outerDim = 0; outerDim < outerSize; outerDim++) + { + size_t srcOffset = outerDim * outerStep; + size_t bufOffset = outerDim * cnStep; + + memcpy(bufPtr + bufOffset, srcPtr + srcOffset, innerSize * sizeof(float)); + + for (size_t cnDim = 1; cnDim < channels; cnDim++) + { + for (size_t i = 0; i < innerSize; i++) + bufPtr[bufOffset + i] = std::max(bufPtr[bufOffset + i], srcPtr[srcOffset + cnDim * cnStep + i]); + } + } + + //subtract max + for (size_t outerDim = 0; outerDim < outerSize; outerDim++) + { + size_t srcOffset = outerDim * outerStep; + size_t bufOffset = outerDim * cnStep; + + for (size_t cnDim = 0; cnDim < channels; cnDim++) + { + for (size_t i = 0; i < innerSize; i++) + dstPtr[srcOffset + cnDim * cnStep + i] = srcPtr[srcOffset + cnDim * cnStep + i] - bufPtr[bufOffset + i]; + } + } + + cv::exp(dst.matRef(), dst.matRef()); + + for (size_t outerDim = 0; outerDim < outerSize; outerDim++) + { + size_t srcOffset = outerDim * outerStep; + size_t bufOffset = outerDim * cnStep; + + //sum exp along axis + for (size_t i = 0; i < innerSize; i++) + bufPtr[bufOffset + i] = 0.f; + + for (size_t cnDim = 0; cnDim < channels; cnDim++) + { + for (size_t i = 0; i < innerSize; i++) + bufPtr[bufOffset + i] += dstPtr[srcOffset + cnDim * cnStep + i]; + } + + //divide by computed sum + for (size_t cnDim = 0; cnDim < channels; cnDim++) + { + for (size_t i = 0; i < innerSize; i++) + dstPtr[srcOffset + cnDim * cnStep + i] /= bufPtr[bufOffset + i]; + } + } + } + +} +} diff --git a/modules/dnn/src/layers/softmax_layer.hpp b/modules/dnn/src/layers/softmax_layer.hpp new file mode 100644 index 000000000..5b55794ae --- /dev/null +++ b/modules/dnn/src/layers/softmax_layer.hpp @@ -0,0 +1,62 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_SOFTMAX_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_SOFTMAX_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + class SoftMaxLayer : public Layer + { + int axis_, axis; + Blob maxAggregator; + + public: + SoftMaxLayer(LayerParams ¶ms); + void allocate(const std::vector &inputs, std::vector &outputs); + void forward(std::vector &inputs, std::vector &outputs); + }; +} +} +#endif diff --git a/modules/dnn/src/layers/split_layer.cpp b/modules/dnn/src/layers/split_layer.cpp new file mode 100644 index 000000000..b29c427bb --- /dev/null +++ b/modules/dnn/src/layers/split_layer.cpp @@ -0,0 +1,83 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include "layers_common.hpp" +#include "split_layer.hpp" + +namespace cv +{ +namespace dnn +{ + +//TODO: maybe "top_count" param is useless because it can be determined by output connections number? +SplitLayer::SplitLayer(LayerParams ¶ms) : Layer(params) +{ + if (params.has("top_count")) + { + outputsNum = params.get("top_count"); + CV_Assert(outputsNum >= 0); + } + else + { + outputsNum = -1; + } +} + +void SplitLayer::allocate(const std::vector &inputs, std::vector &outputs) +{ + CV_Assert(inputs.size() == 1); + + if (outputsNum >= 0) + outputs.resize(outputsNum); + + for (size_t i = 0; i < outputs.size(); i++) + outputs[i].create(inputs[0]->shape(), inputs[0]->type()); +} + +void SplitLayer::forward(std::vector &inputs, std::vector &outputs) +{ + for (size_t i = 0; i < outputs.size(); i++) + inputs[0]->matRefConst().copyTo(outputs[i].matRef()); +} + +} +} diff --git a/modules/dnn/src/layers/split_layer.hpp b/modules/dnn/src/layers/split_layer.hpp new file mode 100644 index 000000000..1793dbf59 --- /dev/null +++ b/modules/dnn/src/layers/split_layer.hpp @@ -0,0 +1,66 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_LAYERS_SPLIT_LAYER_HPP__ +#define __OPENCV_DNN_LAYERS_SPLIT_LAYER_HPP__ +#include "../precomp.hpp" + +namespace cv +{ +namespace dnn +{ + +class SplitLayer : public Layer +{ +public: + SplitLayer(LayerParams ¶ms); + + void allocate(const std::vector &inputs, std::vector &outputs); + + void forward(std::vector &inputs, std::vector &outputs); + +private: + int outputsNum; +}; + +} +} +#endif diff --git a/modules/dnn/src/opencl/im2col.cl b/modules/dnn/src/opencl/im2col.cl new file mode 100644 index 000000000..7900645ea --- /dev/null +++ b/modules/dnn/src/opencl/im2col.cl @@ -0,0 +1,71 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +__kernel void im2col(__global const float *im_src, int im_src_offset, + int channels, int height_inp, int width_inp, + int kernel_h, int kernel_w, int pad_h, int pad_w, int stride_h, int stride_w, + int height_out, int width_out, + __global float *im_col, int im_col_offset + ) +{ + int index = get_global_id(0); + if (index >= height_out * width_out * channels) + return; + int j_out = index % width_out; + int i_out = (index / width_out) % height_out; + int c_inp = (index / width_out) / height_out; + + int c_out = c_inp * kernel_h * kernel_w; + int i_inp = i_out * stride_h - pad_h; + int j_inp = j_out * stride_w - pad_w; + + im_src += (c_inp * height_inp + i_inp) * width_inp + j_inp + im_src_offset / sizeof(float); + im_col += (c_out * height_out + i_out) * width_out + j_out + im_col_offset / sizeof(float); + + for (int ki = 0; ki < kernel_h; ++ki) + for (int kj = 0; kj < kernel_w; ++kj) { + int i = i_inp + ki; + int j = j_inp + kj; + *im_col = (i >= 0 && j >= 0 && i < height_inp && j < width_inp) ? + im_src[ki * width_inp + kj] : 0; + im_col += height_out * width_out; + } +} diff --git a/modules/dnn/src/precomp.hpp b/modules/dnn/src/precomp.hpp new file mode 100644 index 000000000..8639e45f8 --- /dev/null +++ b/modules/dnn/src/precomp.hpp @@ -0,0 +1,43 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include +#include diff --git a/modules/dnn/src/torch/COPYRIGHT.txt b/modules/dnn/src/torch/COPYRIGHT.txt new file mode 100644 index 000000000..bc002b78a --- /dev/null +++ b/modules/dnn/src/torch/COPYRIGHT.txt @@ -0,0 +1,36 @@ +Copyright (c) 2011-2014 Idiap Research Institute (Ronan Collobert) +Copyright (c) 2012-2014 Deepmind Technologies (Koray Kavukcuoglu) +Copyright (c) 2011-2012 NEC Laboratories America (Koray Kavukcuoglu) +Copyright (c) 2011-2013 NYU (Clement Farabet) +Copyright (c) 2006-2010 NEC Laboratories America (Ronan Collobert, Leon Bottou, Iain Melvin, Jason Weston) +Copyright (c) 2006 Idiap Research Institute (Samy Bengio) +Copyright (c) 2001-2004 Idiap Research Institute (Ronan Collobert, Samy Bengio, Johnny Mariethoz) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the names of Deepmind Technologies, NYU, NEC Laboratories America + and IDIAP Research Institute 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. diff --git a/modules/dnn/src/torch/THDiskFile.cpp b/modules/dnn/src/torch/THDiskFile.cpp new file mode 100644 index 000000000..06f8b854d --- /dev/null +++ b/modules/dnn/src/torch/THDiskFile.cpp @@ -0,0 +1,611 @@ +#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER +#include "THGeneral.h" +#include "THDiskFile.h" +#include "THFilePrivate.h" + +extern "C" +{ + +typedef struct THDiskFile__ +{ + THFile file; + + FILE *handle; + char *name; + int isNativeEncoding; + +} THDiskFile; + +static int THDiskFile_isOpened(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)self; + return (dfself->handle != NULL); +} + +const char *THDiskFile_name(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)self; + return dfself->name; +} + +/* workaround mac osx lion ***insane*** fread bug */ +#ifdef __APPLE__ +size_t fread__(void *ptr, size_t size, size_t nitems, FILE *stream) +{ + size_t nread = 0; + while(!feof(stream) && !ferror(stream) && (nread < nitems)) + nread += fread((char*)ptr+nread*size, size, THMin(2147483648/size, nitems-nread), stream); + return nread; +} +#else +#define fread__ fread +#endif + +#define READ_WRITE_METHODS(TYPE, TYPEC, ASCII_READ_ELEM, ASCII_WRITE_ELEM) \ + static long THDiskFile_read##TYPEC(THFile *self, TYPE *data, long n) \ + { \ + THDiskFile *dfself = (THDiskFile*)(self); \ + long nread = 0L; \ + \ + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \ + THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); \ + \ + if(dfself->file.isBinary) \ + { \ + nread = fread__(data, sizeof(TYPE), n, dfself->handle); \ + if(!dfself->isNativeEncoding && (sizeof(TYPE) > 1) && (nread > 0)) \ + THDiskFile_reverseMemory(data, data, sizeof(TYPE), nread); \ + } \ + else \ + { \ + long i; \ + for(i = 0; i < n; i++) \ + { \ + ASCII_READ_ELEM; /* increment here result and break if wrong */ \ + } \ + if(dfself->file.isAutoSpacing && (n > 0)) \ + { \ + int c = fgetc(dfself->handle); \ + if( (c != '\n') && (c != EOF) ) \ + ungetc(c, dfself->handle); \ + } \ + } \ + \ + if(nread != n) \ + { \ + dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */ \ + if(!dfself->file.isQuiet) \ + THError("read error: read %d blocks instead of %d", nread, n); \ + } \ + \ + return nread; \ + } \ + \ + static long THDiskFile_write##TYPEC(THFile *self, TYPE *data, long n) \ + { \ + THDiskFile *dfself = (THDiskFile*)(self); \ + long nwrite = 0L; \ + \ + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \ + THArgCheck(dfself->file.isWritable, 1, "attempt to write in a read-only file"); \ + \ + if(dfself->file.isBinary) \ + { \ + if(dfself->isNativeEncoding) \ + { \ + nwrite = fwrite(data, sizeof(TYPE), n, dfself->handle); \ + } \ + else \ + { \ + if(sizeof(TYPE) > 1) \ + { \ + char *buffer = (char*)THAlloc(sizeof(TYPE)*n); \ + THDiskFile_reverseMemory(buffer, data, sizeof(TYPE), n); \ + nwrite = fwrite(buffer, sizeof(TYPE), n, dfself->handle); \ + THFree(buffer); \ + } \ + else \ + nwrite = fwrite(data, sizeof(TYPE), n, dfself->handle); \ + } \ + } \ + else \ + { \ + long i; \ + for(i = 0; i < n; i++) \ + { \ + ASCII_WRITE_ELEM; \ + if( dfself->file.isAutoSpacing && (i < n-1) ) \ + fprintf(dfself->handle, " "); \ + } \ + if(dfself->file.isAutoSpacing && (n > 0)) \ + fprintf(dfself->handle, "\n"); \ + } \ + \ + if(nwrite != n) \ + { \ + dfself->file.hasError = 1; \ + if(!dfself->file.isQuiet) \ + THError("write error: wrote %d blocks instead of %d", nwrite, n); \ + } \ + \ + return nwrite; \ +} + +static int THDiskFile_mode(const char *mode, int *isReadable, int *isWritable) +{ + *isReadable = 0; + *isWritable = 0; + if(strlen(mode) == 1) + { + if(*mode == 'r') + { + *isReadable = 1; + return 1; + } + else if(*mode == 'w') + { + *isWritable = 1; + return 1; + } + } + else if(strlen(mode) == 2) + { + if(mode[0] == 'r' && mode[1] == 'w') + { + *isReadable = 1; + *isWritable = 1; + return 1; + } + } + return 0; +} + +static void THDiskFile_synchronize(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + fflush(dfself->handle); +} + +static void THDiskFile_seek(THFile *self, long position) +{ + THDiskFile *dfself = (THDiskFile*)(self); + + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + THArgCheck(position >= 0, 2, "position must be positive"); + + if(fseek(dfself->handle, position, SEEK_SET) < 0) + { + dfself->file.hasError = 1; + if(!dfself->file.isQuiet) + THError("unable to seek at position %d", position); + } +} + +static void THDiskFile_seekEnd(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + + if(fseek(dfself->handle, 0L, SEEK_END) < 0) + { + dfself->file.hasError = 1; + if(!dfself->file.isQuiet) + THError("unable to seek at end of file"); + } +} + +static long THDiskFile_position(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + return ftell(dfself->handle); +} + +static void THDiskFile_close(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + fclose(dfself->handle); + dfself->handle = NULL; +} + +/* Little and Big Endian */ + +static void THDiskFile_reverseMemory(void *dst, const void *src, long blockSize, long numBlocks) +{ + if(blockSize != 1) + { + long halfBlockSize = blockSize/2; + char *charSrc = (char*)src; + char *charDst = (char*)dst; + long b, i; + for(b = 0; b < numBlocks; b++) + { + for(i = 0; i < halfBlockSize; i++) + { + char z = charSrc[i]; + charDst[i] = charSrc[blockSize-1-i]; + charDst[blockSize-1-i] = z; + } + charSrc += blockSize; + charDst += blockSize; + } + } +} + +int THDiskFile_isLittleEndianCPU(void) +{ + int x = 7; + char *ptr = (char *)&x; + + if(ptr[0] == 0) + return 0; + else + return 1; +} + +int THDiskFile_isBigEndianCPU(void) +{ + return(!THDiskFile_isLittleEndianCPU()); +} + +void THDiskFile_nativeEndianEncoding(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + dfself->isNativeEncoding = 1; +} + +void THDiskFile_littleEndianEncoding(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + dfself->isNativeEncoding = THDiskFile_isLittleEndianCPU(); +} + +void THDiskFile_bigEndianEncoding(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + dfself->isNativeEncoding = !THDiskFile_isLittleEndianCPU(); +} + +/* End of Little and Big Endian Stuff */ + +static void THDiskFile_free(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + if(dfself->handle) + fclose(dfself->handle); + THFree(dfself->name); + THFree(dfself); +} + +/* READ_WRITE_METHODS(int, Bool, */ +/* int value = 0; int ret = fscanf(file->handle, "%d", &value); array[i] = (value ? 1 : 0); if(ret <= 0) break; else result++, */ +/* int value = (array[i] ? 1 : 0); nElemWritten = fprintf(file->handle, "%d", value), */ +/* true) */ + +/* Note that we do a trick */ +READ_WRITE_METHODS(unsigned char, Byte, + nread = fread(data, 1, n, dfself->handle); break, + nwrite = fwrite(data, 1, n, dfself->handle); break) + +READ_WRITE_METHODS(char, Char, + nread = fread(data, 1, n, dfself->handle); break, + nwrite = fwrite(data, 1, n, dfself->handle); break) + +READ_WRITE_METHODS(short, Short, + int ret = fscanf(dfself->handle, "%hd", &data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%hd", data[i]); if(ret <= 0) break; else nwrite++) + +READ_WRITE_METHODS(int, Int, + int ret = fscanf(dfself->handle, "%d", &data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%d", data[i]); if(ret <= 0) break; else nwrite++) + +READ_WRITE_METHODS(long, Long, + int ret = fscanf(dfself->handle, "%ld", &data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%ld", data[i]); if(ret <= 0) break; else nwrite++) + +READ_WRITE_METHODS(float, Float, + int ret = fscanf(dfself->handle, "%g", &data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%.9g", data[i]); if(ret <= 0) break; else nwrite++) + +READ_WRITE_METHODS(double, Double, + int ret = fscanf(dfself->handle, "%lg", &data[i]); if(ret <= 0) break; else nread++, + int ret = fprintf(dfself->handle, "%.17g", data[i]); if(ret <= 0) break; else nwrite++) + +static long THDiskFile_readString(THFile *self, const char *format, char **str_) +{ + THDiskFile *dfself = (THDiskFile*)(self); + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); + THArgCheck((strlen(format) >= 2 ? (format[0] == '*') && (format[1] == 'a' || format[1] == 'l') : 0), 2, "format must be '*a' or '*l'"); + +/* note: the string won't survive long, as it is copied into lua */ +/* so 1024 is not that big... */ +#define TBRS_BSZ 1024L + + if(format[1] == 'a') + { + char *p = (char*)THAlloc(TBRS_BSZ); + long total = TBRS_BSZ; + long pos = 0L; + + for (;;) + { + if(total-pos == 0) /* we need more space! */ + { + total += TBRS_BSZ; + p = (char*)THRealloc(p, total); + } + pos += fread(p+pos, 1, total-pos, dfself->handle); + if (pos < total) /* eof? */ + { + if(pos == 0L) + { + THFree(p); + dfself->file.hasError = 1; + if(!dfself->file.isQuiet) + THError("read error: read 0 blocks instead of 1"); + + *str_ = NULL; + return 0; + } + *str_ = p; + return pos; + } + } + } + else + { + char *p = (char*)THAlloc(TBRS_BSZ); + long total = TBRS_BSZ; + long pos = 0L; + long size; + + for (;;) + { + if(total-pos <= 1) /* we can only write '\0' in there! */ + { + total += TBRS_BSZ; + p = (char*)THRealloc(p, total); + } + if (fgets(p+pos, total-pos, dfself->handle) == NULL) /* eof? */ + { + if(pos == 0L) + { + THFree(p); + dfself->file.hasError = 1; + if(!dfself->file.isQuiet) + THError("read error: read 0 blocks instead of 1"); + + *str_ = NULL; + return 0; + } + *str_ = p; + return pos; + } + size = strlen(p+pos); + if (size == 0L || (p+pos)[size-1] != '\n') + { + pos += size; + } + else + { + pos += size-1L; /* do not include `eol' */ + *str_ = p; + return pos; + } + } + } + + *str_ = NULL; + return 0; +} + + +static long THDiskFile_writeString(THFile *self, const char *str, long size) +{ + THDiskFile *dfself = (THDiskFile*)(self); + long nwrite; + + THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); + THArgCheck(dfself->file.isWritable, 1, "attempt to write in a read-only file"); + + nwrite = fwrite(str, 1, size, dfself->handle); + if(nwrite != size) + { + dfself->file.hasError = 1; + if(!dfself->file.isQuiet) + THError("write error: wrote %ld blocks instead of %ld", nwrite, size); + } + + return nwrite; +} + +THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet) +{ + static struct THFileVTable vtable = { + THDiskFile_isOpened, + + THDiskFile_readByte, + THDiskFile_readChar, + THDiskFile_readShort, + THDiskFile_readInt, + THDiskFile_readLong, + THDiskFile_readFloat, + THDiskFile_readDouble, + THDiskFile_readString, + + THDiskFile_writeByte, + THDiskFile_writeChar, + THDiskFile_writeShort, + THDiskFile_writeInt, + THDiskFile_writeLong, + THDiskFile_writeFloat, + THDiskFile_writeDouble, + THDiskFile_writeString, + + THDiskFile_synchronize, + THDiskFile_seek, + THDiskFile_seekEnd, + THDiskFile_position, + THDiskFile_close, + THDiskFile_free + }; + + int isReadable; + int isWritable; + FILE *handle; + THDiskFile *self; + + THArgCheck(THDiskFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w' or 'rw'"); + + if( isReadable && isWritable ) + { + handle = fopen(name, "r+b"); + if(!handle) + { + handle = fopen(name, "wb"); + if(handle) + { + fclose(handle); + handle = fopen(name, "r+b"); + } + } + } + else + handle = fopen(name, (isReadable ? "rb" : "wb")); + + if(!handle) + { + if(isQuiet) + return 0; + else + THError("cannot open <%s> in mode %c%c", name, (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' ')); + } + + self = (THDiskFile*)THAlloc(sizeof(THDiskFile)); + + self->handle = handle; + self->name = (char*)THAlloc(strlen(name)+1); + strcpy(self->name, name); + self->isNativeEncoding = 1; + + self->file.vtable = &vtable; + self->file.isQuiet = isQuiet; + self->file.isReadable = isReadable; + self->file.isWritable = isWritable; + self->file.isBinary = 0; + self->file.isAutoSpacing = 1; + self->file.hasError = 0; + + return (THFile*)self; +} + +/* PipeFile */ + +static int THPipeFile_mode(const char *mode, int *isReadable, int *isWritable) +{ + *isReadable = 0; + *isWritable = 0; + if(strlen(mode) == 1) + { + if(*mode == 'r') + { + *isReadable = 1; + return 1; + } + else if(*mode == 'w') + { + *isWritable = 1; + return 1; + } + } + return 0; +} + +static void THPipeFile_free(THFile *self) +{ + THDiskFile *dfself = (THDiskFile*)(self); + if(dfself->handle) + pclose(dfself->handle); + THFree(dfself->name); + THFree(dfself); +} + +THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet) +{ + static struct THFileVTable vtable = { + THDiskFile_isOpened, + + THDiskFile_readByte, + THDiskFile_readChar, + THDiskFile_readShort, + THDiskFile_readInt, + THDiskFile_readLong, + THDiskFile_readFloat, + THDiskFile_readDouble, + THDiskFile_readString, + + THDiskFile_writeByte, + THDiskFile_writeChar, + THDiskFile_writeShort, + THDiskFile_writeInt, + THDiskFile_writeLong, + THDiskFile_writeFloat, + THDiskFile_writeDouble, + THDiskFile_writeString, + + THDiskFile_synchronize, + THDiskFile_seek, + THDiskFile_seekEnd, + THDiskFile_position, + THDiskFile_close, + THPipeFile_free + }; + + int isReadable; + int isWritable; + FILE *handle; + THDiskFile *self; + + THArgCheck(THPipeFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w'"); + +#ifdef _WIN32 + handle = popen(name, (isReadable ? "rb" : "wb")); +#else + handle = popen(name, (isReadable ? "r" : "w")); +#endif + + if(!handle) + { + if(isQuiet) + return 0; + else + THError("cannot open <%s> in mode %c%c", name, (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' ')); + } + + self = (THDiskFile*)THAlloc(sizeof(THDiskFile)); + + self->handle = handle; + self->name = (char*)THAlloc(strlen(name)+1); + strcpy(self->name, name); + self->isNativeEncoding = 1; + + self->file.vtable = &vtable; + self->file.isQuiet = isQuiet; + self->file.isReadable = isReadable; + self->file.isWritable = isWritable; + self->file.isBinary = 0; + self->file.isAutoSpacing = 1; + self->file.hasError = 0; + + return (THFile*)self; +} + +} +#endif diff --git a/modules/dnn/src/torch/THDiskFile.h b/modules/dnn/src/torch/THDiskFile.h new file mode 100644 index 000000000..f7c93c220 --- /dev/null +++ b/modules/dnn/src/torch/THDiskFile.h @@ -0,0 +1,17 @@ +#ifndef TH_DISK_FILE_INC +#define TH_DISK_FILE_INC + +#include "THFile.h" + +TH_API THFile *THDiskFile_new(const char *name, const char *mode, int isQuiet); +TH_API THFile *THPipeFile_new(const char *name, const char *mode, int isQuiet); + +TH_API const char *THDiskFile_name(THFile *self); + +TH_API int THDiskFile_isLittleEndianCPU(void); +TH_API int THDiskFile_isBigEndianCPU(void); +TH_API void THDiskFile_nativeEndianEncoding(THFile *self); +TH_API void THDiskFile_littleEndianEncoding(THFile *self); +TH_API void THDiskFile_bigEndianEncoding(THFile *self); + +#endif diff --git a/modules/dnn/src/torch/THFile.cpp b/modules/dnn/src/torch/THFile.cpp new file mode 100644 index 000000000..148f17915 --- /dev/null +++ b/modules/dnn/src/torch/THFile.cpp @@ -0,0 +1,163 @@ +#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER +#include "THFile.h" +#include "THFilePrivate.h" + +extern "C" +{ + +#define IMPLEMENT_THFILE_RW(TYPEC, TYPE) \ + long THFile_read##TYPEC##Raw(THFile *self, TYPE *data, long n) \ + { \ + return (*self->vtable->read##TYPEC)(self, data, n); \ + } \ + \ + long THFile_write##TYPEC##Raw(THFile *self, TYPE *data, long n) \ + { \ + return (*self->vtable->write##TYPEC)(self, data, n); \ + } + +IMPLEMENT_THFILE_RW(Byte, unsigned char) +IMPLEMENT_THFILE_RW(Char, char) +IMPLEMENT_THFILE_RW(Short, short) +IMPLEMENT_THFILE_RW(Int, int) +IMPLEMENT_THFILE_RW(Long, long) +IMPLEMENT_THFILE_RW(Float, float) +IMPLEMENT_THFILE_RW(Double, double) + +long THFile_readStringRaw(THFile *self, const char *format, char **str_) +{ + return self->vtable->readString(self, format, str_); +} + +long THFile_writeStringRaw(THFile *self, const char *str, long size) +{ + return self->vtable->writeString(self, str, size); +} + +void THFile_synchronize(THFile *self) +{ + self->vtable->synchronize(self); +} + +void THFile_seek(THFile *self, long position) +{ + self->vtable->seek(self, position); +} + +void THFile_seekEnd(THFile *self) +{ + self->vtable->seekEnd(self); +} + +long THFile_position(THFile *self) +{ + return self->vtable->position(self); +} + +void THFile_close(THFile *self) +{ + self->vtable->close(self); +} + +void THFile_free(THFile *self) +{ + self->vtable->free(self); +} + +int THFile_isOpened(THFile *self) +{ + return self->vtable->isOpened(self); +} + +#define IMPLEMENT_THFILE_FLAGS(FLAG) \ + int THFile_##FLAG(THFile *self) \ + { \ + return self->FLAG; \ + } + +IMPLEMENT_THFILE_FLAGS(isQuiet) +IMPLEMENT_THFILE_FLAGS(isReadable) +IMPLEMENT_THFILE_FLAGS(isWritable) +IMPLEMENT_THFILE_FLAGS(isBinary) +IMPLEMENT_THFILE_FLAGS(isAutoSpacing) +IMPLEMENT_THFILE_FLAGS(hasError) + +void THFile_binary(THFile *self) +{ + self->isBinary = 1; +} + +void THFile_ascii(THFile *self) +{ + self->isBinary = 0; +} + +void THFile_autoSpacing(THFile *self) +{ + self->isAutoSpacing = 1; +} + +void THFile_noAutoSpacing(THFile *self) +{ + self->isAutoSpacing = 0; +} + +void THFile_quiet(THFile *self) +{ + self->isQuiet = 1; +} + +void THFile_pedantic(THFile *self) +{ + self->isQuiet = 0; +} + +void THFile_clearError(THFile *self) +{ + self->hasError = 0; +} + +#define IMPLEMENT_THFILE_SCALAR(TYPEC, TYPE) \ + TYPE THFile_read##TYPEC##Scalar(THFile *self) \ + { \ + TYPE scalar; \ + THFile_read##TYPEC##Raw(self, &scalar, 1); \ + return scalar; \ + } \ + \ + void THFile_write##TYPEC##Scalar(THFile *self, TYPE scalar) \ + { \ + THFile_write##TYPEC##Raw(self, &scalar, 1); \ + } + +IMPLEMENT_THFILE_SCALAR(Byte, unsigned char) +IMPLEMENT_THFILE_SCALAR(Char, char) +IMPLEMENT_THFILE_SCALAR(Short, short) +IMPLEMENT_THFILE_SCALAR(Int, int) +IMPLEMENT_THFILE_SCALAR(Long, long) +IMPLEMENT_THFILE_SCALAR(Float, float) +IMPLEMENT_THFILE_SCALAR(Double, double) + +/* +#define IMPLEMENT_THFILE_STORAGE(TYPEC, TYPE) \ + long THFile_read##TYPEC(THFile *self, TH##TYPEC##Storage *storage) \ + { \ + return THFile_read##TYPEC##Raw(self, storage->data, storage->size); \ + } \ + \ + long THFile_write##TYPEC(THFile *self, TH##TYPEC##Storage *storage) \ + { \ + return THFile_write##TYPEC##Raw(self, storage->data, storage->size); \ + } + +IMPLEMENT_THFILE_STORAGE(Byte, unsigned char) +IMPLEMENT_THFILE_STORAGE(Char, char) +IMPLEMENT_THFILE_STORAGE(Short, short) +IMPLEMENT_THFILE_STORAGE(Int, int) +IMPLEMENT_THFILE_STORAGE(Long, long) +IMPLEMENT_THFILE_STORAGE(Float, float) +IMPLEMENT_THFILE_STORAGE(Double, double) +*/ + +} +#endif diff --git a/modules/dnn/src/torch/THFile.h b/modules/dnn/src/torch/THFile.h new file mode 100644 index 000000000..3fac5cc1a --- /dev/null +++ b/modules/dnn/src/torch/THFile.h @@ -0,0 +1,87 @@ +#ifndef TH_FILE_INC +#define TH_FILE_INC + +//#include "THStorage.h" +#include "THGeneral.h" + +typedef struct THFile__ THFile; + +TH_API int THFile_isOpened(THFile *self); +TH_API int THFile_isQuiet(THFile *self); +TH_API int THFile_isReadable(THFile *self); +TH_API int THFile_isWritable(THFile *self); +TH_API int THFile_isBinary(THFile *self); +TH_API int THFile_isAutoSpacing(THFile *self); +TH_API int THFile_hasError(THFile *self); + +TH_API void THFile_binary(THFile *self); +TH_API void THFile_ascii(THFile *self); +TH_API void THFile_autoSpacing(THFile *self); +TH_API void THFile_noAutoSpacing(THFile *self); +TH_API void THFile_quiet(THFile *self); +TH_API void THFile_pedantic(THFile *self); +TH_API void THFile_clearError(THFile *self); + +/* scalar */ +TH_API unsigned char THFile_readByteScalar(THFile *self); +TH_API char THFile_readCharScalar(THFile *self); +TH_API short THFile_readShortScalar(THFile *self); +TH_API int THFile_readIntScalar(THFile *self); +TH_API long THFile_readLongScalar(THFile *self); +TH_API float THFile_readFloatScalar(THFile *self); +TH_API double THFile_readDoubleScalar(THFile *self); + +TH_API void THFile_writeByteScalar(THFile *self, unsigned char scalar); +TH_API void THFile_writeCharScalar(THFile *self, char scalar); +TH_API void THFile_writeShortScalar(THFile *self, short scalar); +TH_API void THFile_writeIntScalar(THFile *self, int scalar); +TH_API void THFile_writeLongScalar(THFile *self, long scalar); +TH_API void THFile_writeFloatScalar(THFile *self, float scalar); +TH_API void THFile_writeDoubleScalar(THFile *self, double scalar); + +/* storage */ +/* +TH_API long THFile_readByte(THFile *self, THByteStorage *storage); +TH_API long THFile_readChar(THFile *self, THCharStorage *storage); +TH_API long THFile_readShort(THFile *self, THShortStorage *storage); +TH_API long THFile_readInt(THFile *self, THIntStorage *storage); +TH_API long THFile_readLong(THFile *self, THLongStorage *storage); +TH_API long THFile_readFloat(THFile *self, THFloatStorage *storage); +TH_API long THFile_readDouble(THFile *self, THDoubleStorage *storage); + +TH_API long THFile_writeByte(THFile *self, THByteStorage *storage); +TH_API long THFile_writeChar(THFile *self, THCharStorage *storage); +TH_API long THFile_writeShort(THFile *self, THShortStorage *storage); +TH_API long THFile_writeInt(THFile *self, THIntStorage *storage); +TH_API long THFile_writeLong(THFile *self, THLongStorage *storage); +TH_API long THFile_writeFloat(THFile *self, THFloatStorage *storage); +TH_API long THFile_writeDouble(THFile *self, THDoubleStorage *storage); +*/ + +/* raw */ +TH_API long THFile_readByteRaw(THFile *self, unsigned char *data, long n); +TH_API long THFile_readCharRaw(THFile *self, char *data, long n); +TH_API long THFile_readShortRaw(THFile *self, short *data, long n); +TH_API long THFile_readIntRaw(THFile *self, int *data, long n); +TH_API long THFile_readLongRaw(THFile *self, long *data, long n); +TH_API long THFile_readFloatRaw(THFile *self, float *data, long n); +TH_API long THFile_readDoubleRaw(THFile *self, double *data, long n); +TH_API long THFile_readStringRaw(THFile *self, const char *format, char **str_); /* you must deallocate str_ */ + +TH_API long THFile_writeByteRaw(THFile *self, unsigned char *data, long n); +TH_API long THFile_writeCharRaw(THFile *self, char *data, long n); +TH_API long THFile_writeShortRaw(THFile *self, short *data, long n); +TH_API long THFile_writeIntRaw(THFile *self, int *data, long n); +TH_API long THFile_writeLongRaw(THFile *self, long *data, long n); +TH_API long THFile_writeFloatRaw(THFile *self, float *data, long n); +TH_API long THFile_writeDoubleRaw(THFile *self, double *data, long n); +TH_API long THFile_writeStringRaw(THFile *self, const char *str, long size); + +TH_API void THFile_synchronize(THFile *self); +TH_API void THFile_seek(THFile *self, long position); +TH_API void THFile_seekEnd(THFile *self); +TH_API long THFile_position(THFile *self); +TH_API void THFile_close(THFile *self); +TH_API void THFile_free(THFile *self); + +#endif diff --git a/modules/dnn/src/torch/THFilePrivate.h b/modules/dnn/src/torch/THFilePrivate.h new file mode 100644 index 000000000..9097fb979 --- /dev/null +++ b/modules/dnn/src/torch/THFilePrivate.h @@ -0,0 +1,43 @@ +struct THFile__ +{ + struct THFileVTable *vtable; + + int isQuiet; + int isReadable; + int isWritable; + int isBinary; + int isAutoSpacing; + int hasError; +}; + +/* virtual table definition */ + +struct THFileVTable +{ + int (*isOpened)(THFile *self); + + long (*readByte)(THFile *self, unsigned char *data, long n); + long (*readChar)(THFile *self, char *data, long n); + long (*readShort)(THFile *self, short *data, long n); + long (*readInt)(THFile *self, int *data, long n); + long (*readLong)(THFile *self, long *data, long n); + long (*readFloat)(THFile *self, float *data, long n); + long (*readDouble)(THFile *self, double *data, long n); + long (*readString)(THFile *self, const char *format, char **str_); + + long (*writeByte)(THFile *self, unsigned char *data, long n); + long (*writeChar)(THFile *self, char *data, long n); + long (*writeShort)(THFile *self, short *data, long n); + long (*writeInt)(THFile *self, int *data, long n); + long (*writeLong)(THFile *self, long *data, long n); + long (*writeFloat)(THFile *self, float *data, long n); + long (*writeDouble)(THFile *self, double *data, long n); + long (*writeString)(THFile *self, const char *str, long size); + + void (*synchronize)(THFile *self); + void (*seek)(THFile *self, long position); + void (*seekEnd)(THFile *self); + long (*position)(THFile *self); + void (*close)(THFile *self); + void (*free)(THFile *self); +}; diff --git a/modules/dnn/src/torch/THGeneral.cpp b/modules/dnn/src/torch/THGeneral.cpp new file mode 100644 index 000000000..dc56e3625 --- /dev/null +++ b/modules/dnn/src/torch/THGeneral.cpp @@ -0,0 +1,255 @@ +#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER +#include "THGeneral.h" +#include + +extern "C" +{ + +#ifndef TH_HAVE_THREAD +#define __thread +#endif + +#if defined(TH_DISABLE_HEAP_TRACKING) +#elif (defined(__unix) || defined(_WIN32)) +#include +#elif defined(__APPLE__) +#include +#endif + +/* Torch Error Handling */ +static void defaultTorchErrorHandlerFunction(const char *msg, void*) +{ + CV_Error(cv::Error::StsError, cv::String("Torch Error: ") + msg); +} + +static __thread void (*torchErrorHandlerFunction)(const char *msg, void *data) = defaultTorchErrorHandlerFunction; +static __thread void *torchErrorHandlerData; + +void _THError(const char *file, const int line, const char *fmt, ...) +{ + char msg[2048]; + va_list args; + + /* vasprintf not standard */ + /* vsnprintf: how to handle if does not exists? */ + va_start(args, fmt); + int n = vsnprintf(msg, 2048, fmt, args); + va_end(args); + + if(n < 2048) { + snprintf(msg + n, 2048 - n, " at %s:%d", file, line); + } + + (*torchErrorHandlerFunction)(msg, torchErrorHandlerData); +} + +void _THAssertionFailed(const char *file, const int line, const char *exp, const char *fmt, ...) { + char msg[1024]; + va_list args; + va_start(args, fmt); + vsnprintf(msg, 1024, fmt, args); + va_end(args); + _THError(file, line, "Assertion `%s' failed. %s", exp, msg); +} + +void THSetErrorHandler( void (*torchErrorHandlerFunction_)(const char *msg, void *data), void *data ) +{ + if(torchErrorHandlerFunction_) + torchErrorHandlerFunction = torchErrorHandlerFunction_; + else + torchErrorHandlerFunction = defaultTorchErrorHandlerFunction; + torchErrorHandlerData = data; +} + +/* Torch Arg Checking Handling */ +static void defaultTorchArgErrorHandlerFunction(int argNumber, const char *msg, void*) +{ + if(msg) + CV_Error(cv::Error::StsError, cv::format("Torch invalid argument %d: %s", argNumber, msg)); + else + CV_Error(cv::Error::StsError, cv::format("Invalid argument %d", argNumber)); +} + +static __thread void (*torchArgErrorHandlerFunction)(int argNumber, const char *msg, void *data) = defaultTorchArgErrorHandlerFunction; +static __thread void *torchArgErrorHandlerData; + +void _THArgCheck(const char *file, int line, int condition, int argNumber, const char *fmt, ...) +{ + if(!condition) { + char msg[2048]; + va_list args; + + /* vasprintf not standard */ + /* vsnprintf: how to handle if does not exists? */ + va_start(args, fmt); + int n = vsnprintf(msg, 2048, fmt, args); + va_end(args); + + if(n < 2048) { + snprintf(msg + n, 2048 - n, " at %s:%d", file, line); + } + + (*torchArgErrorHandlerFunction)(argNumber, msg, torchArgErrorHandlerData); + } +} + +void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction_)(int argNumber, const char *msg, void *data), void *data ) +{ + if(torchArgErrorHandlerFunction_) + torchArgErrorHandlerFunction = torchArgErrorHandlerFunction_; + else + torchArgErrorHandlerFunction = defaultTorchArgErrorHandlerFunction; + torchArgErrorHandlerData = data; +} + +static __thread void (*torchGCFunction)(void *data) = NULL; +static __thread void *torchGCData; +static __thread long torchHeapSize = 0; +static __thread long torchHeapSizeSoftMax = 300000000; // 300MB, adjusted upward dynamically + +/* Optional hook for integrating with a garbage-collected frontend. + * + * If torch is running with a garbage-collected frontend (e.g. Lua), + * the GC isn't aware of TH-allocated memory so may not know when it + * needs to run. These hooks trigger the GC to run in two cases: + * + * (1) When a memory allocation (malloc, realloc, ...) fails + * (2) When the total TH-allocated memory hits a dynamically-adjusted + * soft maximum. + */ +void THSetGCHandler( void (*torchGCFunction_)(void *data), void *data ) +{ + torchGCFunction = torchGCFunction_; + torchGCData = data; +} + +static long getAllocSize(void *ptr) { +#if defined(TH_DISABLE_HEAP_TRACKING) + return 0; +#elif defined(__unix) + return malloc_usable_size(ptr); +#elif defined(__APPLE__) + return malloc_size(ptr); +#elif defined(_WIN32) + return _msize(ptr); +#else + return 0; +#endif +} + +/* (1) if the torch-allocated heap size exceeds the soft max, run GC + * (2) if post-GC heap size exceeds 80% of the soft max, increase the + * soft max by 40% + */ +static void maybeTriggerGC() { + if(torchGCFunction && torchHeapSize > torchHeapSizeSoftMax) { + torchGCFunction(torchGCData); + if(torchHeapSize > torchHeapSizeSoftMax * 0.8) { + torchHeapSizeSoftMax = torchHeapSizeSoftMax * 1.4; + } + } +} + +// hooks into the TH heap tracking +void THHeapUpdate(long size) { + torchHeapSize += size; + if (size > 0) + maybeTriggerGC(); +} + +static void* THAllocInternal(long size) +{ + void *ptr; + + if (size > 5120) + { +#if (defined(__unix) || defined(__APPLE__)) && (!defined(DISABLE_POSIX_MEMALIGN)) + if (posix_memalign(&ptr, 64, size) != 0) + ptr = NULL; +/* +#elif defined(_WIN32) + ptr = _aligned_malloc(size, 64); +*/ +#else + ptr = malloc(size); +#endif + } + else + { + ptr = malloc(size); + } + + THHeapUpdate(getAllocSize(ptr)); + return ptr; +} + +void* THAlloc(long size) +{ + void *ptr; + + if(size < 0) + THError("$ Torch: invalid memory size -- maybe an overflow?"); + + if(size == 0) + return NULL; + + ptr = THAllocInternal(size); + + if(!ptr && torchGCFunction) { + torchGCFunction(torchGCData); + ptr = THAllocInternal(size); + } + + if(!ptr) + THError("$ Torch: not enough memory: you tried to allocate %dGB. Buy new RAM!", size/1073741824); + + return ptr; +} + +void* THRealloc(void *ptr, long size) +{ + if(!ptr) + return(THAlloc(size)); + + if(size == 0) + { + THFree(ptr); + return NULL; + } + + if(size < 0) + THError("$ Torch: invalid memory size -- maybe an overflow?"); + + THHeapUpdate(-getAllocSize(ptr)); + void *newptr = realloc(ptr, size); + + if(!newptr && torchGCFunction) { + torchGCFunction(torchGCData); + newptr = realloc(ptr, size); + } + THHeapUpdate(getAllocSize(newptr ? newptr : ptr)); + + if(!newptr) + THError("$ Torch: not enough memory: you tried to reallocate %dGB. Buy new RAM!", size/1073741824); + + return newptr; +} + +void THFree(void *ptr) +{ + THHeapUpdate(-getAllocSize(ptr)); + free(ptr); +} + +double THLog1p(const double x) +{ +#if (defined(_MSC_VER) || defined(__MINGW32__)) + volatile double y = 1 + x; + return log(y) - ((y-1)-x)/y ; /* cancels errors with IEEE arithmetic */ +#else + return log1p(x); +#endif +} + +} +#endif diff --git a/modules/dnn/src/torch/THGeneral.h b/modules/dnn/src/torch/THGeneral.h new file mode 100644 index 000000000..8d33ede38 --- /dev/null +++ b/modules/dnn/src/torch/THGeneral.h @@ -0,0 +1,89 @@ +#ifndef TH_GENERAL_INC +#define TH_GENERAL_INC + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +# define TH_EXTERNC extern "C" +#else +# define TH_EXTERNC extern +#endif + +#define TH_API TH_EXTERNC + +#define THInf DBL_MAX + +//#define TH_INLINE @TH_INLINE@ + +#ifndef __cplusplus +//#define inline @TH_INLINE@ +#endif + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +TH_API double THLog1p(const double x); +TH_API void _THError(const char *file, const int line, const char *fmt, ...); +TH_API void _THAssertionFailed(const char *file, const int line, const char *exp, const char *fmt, ...); +TH_API void THSetErrorHandler( void (*torchErrorHandlerFunction)(const char *msg, void *data), void *data ); +TH_API void _THArgCheck(const char *file, int line, int condition, int argNumber, const char *fmt, ...); +TH_API void THSetArgErrorHandler( void (*torchArgErrorHandlerFunction)(int argNumber, const char *msg, void *data), void *data ); +TH_API void* THAlloc(long size); +TH_API void* THRealloc(void *ptr, long size); +TH_API void THFree(void *ptr); +TH_API void THSetGCHandler( void (*torchGCHandlerFunction)(void *data), void *data ); +// this hook should only be called by custom allocator functions +TH_API void THHeapUpdate(long size); + +#define THError(...) _THError(__FILE__, __LINE__, __VA_ARGS__) +#define THArgCheck(...) _THArgCheck(__FILE__, __LINE__, __VA_ARGS__) +#define THAssert(exp) \ +do { \ + if (!(exp)) { \ + _THAssertionFailed(__FILE__, __LINE__, #exp, ""); \ + } \ +} while(0) +#define THAssertMsg(exp, ...) \ +do { \ + if (!(exp)) { \ + _THAssertionFailed(__FILE__, __LINE__, #exp, __VA_ARGS__); \ + } \ +} while(0) + +#define TH_CONCAT_STRING_2(x,y) TH_CONCAT_STRING_2_EXPAND(x,y) +#define TH_CONCAT_STRING_2_EXPAND(x,y) #x #y + +#define TH_CONCAT_STRING_3(x,y,z) TH_CONCAT_STRING_3_EXPAND(x,y,z) +#define TH_CONCAT_STRING_3_EXPAND(x,y,z) #x #y #z + +#define TH_CONCAT_STRING_4(x,y,z,w) TH_CONCAT_STRING_4_EXPAND(x,y,z,w) +#define TH_CONCAT_STRING_4_EXPAND(x,y,z,w) #x #y #z #w + +#define TH_CONCAT_2(x,y) TH_CONCAT_2_EXPAND(x,y) +#define TH_CONCAT_2_EXPAND(x,y) x ## y + +#define TH_CONCAT_3(x,y,z) TH_CONCAT_3_EXPAND(x,y,z) +#define TH_CONCAT_3_EXPAND(x,y,z) x ## y ## z + +#define TH_CONCAT_4_EXPAND(x,y,z,w) x ## y ## z ## w +#define TH_CONCAT_4(x,y,z,w) TH_CONCAT_4_EXPAND(x,y,z,w) + +#define THMin(X, Y) ((X) < (Y) ? (X) : (Y)) +#define THMax(X, Y) ((X) > (Y) ? (X) : (Y)) + +#if (defined(_MSC_VER) || defined(__MINGW32__)) +# define log1p(x) THLog1p(x) +#define snprintf _snprintf +#define popen _popen +#define pclose _pclose +#endif + +#endif diff --git a/modules/dnn/src/torch/torch_importer.cpp b/modules/dnn/src/torch/torch_importer.cpp new file mode 100644 index 000000000..8a4071db3 --- /dev/null +++ b/modules/dnn/src/torch/torch_importer.cpp @@ -0,0 +1,714 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "../precomp.hpp" +#include +#include +#include +#include +#include + +namespace cv { +namespace dnn { + +#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER +#include "THDiskFile.h" + +enum LuaType +{ + TYPE_NIL = 0, + TYPE_NUMBER = 1, + TYPE_STRING = 2, + TYPE_TABLE = 3, + TYPE_TORCH = 4, + TYPE_BOOLEAN = 5, + TYPE_FUNCTION = 6, + TYPE_RECUR_FUNCTION = 8, + LEGACY_TYPE_RECUR_FUNCTION = 7 +}; + +template +static String toString(const T &v) +{ + std::ostringstream ss; + ss << v; + return ss.str(); +} + +static inline bool startsWith(const String &str, const char *substr) +{ + return str.find(substr) == 0; +} + +static inline bool endsWith(const String &str, const char *substr) +{ + return str.rfind(substr) == str.length() - strlen(substr); +} + +struct TorchImporter : public ::cv::dnn::Importer +{ + Net net; + + THFile *file; + std::set readedIndexes; + std::map storages; + std::map tensors; + + struct Module + { + String thName, apiType; + dnn::LayerParams params; + std::vector modules; + + Module(const String &_thName, const String &_apiType = String()) + : thName(_thName), apiType(_apiType) {} + + ~Module() + { + for (size_t i = 0; i < modules.size(); i++) + delete modules[i]; + } + }; + + Module *rootModule; + Module *curModule; + int moduleCounter; + + TorchImporter(String filename, bool isBinary) + { + rootModule = curModule = NULL; + moduleCounter = 0; + + file = THDiskFile_new(filename.c_str(), "r", 0); + CV_Assert(file && THFile_isOpened(file)); + + if (isBinary) + THFile_binary(file); + else + THFile_ascii(file); + } + + /* Simple readers */ + + inline int readInt() + { + return THFile_readIntScalar(file); + } + + inline long readLong() + { + return THFile_readLongScalar(file); + } + + inline bool readBool() + { + return readInt() != 0; + } + + inline double readDouble() + { + return THFile_readDoubleScalar(file); + } + + inline String readString() + { + int size = THFile_readIntScalar(file); + String str(size, '\0'); + THFile_readCharRaw(file, const_cast(str.c_str()), size); + return str; + } + + inline String readTorchClassName() + { + String version = readString(); + return startsWith(version, "V ") ? readString() : version; + } + + inline void readFunction() + { + readString(); + readObject(); + } + + void readTable(int index = -1) + { + index = (index < 0) ? readInt() : index; + + if (readedIndexes.count(index)) + return; + + readedIndexes.insert(index); + + int size = readInt(); + for (int i = 0; i < size; i++) + { + readObject(); //key + readObject(); //value + } + } + + /* Special readers */ + + static inline int parseTorchType(const String &str, const char *suffix, const char *prefix = "torch.") + { + if (startsWith(str, prefix) && endsWith(str, suffix)) + { + String typeStr = str.substr(strlen(prefix), str.length() - strlen(prefix) - strlen(suffix)); + + if (typeStr == "Double") + return CV_64F; + else if (typeStr == "Float") + return CV_32F; + else if (typeStr == "Byte") + return CV_8U; + else if (typeStr == "Char") + return CV_8S; + else if (typeStr == "Short") + return CV_16S; + else if (typeStr == "Int") + return CV_32S; + else if (typeStr == "Long") //Carefully! CV_64S type coded as CV_USRTYPE1 + return CV_USRTYPE1; + else + CV_Error(Error::StsNotImplemented, "Unknown type \"" + typeStr + "\" of torch class \"" + str + "\""); + } + + return -1; + } + + static int parseTensorType(const String &className) + { + return parseTorchType(className, "Tensor"); + } + + static int parseStorageType(const String &className) + { + return parseTorchType(className, "Storage"); + } + + void readTorchStorage(int index, int type = -1) + { + long size = readLong(); + Mat storageMat(1, size, (type != CV_USRTYPE1) ? type : CV_64F); //handle LongStorage as CV_64F Mat + + switch (type) + { + case CV_32F: + THFile_readFloatRaw(file, (float*)storageMat.data, size); + break; + case CV_64F: + THFile_readDoubleRaw(file, (double*)storageMat.data, size); + break; + case CV_8S: + case CV_8U: + THFile_readByteRaw(file, (uchar*)storageMat.data, size); + break; + case CV_16S: + case CV_16U: + THFile_readShortRaw(file, (short*)storageMat.data, size); + break; + case CV_32S: + THFile_readIntRaw(file, (int*)storageMat.data, size); + break; + case CV_USRTYPE1: + { + double *buf = storageMat.ptr(); + THFile_readLongRaw(file, (long*)buf, size); + + for (size_t i = (size_t)size; i-- > 0; ) + buf[i] = ((long*)buf)[i]; + } + break; + default: + CV_Error(Error::StsInternal, ""); + break; + } + + storages.insert(std::make_pair(index, storageMat)); + } + + void readTorchTable(Dict &scalarParams, std::map &tensorParams) + { + int luaType = readInt(); + int index = readInt(); + + CV_Assert(luaType == TYPE_TABLE && readedIndexes.count(index) == 0); + readedIndexes.insert(index); + + long fpos; + int numPairs = readInt(); + + for (int i = 0; i < numPairs; i++) + { + fpos = THFile_position(file); + int ktype = readInt(); + + if (ktype != TYPE_STRING) //skip non-string fileds + { + THFile_seek(file, fpos); + readObject(); //key + readObject(); //value + continue; + } + + String key = readString(); + std::cout << i << "th key: " << key << "\n"; + + fpos = THFile_position(file); + int vtype = readInt(); + + if (vtype == TYPE_TORCH) + { + int index = readInt(); + readTorchObject(index); + + if (tensors.count(index)) //tensor was readed + { + tensorParams.insert(std::make_pair(key, tensors[index])); + } + else if (storages.count(index)) //storage was readed + { + Mat &matStorage = storages[index]; + Mat matCasted; + matStorage.convertTo(matCasted, CV_64F); + + DictValue scalar = DictValue::arrayReal(matCasted.ptr(), matCasted.total()); + scalarParams.set(key, scalar); + } + } + else if (vtype == TYPE_NUMBER) + { + scalarParams.set(key, readDouble()); + } + else if (vtype == TYPE_STRING) + { + scalarParams.set(key, readString()); + } + else if (vtype == TYPE_BOOLEAN) + { + scalarParams.set(key, readBool()); + } + else + { + THFile_seek(file, fpos); + readObject(); + } + } + + //Debug output + std::cout << "scalarParams:\n"; + std::cout << scalarParams; + + std::cout << "#" << tensorParams.size() << " tensorParams:\n"; + std::map::const_iterator it; + for (it = tensorParams.begin(); it != tensorParams.end(); it++) + std::cout << it->first << ": Tensor " << it->second.shape() << "\n"; + } + + void readTorchTensor(int indexTensor, int typeTensor) + { + int ndims = readInt(); + AutoBuffer sizes(ndims); + AutoBuffer steps(ndims); + THFile_readLongRaw(file, sizes, ndims); + THFile_readLongRaw(file, steps, ndims); + long offset = readLong() - 1; + + //read Storage + int typeidx = readInt(); + CV_Assert(typeidx == TYPE_TORCH || (typeidx == TYPE_NIL && ndims == 0)); + + if (typeidx == TYPE_NIL) + { + tensors.insert(std::make_pair(indexTensor, Blob())); + return; + } + + int indexStorage = readInt(); + if (readedIndexes.count(indexStorage) == 0) + { + int typeStorage = parseStorageType(readTorchClassName()); + CV_Assert(typeStorage >= 0 && typeTensor == typeStorage); + readTorchStorage(indexStorage, typeStorage); + } + + //small check + size_t requireElems = (size_t)offset + (size_t)steps[0] * (size_t)sizes[0]; + size_t storageElems = storages[indexStorage].total(); + if (requireElems > storageElems) + CV_Error(Error::StsBadSize, "Storage has insufficent number of elemements for requested Tensor"); + + //convert sizes + AutoBuffer isizes(ndims); + AutoBuffer ssteps(ndims); + for (int i = ndims - 1; i >= 0; i--) + { + isizes[i] = (int)sizes[i]; + ssteps[i] = (size_t)steps[i] * CV_ELEM_SIZE(typeTensor); + } + + //allocate Blob + Mat srcMat(ndims, (int*)isizes, typeTensor , storages[indexStorage].ptr() + offset, (size_t*)ssteps); + //int dstType = (typeTensor == CV_64F) ? CV_64F : CV_32F; + int dstType = CV_32F; + + Blob blob; + blob.create(BlobShape(ndims, isizes), dstType); + srcMat.convertTo(blob.matRef(), dstType); + + tensors.insert(std::make_pair(indexTensor, blob)); + } + + static bool isNNClass(const String &className, String &nnName) + { + const char *prefixes[] = {"nn.", "cunn.", "cudnn.", "fbcunn.", NULL}; + + for (int i = 0; prefixes[i]; i++) + { + if (startsWith(className, prefixes[i])) + { + nnName = className.substr(strlen(prefixes[i])); + return true; + } + } + + return false; + } + + static void convertTorchKernelsParams(const Dict &torchParams, cv::dnn::LayerParams &layerParams) + { + layerParams.set("kernel_h", torchParams.get("kH")); + layerParams.set("kernel_w", torchParams.get("kW")); + layerParams.set("stride_h", torchParams.get("dH")); + layerParams.set("stride_w", torchParams.get("dW")); + layerParams.set("pad_h", torchParams.get("padH", 0)); + layerParams.set("pad_w", torchParams.get("padW", 0)); + } + + void readTorchObject(int index) + { + if(readedIndexes.count(index)) + { + if(!storages.count(index) && !tensors.count(index)) + CV_Error(Error::StsNotImplemented, "Objects which have multiple references are not supported"); + else + return; + } + + String className = readTorchClassName(); + String nnName; + std::cout << "Class: " << className << std::endl; + + int type; + if ( (type = parseTensorType(className)) >= 0 ) //is Tensor + { + readTorchTensor(index, type); + } + else if ( (type = parseStorageType(className)) >= 0 ) //is Storage + { + readTorchStorage(index, type); + } + else if (isNNClass(className, nnName)) + { + Dict scalarParams; + std::map tensorParams; + + Module *newModule = new Module(nnName); + cv::dnn::LayerParams &layerParams = newModule->params; + + if (nnName == "Sequential" || nnName == "Parallel" || nnName == "Concat") + { + Module *parentModule = curModule; + curModule->modules.push_back(newModule); + curModule = newModule; + readTorchTable(scalarParams, tensorParams); + curModule = parentModule; + + if (nnName == "Parallel") + { + layerParams.set("inputDimension", scalarParams.get("inputDimension")); + layerParams.set("outputDimension", scalarParams.get("outputDimension")); + } + if (nnName == "Concat") + { + layerParams.set("dimension", scalarParams.get("dimension")); + } + } + else if (nnName == "SpatialConvolution") + { + newModule->apiType = "Convolution"; + readTorchTable(scalarParams, tensorParams); + + CV_Assert(tensorParams.count("weight")); + layerParams.blobs.push_back(tensorParams["weight"]); + + bool bias = tensorParams.count("bias") != 0; + layerParams.set("bias_term", bias); + if (bias) + layerParams.blobs.push_back(tensorParams["bias"]); + + layerParams.set("num_output", scalarParams.get("nOutputPlane")); + convertTorchKernelsParams(scalarParams, layerParams); + + curModule->modules.push_back(newModule); + } + else if (nnName == "SpatialMaxPooling" || nnName == "SpatialAveragePooling") + { + newModule->apiType = "Pooling"; + readTorchTable(scalarParams, tensorParams); + + if (nnName == "SpatialMaxPooling") + layerParams.set("pool", "MAX"); + if (nnName == "SpatialAveragePooling") + layerParams.set("pool", "AVE"); + convertTorchKernelsParams(scalarParams, layerParams); + + curModule->modules.push_back(newModule); + } + else if (nnName == "Linear") + { + newModule->apiType = "InnerProduct"; + readTorchTable(scalarParams, tensorParams); + + CV_Assert(tensorParams.count("weight")); + Blob weightBlob = tensorParams["weight"]; + layerParams.blobs.push_back(weightBlob); + + bool bias = tensorParams.count("bias") != 0; + if (bias) + layerParams.blobs.push_back(tensorParams["bias"]); + layerParams.set("bias_term", bias); + + layerParams.set("num_output", weightBlob.size(0)); + curModule->modules.push_back(newModule); + } + else if (nnName == "Reshape") + { + newModule->apiType = "Reshape"; + + readTorchTable(scalarParams, tensorParams); + CV_Assert(scalarParams.has("size")); + + DictValue dimParam = scalarParams.get("size"); + layerParams.set("dim", dimParam); + + if (scalarParams.has("batchMode") && scalarParams.get("batchMode")) + layerParams.set("axis", 1); + + curModule->modules.push_back(newModule); + } + else if (nnName == "ReLU") + { + curModule->modules.push_back(new Module(nnName, "ReLU")); + readObject(); + } + else if (nnName == "Tanh") + { + curModule->modules.push_back(new Module(nnName, "TanH")); + readObject(); + } + else if (nnName == "Sigmoid") + { + curModule->modules.push_back(new Module(nnName, "Sigmoid")); + readObject(); + } + else + { + delete newModule; + CV_Error(Error::StsNotImplemented, "Unknown nn class \"" + className + "\""); + readObject(); + } + } + else + { + CV_Error(Error::StsNotImplemented, "Unsupported Torch class \"" + className + "\""); + } + + readedIndexes.insert(index); + } + + void readObject() + { + int typeidx = readInt(); + + if (typeidx == TYPE_TORCH) + { + int index = readInt(); + readTorchObject(index); + readedIndexes.insert(index); + } + else if (typeidx == TYPE_NIL) + return; + else if (typeidx == TYPE_NUMBER) + readDouble(); + else if (typeidx == TYPE_BOOLEAN) + readBool(); + else if (typeidx == TYPE_STRING) + readString(); + else if (typeidx == TYPE_TABLE) + readTable(); + else + CV_Error(Error::StsNotImplemented, "Unsupported Lua type"); + } + + inline String generateLayerName(const String &label = String()) + { + return "l" + toString(++this->moduleCounter) + "_" + label; + } + + int fill(Module *module, int prevLayerId = 0, int prevOutNum = 0) + { + if (module == NULL) + return prevLayerId; + + if (module->apiType.length()) + { + int newLayerId = this->net.addLayer(generateLayerName(module->apiType), module->apiType, module->params); + net.connect(prevLayerId, prevOutNum, newLayerId, 0); + return newLayerId; + } + else + { + if (module->thName == "Sequential") + { + for (size_t i = 0; i < module->modules.size(); i++) + { + prevLayerId = fill(module->modules[i], prevLayerId, prevOutNum); + prevOutNum = 0; + } + return prevLayerId; + } + else if (module->thName == "Concat") + { + int newId, splitId, mergeId; + LayerParams mergeParams, splitParams; + mergeParams.set("axis", module->params.get("dimension") - 1); + + splitId = net.addLayer(generateLayerName("torchSplit"), "Split", splitParams); + mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); + net.connect(prevLayerId, prevOutNum, splitId, 0); + + for (int i = 0; i < (int)module->modules.size(); i++) + { + newId = fill(module->modules[i], splitId, i); + net.connect(newId, 0, mergeId, i); + } + + return mergeId; + } + else if (module->thName == "Parallel") + { + int newId, splitId, mergeId, reshapeId; + + LayerParams splitParams, mergeParams, reshapeParams; + splitParams.set("axis", module->params.get("inputDimension") - 1); + mergeParams.set("axis", module->params.get("outputDimension") - 1); + reshapeParams.set("axis", splitParams.get("axis")); + reshapeParams.set("num_axes", 1); + + splitId = net.addLayer(generateLayerName("torchSplit"), "Slice", splitParams); + mergeId = net.addLayer(generateLayerName("torchMerge"), "Concat", mergeParams); + reshapeId = net.addLayer(generateLayerName("torchReshape"), "Reshape", reshapeParams); + net.connect(prevLayerId, prevOutNum, splitId, 0); + + for (int i = 0; i < (int)module->modules.size(); i++) + { + net.connect(splitId, i, reshapeId, i); + newId = fill(module->modules[i], reshapeId, i); + net.connect(newId, 0, mergeId, i); + } + + return mergeId; + } + } + + CV_Error(Error::StsInternal, "Unexpected torch container: " + module->thName); + return -1; + } + + void populateNet(Net net) + { + if (rootModule == NULL) + { + rootModule = new Module("Sequential"); + curModule = rootModule; + + THFile_seek(file, 0); + readObject(); + } + + this->net = net; + fill(rootModule); + } +}; + +CV_EXPORTS Ptr createTorchImporter(const String &filename, bool isBinary) +{ + return Ptr(new TorchImporter(filename, isBinary)); +} + + +CV_EXPORTS Blob readTorchBlob(const String &filename, bool isBinary) +{ + Ptr importer(new TorchImporter(filename, isBinary)); + importer->readObject(); + CV_Assert(importer->tensors.size() == 1); + + return importer->tensors.begin()->second; +} + +#else //ENABLE_TORCH_IMPORTER + +CV_EXPORTS Ptr createTorchImporter(const String&, bool) +{ + CV_Error(Error::StsNotImplemented, "Module was build without Torch importer"); + return Ptr(); +} + +CV_EXPORTS Blob readTorchMat(const String&, bool) +{ + CV_Error(Error::StsNotImplemented, "Module was build without Torch importer"); + return Blob(); +} + +#endif //ENABLE_TORCH_IMPORTER +} +} diff --git a/modules/dnn/test/cnpy.cpp b/modules/dnn/test/cnpy.cpp new file mode 100644 index 000000000..ee49519f5 --- /dev/null +++ b/modules/dnn/test/cnpy.cpp @@ -0,0 +1,291 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +//Copyright (C) 2011 Carl Rogers +//Released under MIT License +//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php + +#include"cnpy.h" +#include +#include +#include +#include +#include + +char cnpy::BigEndianTest() { + union + { + unsigned char x[2]; + short y; + }; + x[0] = 1; + x[1] = 0; + + return y == 1 ? '<' : '>'; +} + +char cnpy::map_type(const std::type_info& t) +{ + if(t == typeid(float) ) return 'f'; + if(t == typeid(double) ) return 'f'; + if(t == typeid(long double) ) return 'f'; + + if(t == typeid(int) ) return 'i'; + if(t == typeid(char) ) return 'i'; + if(t == typeid(short) ) return 'i'; + if(t == typeid(long) ) return 'i'; + if(t == typeid(long long) ) return 'i'; + + if(t == typeid(unsigned char) ) return 'u'; + if(t == typeid(unsigned short) ) return 'u'; + if(t == typeid(unsigned long) ) return 'u'; + if(t == typeid(unsigned long long) ) return 'u'; + if(t == typeid(unsigned int) ) return 'u'; + + if(t == typeid(bool) ) return 'b'; + + if(t == typeid(std::complex) ) return 'c'; + if(t == typeid(std::complex) ) return 'c'; + if(t == typeid(std::complex) ) return 'c'; + + else return '?'; +} + +template<> std::vector& cnpy::operator+=(std::vector& lhs, const std::string rhs) { + lhs.insert(lhs.end(),rhs.begin(),rhs.end()); + return lhs; +} + +template<> std::vector& cnpy::operator+=(std::vector& lhs, const char* rhs) { + //write in little endian + size_t len = strlen(rhs); + lhs.reserve(len); + for(size_t byte = 0; byte < len; byte++) { + lhs.push_back(rhs[byte]); + } + return lhs; +} + +void cnpy::parse_npy_header(FILE* fp, unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order) { + char buffer[256]; + size_t res = fread(buffer,sizeof(char),11,fp); + if(res != 11) + throw std::runtime_error("parse_npy_header: failed fread"); + std::string header = fgets(buffer,256,fp); + cnpy_assert(header[header.size()-1] == '\n'); + + size_t loc1, loc2; + + //fortran order + loc1 = header.find("fortran_order")+16; + fortran_order = (header.substr(loc1,5) == "True" ? true : false); + + //shape + loc1 = header.find("("); + loc2 = header.find(")"); + std::string str_shape = header.substr(loc1+1,loc2-loc1-1); + if(str_shape[str_shape.size()-1] == ',') ndims = 1; + else ndims = (unsigned)std::count(str_shape.begin(),str_shape.end(),',')+1; + shape = new unsigned int[ndims]; + for(unsigned int i = 0;i < ndims;i++) { + loc1 = str_shape.find(","); + shape[i] = atoi(str_shape.substr(0,loc1).c_str()); + str_shape = str_shape.substr(loc1+1); + } + + //endian, word size, data type + //byte order code | stands for not applicable. + //not sure when this applies except for byte array + loc1 = header.find("descr")+9; + bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false); + cnpy_assert(littleEndian); + + //char type = header[loc1+1]; + //assert(type == map_type(T)); + + std::string str_ws = header.substr(loc1+2); + loc2 = str_ws.find("'"); + word_size = atoi(str_ws.substr(0,loc2).c_str()); +} + +void cnpy::parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset) +{ + std::vector footer(22); + fseek(fp,-22,SEEK_END); + size_t res = fread(&footer[0],sizeof(char),22,fp); + if(res != 22) + throw std::runtime_error("parse_zip_footer: failed fread"); + + unsigned short disk_no, disk_start, nrecs_on_disk, comment_len; + disk_no = *(unsigned short*) &footer[4]; + disk_start = *(unsigned short*) &footer[6]; + nrecs_on_disk = *(unsigned short*) &footer[8]; + nrecs = *(unsigned short*) &footer[10]; + global_header_size = *(unsigned int*) &footer[12]; + global_header_offset = *(unsigned int*) &footer[16]; + comment_len = *(unsigned short*) &footer[20]; + + cnpy_assert(disk_no == 0); + cnpy_assert(disk_start == 0); + cnpy_assert(nrecs_on_disk == nrecs); + cnpy_assert(comment_len == 0); +} + +cnpy::NpyArray load_the_npy_file(FILE* fp) { + unsigned int* shape; + unsigned int ndims, word_size; + bool fortran_order; + cnpy::parse_npy_header(fp,word_size,shape,ndims,fortran_order); + unsigned long long size = 1; //long long so no overflow when multiplying by word_size + for(unsigned int i = 0;i < ndims;i++) size *= shape[i]; + + cnpy::NpyArray arr; + arr.word_size = word_size; + arr.shape = std::vector(shape,shape+ndims); + delete[] shape; + arr.data = new char[size*word_size]; + arr.fortran_order = fortran_order; + size_t nread = fread(arr.data,word_size,size,fp); + if(nread != size) + throw std::runtime_error("load_the_npy_file: failed fread"); + return arr; +} + +cnpy::npz_t cnpy::npz_load(std::string fname) { + FILE* fp = fopen(fname.c_str(),"rb"); + + if(!fp) printf("npz_load: Error! Unable to open file %s!\n",fname.c_str()); + cnpy_assert(fp); + + cnpy::npz_t arrays; + + while(1) { + std::vector local_header(30); + size_t headerres = fread(&local_header[0],sizeof(char),30,fp); + if(headerres != 30) + throw std::runtime_error("npz_load: failed fread"); + + //if we've reached the global header, stop reading + if(local_header[2] != 0x03 || local_header[3] != 0x04) break; + + //read in the variable name + unsigned short name_len = *(unsigned short*) &local_header[26]; + std::string varname(name_len,' '); + size_t vname_res = fread(&varname[0],sizeof(char),name_len,fp); + if(vname_res != name_len) + throw std::runtime_error("npz_load: failed fread"); + + //erase the lagging .npy + varname.erase(varname.end()-4,varname.end()); + + //read in the extra field + unsigned short extra_field_len = *(unsigned short*) &local_header[28]; + if(extra_field_len > 0) { + std::vector buff(extra_field_len); + size_t efield_res = fread(&buff[0],sizeof(char),extra_field_len,fp); + if(efield_res != extra_field_len) + throw std::runtime_error("npz_load: failed fread"); + } + + arrays[varname] = load_the_npy_file(fp); + } + + fclose(fp); + return arrays; +} + +cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname) { + FILE* fp = fopen(fname.c_str(),"rb"); + + if(!fp) { + throw std::runtime_error("npz_load: Error! Unable to open file " + fname + "!\n"); + } + + while(1) { + std::vector local_header(30); + size_t header_res = fread(&local_header[0],sizeof(char),30,fp); + if(header_res != 30) + throw std::runtime_error("npz_load: failed fread"); + + //if we've reached the global header, stop reading + if(local_header[2] != 0x03 || local_header[3] != 0x04) break; + + //read in the variable name + unsigned short name_len = *(unsigned short*) &local_header[26]; + std::string vname(name_len,' '); + size_t vname_res = fread(&vname[0],sizeof(char),name_len,fp); + if(vname_res != name_len) + throw std::runtime_error("npz_load: failed fread"); + vname.erase(vname.end()-4,vname.end()); //erase the lagging .npy + + //read in the extra field + unsigned short extra_field_len = *(unsigned short*) &local_header[28]; + fseek(fp,extra_field_len,SEEK_CUR); //skip past the extra field + + if(vname == varname) { + NpyArray array = load_the_npy_file(fp); + fclose(fp); + return array; + } + else { + //skip past the data + unsigned int size = *(unsigned int*) &local_header[22]; + fseek(fp,size,SEEK_CUR); + } + } + + fclose(fp); + throw std::runtime_error("npz_load: Error! Variable name " + varname + " not found in " + fname + "!\n"); +} + +cnpy::NpyArray cnpy::npy_load(std::string fname) { + + FILE* fp = fopen(fname.c_str(), "rb"); + + if(!fp) { + throw std::runtime_error("npy_load: Error! Unable to open file " + fname + "!\n"); + } + + NpyArray arr = load_the_npy_file(fp); + + fclose(fp); + return arr; +} diff --git a/modules/dnn/test/cnpy.h b/modules/dnn/test/cnpy.h new file mode 100644 index 000000000..4e98ce802 --- /dev/null +++ b/modules/dnn/test/cnpy.h @@ -0,0 +1,294 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +//Copyright (C) 2011 Carl Rogers +//Released under MIT License +//license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php + +#ifndef LIBCNPY_H_ +#define LIBCNPY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(HAVE_ZLIB) && HAVE_ZLIB +#include +#endif + +#ifndef NDEBUG +#define cnpy_assert(expression) assert(expression) +#else +#define cnpy_assert(expression) ((void)(expression)) +#endif + +namespace cnpy { + + struct NpyArray { + char* data; + std::vector shape; + unsigned int word_size; + bool fortran_order; + void destruct() {delete[] data;} + }; + + struct npz_t : public std::map + { + void destruct() + { + npz_t::iterator it = this->begin(); + for(; it != this->end(); ++it) (*it).second.destruct(); + } + }; + + char BigEndianTest(); + char map_type(const std::type_info& t); + template std::vector create_npy_header(const T* data, const unsigned int* shape, const unsigned int ndims); + void parse_npy_header(FILE* fp,unsigned int& word_size, unsigned int*& shape, unsigned int& ndims, bool& fortran_order); + void parse_zip_footer(FILE* fp, unsigned short& nrecs, unsigned int& global_header_size, unsigned int& global_header_offset); + npz_t npz_load(std::string fname); + NpyArray npz_load(std::string fname, std::string varname); + NpyArray npy_load(std::string fname); + + template std::vector& operator+=(std::vector& lhs, const T rhs) { + //write in little endian + for(char byte = 0; byte < sizeof(T); byte++) { + char val = *((char*)&rhs+byte); + lhs.push_back(val); + } + return lhs; + } + + template<> std::vector& operator+=(std::vector& lhs, const std::string rhs); + template<> std::vector& operator+=(std::vector& lhs, const char* rhs); + + + template std::string tostring(T i, int = 0, char = ' ') { + std::stringstream s; + s << i; + return s.str(); + } + + template void npy_save(std::string fname, const T* data, const unsigned int* shape, const unsigned int ndims, std::string mode = "w") { + FILE* fp = NULL; + + if(mode == "a") fp = fopen(fname.c_str(),"r+b"); + + if(fp) { + //file exists. we need to append to it. read the header, modify the array size + unsigned int word_size, tmp_dims; + unsigned int* tmp_shape = 0; + bool fortran_order; + parse_npy_header(fp,word_size,tmp_shape,tmp_dims,fortran_order); + cnpy_assert(!fortran_order); + + if(word_size != sizeof(T)) { + std::cout<<"libnpy error: "< header = create_npy_header(data,tmp_shape,ndims); + fwrite(&header[0],sizeof(char),header.size(),fp); + fseek(fp,0,SEEK_END); + + delete[] tmp_shape; + } + else { + fp = fopen(fname.c_str(),"wb"); + std::vector header = create_npy_header(data,shape,ndims); + fwrite(&header[0],sizeof(char),header.size(),fp); + } + + unsigned int nels = 1; + for(unsigned i = 0;i < ndims;i++) nels *= shape[i]; + + fwrite(data,sizeof(T),nels,fp); + fclose(fp); + } + + template void npz_save(std::string zipname, std::string fname, const T* data, const unsigned int* shape, const unsigned int ndims, std::string mode = "w") + { + //first, append a .npy to the fname + fname += ".npy"; + + //now, on with the show + FILE* fp = NULL; + unsigned short nrecs = 0; + unsigned int global_header_offset = 0; + std::vector global_header; + + if(mode == "a") fp = fopen(zipname.c_str(),"r+b"); + + if(fp) { + //zip file exists. we need to add a new npy file to it. + //first read the footer. this gives us the offset and size of the global header + //then read and store the global header. + //below, we will write the the new data at the start of the global header then append the global header and footer below it + unsigned int global_header_size; + parse_zip_footer(fp,nrecs,global_header_size,global_header_offset); + fseek(fp,global_header_offset,SEEK_SET); + global_header.resize(global_header_size); + size_t res = fread(&global_header[0],sizeof(char),global_header_size,fp); + if(res != global_header_size){ + throw std::runtime_error("npz_save: header read error while adding to existing zip"); + } + fseek(fp,global_header_offset,SEEK_SET); + } + else { + fp = fopen(zipname.c_str(),"wb"); + } + + std::vector npy_header = create_npy_header(data,shape,ndims); + + unsigned long nels = 1; + for (unsigned m=0; m local_header; + local_header += "PK"; //first part of sig + local_header += (unsigned short) 0x0403; //second part of sig + local_header += (unsigned short) 20; //min version to extract + local_header += (unsigned short) 0; //general purpose bit flag + local_header += (unsigned short) 0; //compression method + local_header += (unsigned short) 0; //file last mod time + local_header += (unsigned short) 0; //file last mod date + local_header += (unsigned int) crc; //crc + local_header += (unsigned int) nbytes; //compressed size + local_header += (unsigned int) nbytes; //uncompressed size + local_header += (unsigned short) fname.size(); //fname length + local_header += (unsigned short) 0; //extra field length + local_header += fname; + + //build global header + global_header += "PK"; //first part of sig + global_header += (unsigned short) 0x0201; //second part of sig + global_header += (unsigned short) 20; //version made by + global_header.insert(global_header.end(),local_header.begin()+4,local_header.begin()+30); + global_header += (unsigned short) 0; //file comment length + global_header += (unsigned short) 0; //disk number where file starts + global_header += (unsigned short) 0; //internal file attributes + global_header += (unsigned int) 0; //external file attributes + global_header += (unsigned int) global_header_offset; //relative offset of local file header, since it begins where the global header used to begin + global_header += fname; + + //build footer + std::vector footer; + footer += "PK"; //first part of sig + footer += (unsigned short) 0x0605; //second part of sig + footer += (unsigned short) 0; //number of this disk + footer += (unsigned short) 0; //disk where footer starts + footer += (unsigned short) (nrecs+1); //number of records on this disk + footer += (unsigned short) (nrecs+1); //total number of records + footer += (unsigned int) global_header.size(); //nbytes of global headers + footer += (unsigned int) (global_header_offset + nbytes + local_header.size()); //offset of start of global headers, since global header now starts after newly written array + footer += (unsigned short) 0; //zip file comment length + + //write everything + fwrite(&local_header[0],sizeof(char),local_header.size(),fp); + fwrite(&npy_header[0],sizeof(char),npy_header.size(),fp); + fwrite(data,sizeof(T),nels,fp); + fwrite(&global_header[0],sizeof(char),global_header.size(),fp); + fwrite(&footer[0],sizeof(char),footer.size(),fp); + fclose(fp); + } + + template std::vector create_npy_header(const T*, const unsigned int* shape, const unsigned int ndims) { + + std::vector dict; + dict += "{'descr': '"; + dict += BigEndianTest(); + dict += map_type(typeid(T)); + dict += tostring(sizeof(T)); + dict += "', 'fortran_order': False, 'shape': ("; + dict += tostring(shape[0]); + for(unsigned i = 1;i < ndims;i++) { + dict += ", "; + dict += tostring(shape[i]); + } + if(ndims == 1) dict += ","; + dict += "), }"; + //pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to end with \n + int remainder = 16 - (10 + dict.size()) % 16; + dict.insert(dict.end(),remainder,' '); + dict.back() = '\n'; + + std::vector header; + header += (unsigned char) 0x93; + header += "NUMPY"; + header += (char) 0x01; //major version of numpy format + header += (char) 0x00; //minor version of numpy format + header += (unsigned short) dict.size(); + header.insert(header.end(),dict.begin(),dict.end()); + + return header; + } + + +} + +#endif diff --git a/modules/dnn/test/npy_blob.hpp b/modules/dnn/test/npy_blob.hpp new file mode 100644 index 000000000..7c9910172 --- /dev/null +++ b/modules/dnn/test/npy_blob.hpp @@ -0,0 +1,65 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_DNN_TEST_NPY_BLOB_HPP__ +#define __OPENCV_DNN_TEST_NPY_BLOB_HPP__ +#include "test_precomp.hpp" +#include "cnpy.h" + +inline cv::dnn::Blob blobFromNPY(const cv::String &path) +{ + cnpy::NpyArray npyBlob = cnpy::npy_load(path.c_str()); + cv::dnn::BlobShape shape((int)npyBlob.shape.size(), (int*)&npyBlob.shape[0]); + + cv::dnn::Blob blob(shape); + blob.fill(shape, CV_32F, npyBlob.data); + + npyBlob.destruct(); + return blob; +} + +inline void saveBlobToNPY(cv::dnn::Blob &blob, const cv::String &path) +{ + cv::dnn::BlobShape shape = blob.shape(); + cnpy::npy_save(path.c_str(), blob.ptrf(), (unsigned*)&shape[0], shape.dims()); +} + +#endif diff --git a/modules/dnn/test/test_alexnet.cpp b/modules/dnn/test/test_alexnet.cpp new file mode 100644 index 000000000..b0abb1765 --- /dev/null +++ b/modules/dnn/test/test_alexnet.cpp @@ -0,0 +1,81 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#if defined(ENABLE_CAFFE_MODEL_TESTS) && defined(ENABLE_CAFFE_ALEXNET_TEST) //AlexNet is disabled now +#include "test_precomp.hpp" +#include "npy_blob.hpp" + +namespace cvtest +{ + +using namespace cv; +using namespace cv::dnn; + +template +static std::string _tf(TString filename) +{ + return (getOpenCVExtraDir() + "/dnn/") + filename; +} + +TEST(Reproducibility_AlexNet, Accuracy) +{ + Net net; + { + Ptr importer = createCaffeImporter(_tf("bvlc_alexnet.prototxt"), _tf("bvlc_alexnet.caffemodel")); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } + + std::vector inpMats; + inpMats.push_back( imread(_tf("alexnet_0.png")) ); + inpMats.push_back( imread(_tf("alexnet_1.png")) ); + ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty()); + + net.setBlob(".data", Blob(inpMats)); + net.forward(); + + Blob out = net.getBlob("prob"); + Blob ref = blobFromNPY(_tf("alexnet.npy")); + normAssert(ref, out, "prob"); +} + +} +#endif diff --git a/modules/dnn/test/test_caffe_importer.cpp b/modules/dnn/test/test_caffe_importer.cpp new file mode 100644 index 000000000..4983b8c3f --- /dev/null +++ b/modules/dnn/test/test_caffe_importer.cpp @@ -0,0 +1,76 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "test_precomp.hpp" + +namespace cvtest +{ + +using namespace cv; +using namespace cv::dnn; + +template +static std::string _tf(TString filename) +{ + return (getOpenCVExtraDir() + "/dnn/") + filename; +} + +TEST(Test_Caffe, read_gtsrb) +{ + Net net; + { + Ptr importer = createCaffeImporter(_tf("gtsrb.prototxt"), ""); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } +} + +TEST(Test_Caffe, read_googlenet) +{ + Net net; + { + Ptr importer = createCaffeImporter(_tf("bvlc_googlenet.prototxt"), ""); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } +} + +} diff --git a/modules/dnn/test/test_common.hpp b/modules/dnn/test/test_common.hpp new file mode 100644 index 000000000..b9a4ee12e --- /dev/null +++ b/modules/dnn/test/test_common.hpp @@ -0,0 +1,65 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef __OPENCV_TEST_COMMON_HPP__ +#define __OPENCV_TEST_COMMON_HPP__ + +inline const std::string &getOpenCVExtraDir() +{ + return cvtest::TS::ptr()->get_data_path(); +} + +inline void normAssert(cv::InputArray ref, cv::InputArray test, const char *comment = "") +{ + double normL1 = cvtest::norm(ref, test, cv::NORM_L1) / ref.getMat().total(); + EXPECT_LE(normL1, 0.0001) << comment; + + double normInf = cvtest::norm(ref, test, cv::NORM_INF); + EXPECT_LE(normInf, 0.001) << comment; +} + +inline void normAssert(cv::dnn::Blob &ref, cv::dnn::Blob &test, const char *comment = "") +{ + ASSERT_EQ(ref.shape(), test.shape()) << comment; + normAssert(ref.matRefConst(), test.matRefConst(), comment); +} + +#endif diff --git a/modules/dnn/test/test_googlenet.cpp b/modules/dnn/test/test_googlenet.cpp new file mode 100644 index 000000000..74be05368 --- /dev/null +++ b/modules/dnn/test/test_googlenet.cpp @@ -0,0 +1,81 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#if defined(ENABLE_CAFFE_MODEL_TESTS) +#include "test_precomp.hpp" +#include "npy_blob.hpp" + +namespace cvtest +{ + +using namespace cv; +using namespace cv::dnn; + +template +static std::string _tf(TString filename) +{ + return (getOpenCVExtraDir() + "/dnn/") + filename; +} + +TEST(Reproducibility_GoogLeNet, Accuracy) +{ + Net net; + { + Ptr importer = createCaffeImporter(_tf("bvlc_googlenet.prototxt"), _tf("bvlc_googlenet.caffemodel")); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } + + std::vector inpMats; + inpMats.push_back( imread(_tf("googlenet_0.jpg")) ); + inpMats.push_back( imread(_tf("googlenet_1.jpg")) ); + ASSERT_TRUE(!inpMats[0].empty() && !inpMats[1].empty()); + + net.setBlob(".data", Blob(inpMats)); + net.forward(); + + Blob out = net.getBlob("prob"); + Blob ref = blobFromNPY(_tf("googlenet_prob.npy")); + normAssert(out, ref); +} + +} +#endif diff --git a/modules/dnn/test/test_layers.cpp b/modules/dnn/test/test_layers.cpp new file mode 100644 index 000000000..35c678b27 --- /dev/null +++ b/modules/dnn/test/test_layers.cpp @@ -0,0 +1,177 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "test_precomp.hpp" +#include +#include +#include "npy_blob.hpp" + +namespace cvtest +{ + +using namespace cv; +using namespace cv::dnn; + +template +static String _tf(TString filename) +{ + return (getOpenCVExtraDir() + "/dnn/layers/") + filename; +} + +static void testLayer(String basename, bool useCaffeModel = false, bool useCommonInputBlob = true) +{ + String prototxt = _tf(basename + ".prototxt"); + String caffemodel = _tf(basename + ".caffemodel"); + + String inpfile = (useCommonInputBlob) ? _tf("blob.npy") : _tf(basename + ".input.npy"); + String outfile = _tf(basename + ".npy"); + + Net net; + { + Ptr importer = createCaffeImporter(prototxt, (useCaffeModel) ? caffemodel : String()); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } + + Blob inp = blobFromNPY(inpfile); + Blob ref = blobFromNPY(outfile); + + net.setBlob(".input", inp); + net.forward(); + Blob out = net.getBlob("output"); + + normAssert(ref, out); +} + +TEST(Layer_Test_Softmax, Accuracy) +{ + testLayer("layer_softmax"); +} + +TEST(Layer_Test_LRN_spatial, Accuracy) +{ + testLayer("layer_lrn_spatial"); +} + +TEST(Layer_Test_LRN_channels, Accuracy) +{ + testLayer("layer_lrn_channels"); +} + +TEST(Layer_Test_Convolution, Accuracy) +{ + testLayer("layer_convolution", true); +} + +//TODO: move this test into separate file +TEST(Layer_Test_Convolution, AccuracyOCL) +{ + if (cv::ocl::haveOpenCL()) + { + cv::ocl::setUseOpenCL(true); + testLayer("layer_convolution", true); + cv::ocl::setUseOpenCL(false); + } +} + +TEST(Layer_Test_InnerProduct, Accuracy) +{ + testLayer("layer_inner_product", true); +} + +TEST(Layer_Test_Pooling_max, Accuracy) +{ + testLayer("layer_pooling_max"); +} + +TEST(Layer_Test_Pooling_ave, Accuracy) +{ + testLayer("layer_pooling_ave"); +} + +TEST(Layer_Test_DeConvolution, Accuracy) +{ + testLayer("layer_deconvolution", true, false); +} + +TEST(Layer_Test_MVN, Accuracy) +{ + testLayer("layer_mvn"); +} + +TEST(Layer_Test_Reshape, squeeze) +{ + LayerParams params; + params.set("axis", 2); + params.set("num_axes", 1); + + Blob inp(BlobShape(4, 3, 1, 2)); + std::vector inpVec(1, &inp); + std::vector outVec; + + Ptr rl = LayerFactory::createLayerInstance("Reshape", params); + rl->allocate(inpVec, outVec); + rl->forward(inpVec, outVec); + + EXPECT_EQ(outVec[0].shape(), BlobShape(Vec3i(4, 3, 2))); +} + +TEST(Layer_Test_Reshape_Split_Slice, Accuracy) +{ + Net net; + { + Ptr importer = createCaffeImporter(_tf("reshape_and_slice_routines.prototxt")); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + } + + Blob input(BlobShape(Vec2i(6, 12))); + RNG rng(0); + rng.fill(input.matRef(), RNG::UNIFORM, -1, 1); + + net.setBlob(".input", input); + net.forward(); + Blob output = net.getBlob("output"); + + normAssert(input, output); +} + +} diff --git a/modules/dnn/test/test_main.cpp b/modules/dnn/test/test_main.cpp new file mode 100644 index 000000000..6f9ac2e0d --- /dev/null +++ b/modules/dnn/test/test_main.cpp @@ -0,0 +1,3 @@ +#include "test_precomp.hpp" + +CV_TEST_MAIN("") diff --git a/modules/dnn/test/test_precomp.hpp b/modules/dnn/test/test_precomp.hpp new file mode 100644 index 000000000..ee13ebe19 --- /dev/null +++ b/modules/dnn/test/test_precomp.hpp @@ -0,0 +1,62 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_TEST_PRECOMP_HPP__ +#define __OPENCV_TEST_PRECOMP_HPP__ + +#include "opencv2/core.hpp" +#include "opencv2/dnn.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/ts.hpp" +#include +#include +#include "test_common.hpp" + +#endif diff --git a/modules/dnn/test/test_torch_importer.cpp b/modules/dnn/test/test_torch_importer.cpp new file mode 100644 index 000000000..0f45ab340 --- /dev/null +++ b/modules/dnn/test/test_torch_importer.cpp @@ -0,0 +1,128 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#if defined(ENABLE_TORCH_IMPORTER) && ENABLE_TORCH_IMPORTER +#if defined(ENABLE_TORCH_TESTS) && ENABLE_TORCH_TESTS +#include "test_precomp.hpp" + +namespace cvtest +{ + +using namespace std; +using namespace testing; +using namespace cv; +using namespace cv::dnn; + +template +static std::string _tf(TStr filename) +{ + return (getOpenCVExtraDir() + "/dnn/torch/") + filename; +} + +TEST(Torch_Importer, simple_read) +{ + Net net; + Ptr importer; + + ASSERT_NO_THROW( importer = createTorchImporter(_tf("net_simple_net.txt"), false) ); + ASSERT_TRUE( importer != NULL ); + importer->populateNet(net); +} + +static void runTorchNet(String prefix, String outLayerName, bool isBinary) +{ + String suffix = (isBinary) ? ".dat" : ".txt"; + + Net net; + Ptr importer = createTorchImporter(_tf(prefix + "_net" + suffix), isBinary); + ASSERT_TRUE(importer != NULL); + importer->populateNet(net); + + Blob inp, outRef; + ASSERT_NO_THROW( inp = readTorchBlob(_tf(prefix + "_input" + suffix), isBinary) ); + ASSERT_NO_THROW( outRef = readTorchBlob(_tf(prefix + "_output" + suffix), isBinary) ); + + net.setBlob(".0", inp); + net.forward(); + Blob out = net.getBlob(outLayerName); + + normAssert(outRef, out); +} + +TEST(Torch_Importer, run_convolution) +{ + runTorchNet("net_conv", "l1_Convolution", false); +} + +TEST(Torch_Importer, run_pool_max) +{ + runTorchNet("net_pool_max", "l1_Pooling", false); +} + +TEST(Torch_Importer, run_pool_ave) +{ + runTorchNet("net_pool_ave", "l1_Pooling", false); +} + +TEST(Torch_Importer, run_reshape) +{ + runTorchNet("net_reshape", "l1_Reshape", false); + runTorchNet("net_reshape_batch", "l1_Reshape", false); +} + +TEST(Torch_Importer, run_linear) +{ + runTorchNet("net_linear_2d", "l1_InnerProduct", false); +} + +TEST(Torch_Importer, run_paralel) +{ + runTorchNet("net_parallel", "l2_torchMerge", false); +} + +TEST(Torch_Importer, run_concat) +{ + runTorchNet("net_concat", "l2_torchMerge", false); +} + +} +#endif +#endif diff --git a/modules/dnn/testdata/dnn/layers/layer_convolution.prototxt b/modules/dnn/testdata/dnn/layers/layer_convolution.prototxt new file mode 100644 index 000000000..979d34352 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_convolution.prototxt @@ -0,0 +1,39 @@ +name: "test_Convolution" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "Convolution" + + convolution_param + { + group: 3 + num_output: 12 + + pad_h: 0 + pad_w: 1 + kernel_h: 4 + kernel_w: 5 + stride_h: 2 + stride_w: 3 + + weight_filler{ + type: 'uniform' + min: -1 + max: 1 + } + bias_filler { + type: 'uniform' + min: -1 + max: 1 + } + } + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/layer_deconvolution.prototxt b/modules/dnn/testdata/dnn/layers/layer_deconvolution.prototxt new file mode 100644 index 000000000..eb69b6a03 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_deconvolution.prototxt @@ -0,0 +1,39 @@ +name: "test_Convolution" +input: "input" + +input_dim: 2 +input_dim: 12 +input_dim: 36 +input_dim: 37 + +layer { + type: "Deconvolution" + + convolution_param + { + group: 3 + num_output: 12 + + pad_h: 0 + pad_w: 1 + kernel_h: 4 + kernel_w: 5 + stride_h: 2 + stride_w: 3 + + weight_filler{ + type: 'uniform' + min: -1 + max: 1 + } + bias_filler { + type: 'uniform' + min: -1 + max: 1 + } + } + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/layer_inner_product.prototxt b/modules/dnn/testdata/dnn/layers/layer_inner_product.prototxt new file mode 100644 index 000000000..459992500 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_inner_product.prototxt @@ -0,0 +1,32 @@ +name: "test_InnerProduct" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "InnerProduct" + + inner_product_param + { + axis: 3 + num_output: 2 + + weight_filler{ + type: 'uniform' + min: -1 + max: 1 + } + bias_filler { + type: 'uniform' + min: -1 + max: 1 + } + } + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/layer_lrn_channels.prototxt b/modules/dnn/testdata/dnn/layers/layer_lrn_channels.prototxt new file mode 100644 index 000000000..a8ec041c1 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_lrn_channels.prototxt @@ -0,0 +1,21 @@ +name: "test_LRN_channels" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "LRN" + lrn_param { + norm_region: ACROSS_CHANNELS; + local_size: 5 + alpha: 1.1 + beta: 0.75 + } + + name: "output" + bottom: "input" + top: "output" +} diff --git a/modules/dnn/testdata/dnn/layers/layer_lrn_spatial.prototxt b/modules/dnn/testdata/dnn/layers/layer_lrn_spatial.prototxt new file mode 100644 index 000000000..df88afbd5 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_lrn_spatial.prototxt @@ -0,0 +1,22 @@ +name: "test_LRN_spatial" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "LRN" + + lrn_param { + norm_region: WITHIN_CHANNEL; + local_size: 5 + alpha: 0.9 + beta: 0.75 + } + + name: "output" + bottom: "input" + top: "output" +} diff --git a/modules/dnn/testdata/dnn/layers/layer_mvn.prototxt b/modules/dnn/testdata/dnn/layers/layer_mvn.prototxt new file mode 100644 index 000000000..6753695d5 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_mvn.prototxt @@ -0,0 +1,21 @@ +name: "test_MVN_channels" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "MVN" + + mvn_param { + eps: 0.1 + across_channels: false + normalize_variance: true + } + + name: "output" + bottom: "input" + top: "output" +} diff --git a/modules/dnn/testdata/dnn/layers/layer_pooling_ave.prototxt b/modules/dnn/testdata/dnn/layers/layer_pooling_ave.prototxt new file mode 100644 index 000000000..95cff9aad --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_pooling_ave.prototxt @@ -0,0 +1,26 @@ +name: "test_Pooling_max" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "Pooling" + + pooling_param + { + pool: AVE + pad_h: 2 + pad_w: 1 + kernel_h: 3 + kernel_w: 5 + stride_h: 2 + stride_w: 1 + } + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/layer_pooling_max.prototxt b/modules/dnn/testdata/dnn/layers/layer_pooling_max.prototxt new file mode 100644 index 000000000..5c4f4155c --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_pooling_max.prototxt @@ -0,0 +1,26 @@ +name: "test_Pooling_max" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "Pooling" + + pooling_param + { + pool: MAX + pad_h: 2 + pad_w: 1 + kernel_h: 3 + kernel_w: 5 + stride_h: 2 + stride_w: 1 + } + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/layer_softmax.prototxt b/modules/dnn/testdata/dnn/layers/layer_softmax.prototxt new file mode 100644 index 000000000..3a717a4c6 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/layer_softmax.prototxt @@ -0,0 +1,15 @@ +name: "test_Softmax" +input: "input" + +input_dim: 2 +input_dim: 6 +input_dim: 75 +input_dim: 113 + +layer { + type: "Softmax" + + name: "output" + bottom: "input" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/reshape_and_slice_routines.prototxt b/modules/dnn/testdata/dnn/layers/reshape_and_slice_routines.prototxt new file mode 100644 index 000000000..9d02133b4 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/reshape_and_slice_routines.prototxt @@ -0,0 +1,77 @@ +name: "test_reshape_splice_split" +input: "input" + +layer{ + type: "Split" + name: "dummy_split" + bottom: "input" + top: "dummy_split_0" + top: "dummy_split_1" +} +layer{ + type: "Slice" + name: "dummy_slice_0" + bottom: "dummy_split_0" + slice_param{ + slice_point: 1 + slice_point: 2 + } + top: "dummy_slice_0_0" + top: "dummy_slice_0_1" + top: "dummy_slice_0_2" +} +layer{ + type: "Slice" + name: "dummy_slice_1" + bottom: "dummy_split_1" + slice_param{ + slice_point: 1 + slice_point: 2 + } + top: "dummy_slice_1_0" + top: "dummy_slice_1_1" + top: "dummy_slice_1_2" +} +layer{ + type: "Sigmoid" + name: "alter_sliced_split" + bottom: "dummy_slice_1_2" + top: "dummy_slice_1_2" +} +layer{ + type: "Concat" + name: "dummy_concat" + bottom: "dummy_slice_0_0" + bottom: "dummy_slice_1_1" + bottom: "dummy_slice_0_2" + top: "dummy_concat" +} +layer{ + type: "Reshape" + name: "dummy_reshape" + bottom: "dummy_concat" + reshape_param{ + shape{ + dim: 0 + dim: 1 + dim: 1 + dim: -1 + dim: 1 + } + axis: 1 + num_axes: 1 + } + top: "dummy_reshape" +} +layer{ + type: "Flatten" + name: "dummy_reshape_undo" + bottom: "dummy_reshape" + top: "dummy_reshape_undo" +} +layer{ + type: "Split" + name: "output" + bottom: "dummy_reshape_undo" + top: "output" +} \ No newline at end of file diff --git a/modules/dnn/testdata/dnn/layers/run.py b/modules/dnn/testdata/dnn/layers/run.py new file mode 100644 index 000000000..23d4117c9 --- /dev/null +++ b/modules/dnn/testdata/dnn/layers/run.py @@ -0,0 +1,45 @@ +# coding: utf-8 + +import sys, os, glob + +CAFFE_ROOT = "/home/vitaliy/opencv/caffe/" +sys.path.insert(0, CAFFE_ROOT + 'python') + +import numpy as np +import caffe +#import cv2 + +def get_cafe_output(inp_blob, proto_name, caffemodel_name): + caffe.set_mode_cpu() + net = caffe.Net(proto_name, caffe.TEST) + + #net.blobs['input'].reshape(*inp_blob.shape) + net.blobs['input'].data[...] = inp_blob + + net.forward() + out_blob = net.blobs['output'].data[...]; + + if net.params.get('output'): + print "Params count:", len(net.params['output']) + net.save(caffemodel_name) + + return out_blob + +if __name__ == '__main__': + proto_filenames = glob.glob("layer_*.prototxt") + + for proto_filename in proto_filenames: + proto_filename = os.path.basename(proto_filename) + proto_basename = os.path.splitext(proto_filename)[0] + cfmod_basename = proto_basename + ".caffemodel" + npy_filename = proto_basename + ".npy" + + inp_blob_name = proto_basename + ".input.npy" + inp_blob = np.load(inp_blob_name) if os.path.exists(inp_blob_name) else np.load('blob.npy') + + print "\nGenerate data for:" + print cfmod_basename, inp_blob.shape + + out_blob = get_cafe_output(inp_blob, proto_filename, cfmod_basename) + print out_blob.shape + np.save(npy_filename, out_blob) diff --git a/modules/dnn/testdata/dnn/torch/torch_gen_test_data.lua b/modules/dnn/testdata/dnn/torch/torch_gen_test_data.lua new file mode 100644 index 000000000..ae25caafd --- /dev/null +++ b/modules/dnn/testdata/dnn/torch/torch_gen_test_data.lua @@ -0,0 +1,67 @@ +import 'nn' + +function fill_net(net) + if net.modules then + for i = 1, #net.modules do + fill_net(net.modules[i]) + end + end + if net.weight then + net.weight = torch.rand(net.weight:size()) + end + if net.bias then + net.bias = torch.rand(net.bias:size()) + end +end + +function save(net, input, label) + fill_net(net) + output = net:forward(input) + + --torch.save(label .. '_net.dat', net) + torch.save(label .. '_net.txt', net, 'ascii') + --torch.save(label .. '_input.dat', input) + torch.save(label .. '_input.txt', input, 'ascii') + --torch.save(label .. '_output.dat', output) + torch.save(label .. '_output.txt', output, 'ascii') +end + +local net_simple = nn.Sequential() +net_simple:add(nn.ReLU()) +net_simple:add(nn.SpatialConvolution(3,64, 11,7, 3,4, 3,2)) +net_simple:add(nn.SpatialMaxPooling(4,5, 3,2, 1,2)) +net_simple:add(nn.Sigmoid()) +save(net_simple, torch.Tensor(2, 3, 25, 35), 'net_simple') + +local net_pool_max = nn.Sequential() +net_pool_max:add(nn.SpatialMaxPooling(4,5, 3,2, 1,2):ceil()) --TODO: add ceil and floor modes +save(net_pool_max, torch.rand(2, 3, 50, 30), 'net_pool_max') + +local net_pool_ave = nn.Sequential() +net_pool_ave:add(nn.SpatialAveragePooling(4,5, 2,1, 1,2)) +save(net_pool_ave, torch.rand(2, 3, 50, 30), 'net_pool_ave') + +local net_conv = nn.Sequential() +net_conv:add(nn.SpatialConvolution(3,64, 11,7, 3,4, 3,2)) +save(net_conv, torch.rand(1, 3, 50, 60), 'net_conv') + +local net_reshape = nn.Sequential() +net_reshape:add(nn.Reshape(5, 4, 3, 2)) +save(net_reshape, torch.rand(2, 3, 4, 5), 'net_reshape') + +local net_reshape_batch = nn.Sequential() +net_reshape_batch:add(nn.Reshape(5, 4, 3, true)) +save(net_reshape_batch, torch.rand(2, 3, 4, 5), 'net_reshape_batch') + +save(nn.Linear(7, 3), torch.rand(13, 7), 'net_linear_2d') + +local net_parallel = nn.Parallel(4, 2) +net_parallel:add(nn.Sigmoid()) +net_parallel:add(nn.Tanh()) +save(net_parallel, torch.rand(2, 6, 4, 2), 'net_parallel') + +local net_concat = nn.Concat(2) +net_concat:add(nn.ReLU()) +net_concat:add(nn.Tanh()) +net_concat:add(nn.Sigmoid()) +save(net_concat, torch.rand(2, 6, 4, 3) - 0.5, 'net_concat') diff --git a/modules/dnn/testdata/dnn/torch/torch_nn_echo.lua b/modules/dnn/testdata/dnn/torch/torch_nn_echo.lua new file mode 100644 index 000000000..46c258353 --- /dev/null +++ b/modules/dnn/testdata/dnn/torch/torch_nn_echo.lua @@ -0,0 +1,2 @@ +require 'nn' +print("nn module exists!") \ No newline at end of file diff --git a/modules/dnn/tutorials/images/build_1.png b/modules/dnn/tutorials/images/build_1.png new file mode 100644 index 000000000..855159e87 Binary files /dev/null and b/modules/dnn/tutorials/images/build_1.png differ diff --git a/modules/dnn/tutorials/images/build_2.png b/modules/dnn/tutorials/images/build_2.png new file mode 100644 index 000000000..6741e8ab6 Binary files /dev/null and b/modules/dnn/tutorials/images/build_2.png differ diff --git a/modules/dnn/tutorials/images/build_3.png b/modules/dnn/tutorials/images/build_3.png new file mode 100644 index 000000000..102d6e339 Binary files /dev/null and b/modules/dnn/tutorials/images/build_3.png differ diff --git a/modules/dnn/tutorials/images/build_4.png b/modules/dnn/tutorials/images/build_4.png new file mode 100644 index 000000000..3ad4df817 Binary files /dev/null and b/modules/dnn/tutorials/images/build_4.png differ diff --git a/modules/dnn/tutorials/images/build_5.png b/modules/dnn/tutorials/images/build_5.png new file mode 100644 index 000000000..bd187c6fb Binary files /dev/null and b/modules/dnn/tutorials/images/build_5.png differ diff --git a/modules/dnn/tutorials/images/space_shuttle.jpg b/modules/dnn/tutorials/images/space_shuttle.jpg new file mode 100644 index 000000000..412a91969 Binary files /dev/null and b/modules/dnn/tutorials/images/space_shuttle.jpg differ diff --git a/modules/dnn/tutorials/tutorial_dnn_build.markdown b/modules/dnn/tutorials/tutorial_dnn_build.markdown new file mode 100644 index 000000000..d5fbc7f6a --- /dev/null +++ b/modules/dnn/tutorials/tutorial_dnn_build.markdown @@ -0,0 +1,68 @@ +Build opencv_contrib with dnn module {#tutorial_dnn_build} +==================================== + +Introduction +------------ +opencv_dnn module is placed in the secondary [opencv_contrib](https://github.com/Itseez/opencv_contrib) repository, +which isn't distributed in binary form, therefore you need to build it manually. + +To do this you need to have installed: [CMake](http://www.cmake.org/download), git, and build system (*gcc* with *make* for Linux or *MS Visual Studio* for Windows) + +Steps +----- +-# Make any directory, for example **opencv_root** + +-# Clone [opencv](https://github.com/Itseez/opencv) and [opencv_contrib](https://github.com/Itseez/opencv_contrib) repos to the **opencv_root**. + You can do it in terminal like here: +@code +cd opencv_root +git clone https://github.com/Itseez/opencv +git clone https://github.com/Itseez/opencv_contrib +@endcode + +-# Run [CMake-gui] and set source and build directories: + + - Set source code directory to **opencv_root**/opencv; + + - Set binaries directory, for example, to **opencv_root**/build_opencv. + This directory will contain built libraries. + ![](images/build_1.png) + +-# Configure opencv: + - press *Configure*; + - choose the preferred project generator (Makefiles for Linux, MS Visual Studio for Windows); + - also you can set many opencv build options, for more details see @ref tutorial_linux_install. + ![](images/build_2.png) + +-# In the appeared list of build parameters find parameter `OPENCV_EXTRA_MODULES_PATH` and set it to the **opencv_root**/opencv_contrib. + ![](images/build_3.png) + +-# *Configure* the project again, and set build options of dnn module: + + - `BUILD_opencv_dnn` parameter must exist and be checked. + + - dnn module covers waste part of [Caffe](http://caffe.berkeleyvision.org) framework functionality. + However, to load Caffe networks libprotobuf is required. + You you can uncheck `BUILD_LIBPROTOBUF_FROM_SOURCES` flag to try use protobuf installed in your system. + Elsewise libpotobuf will be built from opencv sources. + + - You can additionally check `opencv_dnn_BUILD_TORCH_IMPORTER` parameter to build [Torch7](http://torch.ch/) importer. + It allows you to use networks, generated by [Torch7.nn](https://github.com/torch/nn/blob/master/README.md/) module. + ![](images/build_4.png) + +-# Press *Configure* and *Generate*. + ![](images/build_5.png) + +-# Build the generated project: + - If Makefiles generator on Unix was used, run the following in terminal: + @code + cd opencv_root/build_opencv + make all + @endcode + - If MS Visual Studio generator was used, then open OpenCV.sln from **opencv_root**/build_opencv folder in the Visual Studio, + and build it by choosing **Build** -> **Build Solution** menu or using **F7** short-cut. + +-# Now you can build own program by using libraries were built into **opencv_root**/build_opencv/lib. + See the following tutorials to learn how to create a program using OpenCV: + - @ref tutorial_windows_install + - @ref tutorial_linux_gcc_cmake \ No newline at end of file diff --git a/modules/dnn/tutorials/tutorial_dnn_googlenet.markdown b/modules/dnn/tutorials/tutorial_dnn_googlenet.markdown new file mode 100644 index 000000000..87b60acef --- /dev/null +++ b/modules/dnn/tutorials/tutorial_dnn_googlenet.markdown @@ -0,0 +1,66 @@ +Load Caffe framework models {#tutorial_dnn_googlenet} +=========================== + +Introduction +------------ + +In this tutorial you will learn how to use opencv_dnn module for image classification by using +GoogLeNet trained network from [Caffe model zoo](http://caffe.berkeleyvision.org/model_zoo.html). + +We will demonstrate results of this example on the following picture. +![Buran space shuttle](images/space_shuttle.jpg) + +Source Code +----------- + +We will be using snippets from the example application, that can be downloaded [here](https://github.com/ludv1x/opencv_contrib/blob/master/modules/dnn/samples/caffe_googlenet.cpp). + +@include dnn/samples/caffe_googlenet.cpp + +Explanation +----------- + +-# Firstly, download GoogLeNet model files: + [bvlc_googlenet.prototxt ](https://raw.githubusercontent.com/ludv1x/opencv_contrib/master/modules/dnn/samples/bvlc_googlenet.prototxt) and + [bvlc_googlenet.caffemodel](http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel) + + Also you need file with names of [ILSVRC2012](http://image-net.org/challenges/LSVRC/2012/browse-synsets) classes: + [synset_words.txt](https://raw.githubusercontent.com/ludv1x/opencv_contrib/master/modules/dnn/samples/synset_words.txt). + + Put these files into working dir of this program example. + +-# Create the importer of Caffe models + @snippet dnn/samples/caffe_googlenet.cpp Create the importer of Caffe model + +-# Create the network and initialize its by using the created importer + @snippet dnn/samples/caffe_googlenet.cpp Initialize network + +-# Read input image and convert to the blob, acceptable by GoogleNet + @snippet dnn/samples/caffe_googlenet.cpp Prepare blob + Firstly, we resize the image and change its channel sequence order. + + Now image is actually a 3-dimensional array with 224x224x3 shape. + + Next, we convert the image to 4-dimensional blob (so-called batch) with 1x2x224x224 shape by using special @ref cv::dnn::Blob constructor. + +-# Pass the blob to the network + @snippet dnn/samples/caffe_googlenet.cpp Set input blob + In bvlc_googlenet.prototxt the network input blob named as "data", therefore this blob labeled as ".data" in opencv_dnn API. + + Other blobs labeled as "name_of_layer.name_of_layer_output". + +-# Make forward pass + @snippet dnn/samples/caffe_googlenet.cpp Make forward pass + During the forward pass output of each network layer is computed, but in this example we need output from "prob" layer only. + +-# Determine the best class + @snippet dnn/samples/caffe_googlenet.cpp Gather output + We put the output of "prob" layer, which contain probabilities for each of 1000 ILSVRC2012 image classes, to the `prob` blob. + And find the index of element with maximal value in this one. This index correspond to the class of the image. + +-# Print results + @snippet dnn/samples/caffe_googlenet.cpp Print results + For our image we get: +> Best class: #812 'space shuttle' +> +> Probability: 99.6378% \ No newline at end of file diff --git a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp index c8d32f142..65c439581 100644 --- a/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp +++ b/modules/line_descriptor/include/opencv2/line_descriptor/descriptor.hpp @@ -143,6 +143,30 @@ struct CV_EXPORTS KeyLine /** number of pixels covered by the line */ int numOfPixels; + /** Returns the start point of the line in the original image */ + Point2f getStartPoint() const + { + return Point2f(startPointX, startPointY); + } + + /** Returns the end point of the line in the original image */ + Point2f getEndPoint() const + { + return Point2f(endPointX, endPointY); + } + + /** Returns the start point of the line in the octave it was extracted from */ + Point2f getStartPointInOctave() const + { + return Point2f(sPointInOctaveX, sPointInOctaveY); + } + + /** Returns the end point of the line in the octave it was extracted from */ + Point2f getEndPointInOctave() const + { + return Point2f(ePointInOctaveX, ePointInOctaveY); + } + /** constructor */ KeyLine() { diff --git a/modules/line_descriptor/src/LSDDetector.cpp b/modules/line_descriptor/src/LSDDetector.cpp index e5e30a738..1061291f5 100644 --- a/modules/line_descriptor/src/LSDDetector.cpp +++ b/modules/line_descriptor/src/LSDDetector.cpp @@ -179,7 +179,7 @@ void LSDDetector::detectImpl( const Mat& imageSrc, std::vector& keyline kl.sPointInOctaveY = (float) extremes[1]; kl.ePointInOctaveX = (float) extremes[2]; kl.ePointInOctaveY = (float) extremes[3]; - kl.lineLength = (float) sqrt( pow( extremes[0] - extremes[2], 2 ) + pow( extremes[1] - extremes[3], 2 ) ); + kl.lineLength = (float) sqrt( pow( (float) extremes[0] - extremes[2], 2 ) + pow( (float) extremes[1] - extremes[3], 2 ) ); /* compute number of pixels covered by line */ LineIterator li( gaussianPyrs[j], Point( extremes[0], extremes[1] ), Point( extremes[2], extremes[3] ) ); diff --git a/modules/line_descriptor/src/binary_descriptor.cpp b/modules/line_descriptor/src/binary_descriptor.cpp index f409d1f50..16f124992 100644 --- a/modules/line_descriptor/src/binary_descriptor.cpp +++ b/modules/line_descriptor/src/binary_descriptor.cpp @@ -653,7 +653,7 @@ void BinaryDescriptor::computeImpl( const Mat& imageSrc, std::vector& k uchar* pointerToRow = descriptors.ptr( originalIndex ); /* get LBD data */ - float* desVec = sl[k][lineC].descriptor.data(); + float* desVec = &sl[k][lineC].descriptor.front(); /* fill current row with binary descriptor */ for ( int comb = 0; comb < 32; comb++ ) @@ -692,7 +692,7 @@ int BinaryDescriptor::OctaveKeyLines( cv::Mat& image, ScaleLines &keyLines ) /* sigma values and reduction factor used in Gaussian pyramids */ float preSigma2 = 0; //orignal image is not blurred, has zero sigma; float curSigma2 = 1.0; //[sqrt(2)]^0=1; - double factor = sqrt( 2 ); //the down sample factor between connective two octave images + double factor = sqrt( 2.0 ); //the down sample factor between connective two octave images /* loop over number of octaves */ for ( int octaveCount = 0; octaveCount < params.numOfOctave_; octaveCount++ ) @@ -1241,7 +1241,7 @@ int BinaryDescriptor::computeLBD( ScaleLines &keyLines, bool useDetectionData ) /* construct line descriptor */ pSingleLine->descriptor.resize( descriptor_size ); - desVec = pSingleLine->descriptor.data(); + desVec = &pSingleLine->descriptor.front(); short desID; @@ -1280,7 +1280,7 @@ int BinaryDescriptor::computeLBD( ScaleLines &keyLines, bool useDetectionData ) float tempM, tempS; tempM = 0; tempS = 0; - desVec = pSingleLine->descriptor.data(); + desVec = &pSingleLine->descriptor.front(); int base = 0; for ( short i = 0; i < (short) ( NUM_OF_BANDS * 8 ); ++base, i = (short) ( base * 8 ) ) @@ -1297,7 +1297,7 @@ int BinaryDescriptor::computeLBD( ScaleLines &keyLines, bool useDetectionData ) tempM = 1 / sqrt( tempM ); tempS = 1 / sqrt( tempS ); - desVec = pSingleLine->descriptor.data(); + desVec = &pSingleLine->descriptor.front(); base = 0; for ( short i = 0; i < (short) ( NUM_OF_BANDS * 8 ); ++base, i = (short) ( base * 8 ) ) { @@ -1315,7 +1315,7 @@ int BinaryDescriptor::computeLBD( ScaleLines &keyLines, bool useDetectionData ) * a threshold is used to limit the value of element in the unit feature * vector no larger than this threshold. In Z.Wang's work, a value of 0.4 is found * empirically to be a proper threshold.*/ - desVec = pSingleLine->descriptor.data(); + desVec = &pSingleLine->descriptor.front(); for ( short i = 0; i < descriptor_size; i++ ) { if( desVec[i] > 0.4 ) @@ -1344,7 +1344,7 @@ int BinaryDescriptor::computeLBD( ScaleLines &keyLines, bool useDetectionData ) for ( int g = 0; g < 32; g++ ) { /* get LBD data */ - float* des_Vec = keyLines[lineIDInScaleVec][0].descriptor.data(); + float* des_Vec = &keyLines[lineIDInScaleVec][0].descriptor.front(); *pointerToRow = des_Vec[g]; pointerToRow++; @@ -2204,9 +2204,9 @@ int BinaryDescriptor::EDLineDetector::EdgeDrawing( cv::Mat &image, EdgeChains &e edgeChains.xCors.resize( offsetPFirst + offsetPSecond ); edgeChains.yCors.resize( offsetPFirst + offsetPSecond ); edgeChains.sId.resize( offsetPS + 1 ); - unsigned int *pxCors = edgeChains.xCors.data(); - unsigned int *pyCors = edgeChains.yCors.data(); - unsigned int *psId = edgeChains.sId.data(); + unsigned int *pxCors = &edgeChains.xCors.front(); + unsigned int *pyCors = &edgeChains.yCors.front(); + unsigned int *psId = &edgeChains.sId.front(); offsetPFirst = 0; offsetPSecond = 0; unsigned int indexInCors = 0; @@ -2252,12 +2252,12 @@ int BinaryDescriptor::EDLineDetector::EDline( cv::Mat &image, LineChains &lines lines.xCors.resize( linePixelID ); lines.yCors.resize( linePixelID ); lines.sId.resize( 5 * edges.numOfEdges ); - unsigned int *pEdgeXCors = edges.xCors.data(); - unsigned int *pEdgeYCors = edges.yCors.data(); - unsigned int *pEdgeSID = edges.sId.data(); - unsigned int *pLineXCors = lines.xCors.data(); - unsigned int *pLineYCors = lines.yCors.data(); - unsigned int *pLineSID = lines.sId.data(); + unsigned int *pEdgeXCors = &edges.xCors.front(); + unsigned int *pEdgeYCors = &edges.yCors.front(); + unsigned int *pEdgeSID = &edges.sId.front(); + unsigned int *pLineXCors = &lines.xCors.front(); + unsigned int *pLineYCors = &lines.yCors.front(); + unsigned int *pLineSID = &lines.sId.front(); logNT_ = 2.0 * ( log10( (double) imageWidth ) + log10( (double) imageHeight ) ); double lineFitErr = 0; //the line fit error; std::vector lineEquation( 2, 0 ); @@ -2732,9 +2732,9 @@ int BinaryDescriptor::EDLineDetector::EDline( cv::Mat &image ) lineSalience_.resize( lines_.numOfLines ); unsigned char *pgImg = gImgWO_.ptr(); unsigned int indexInLineArray; - unsigned int *pXCor = lines_.xCors.data(); - unsigned int *pYCor = lines_.yCors.data(); - unsigned int *pSID = lines_.sId.data(); + unsigned int *pXCor = &lines_.xCors.front(); + unsigned int *pYCor = &lines_.yCors.front(); + unsigned int *pSID = &lines_.sId.front(); for ( unsigned int i = 0; i < lineSalience_.size(); i++ ) { int salience = 0; diff --git a/modules/line_descriptor/src/bitarray.hpp b/modules/line_descriptor/src/bitarray.hpp index 3353ea56d..d5cd764e6 100644 --- a/modules/line_descriptor/src/bitarray.hpp +++ b/modules/line_descriptor/src/bitarray.hpp @@ -43,7 +43,7 @@ #ifndef __OPENCV_BITARRAY_HPP #define __OPENCV_BITARRAY_HPP -#ifdef _WIN32 +#ifdef _MSC_VER #pragma warning( disable : 4267 ) #endif diff --git a/modules/line_descriptor/src/bitops.hpp b/modules/line_descriptor/src/bitops.hpp index 02ccb98cb..2b5d62474 100644 --- a/modules/line_descriptor/src/bitops.hpp +++ b/modules/line_descriptor/src/bitops.hpp @@ -45,7 +45,7 @@ #include "precomp.hpp" -#ifdef _WIN32 +#ifdef _MSC_VER # include # define popcnt __popcnt # pragma warning( disable : 4267 ) diff --git a/modules/line_descriptor/src/draw.cpp b/modules/line_descriptor/src/draw.cpp index bfd1680a2..1319c4767 100644 --- a/modules/line_descriptor/src/draw.cpp +++ b/modules/line_descriptor/src/draw.cpp @@ -166,7 +166,7 @@ void drawKeylines( const Mat& image, const std::vector& keylines, Mat& { /* decide lines' color */ Scalar lineColor; - if( color != Scalar::all( -1 ) ) + if( color == Scalar::all( -1 ) ) { int R = ( rand() % (int) ( 255 + 1 ) ); int G = ( rand() % (int) ( 255 + 1 ) ); diff --git a/modules/line_descriptor/src/precomp.hpp b/modules/line_descriptor/src/precomp.hpp index c9406b7e1..189fba2ee 100644 --- a/modules/line_descriptor/src/precomp.hpp +++ b/modules/line_descriptor/src/precomp.hpp @@ -42,7 +42,7 @@ #ifndef __OPENCV_PRECOMP_H__ #define __OPENCV_PRECOMP_H__ -#ifdef _WIN32 +#ifdef _MSC_VER #pragma warning( disable : 4267 ) #endif diff --git a/modules/line_descriptor/src/types.hpp b/modules/line_descriptor/src/types.hpp index 7a80a82a5..80a17f094 100644 --- a/modules/line_descriptor/src/types.hpp +++ b/modules/line_descriptor/src/types.hpp @@ -49,7 +49,7 @@ #ifndef __OPENCV_TYPES_HPP #define __OPENCV_TYPES_HPP -#ifdef _WIN32 +#ifdef _MSC_VER #pragma warning( disable : 4267 ) #endif diff --git a/modules/matlab/CMakeLists.txt b/modules/matlab/CMakeLists.txt index 8c1382b53..18ffcc366 100644 --- a/modules/matlab/CMakeLists.txt +++ b/modules/matlab/CMakeLists.txt @@ -101,7 +101,6 @@ string(REGEX REPLACE "(\r?\n)+$" "" GIT_COMMIT "${GIT_COMMIT}") # set the path to the C++ header and doc parser, and template engine set(JINJA2_PATH ${CMAKE_SOURCE_DIR}/3rdparty) set(HDR_PARSER_PATH ${CMAKE_SOURCE_DIR}/modules/python/src2) -set(RST_PARSER_PATH ${CMAKE_SOURCE_DIR}/modules/java/generator) # set mex compiler options prepend("-I" MEX_INCLUDE_DIRS ${CMAKE_BINARY_DIR}) @@ -158,7 +157,6 @@ if (NOT MEX_WORKS) ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py --jinja2 ${JINJA2_PATH} --hdrparser ${HDR_PARSER_PATH} - --rstparser ${RST_PARSER_PATH} --extra "test=${CMAKE_CURRENT_SOURCE_DIR}/test/test_generator.hpp" --outdir ${CMAKE_BINARY_DIR}/junk ERROR_VARIABLE GEN_ERROR @@ -218,7 +216,6 @@ add_custom_command( ${CMAKE_CURRENT_SOURCE_DIR}/generator/gen_matlab.py --jinja2 ${JINJA2_PATH} --hdrparser ${HDR_PARSER_PATH} - --rstparser ${RST_PARSER_PATH} --moduleroot ${CMAKE_SOURCE_DIR}/modules ${OPENCV_EXTRA_MODULES_PATH} --modules ${opencv_modules} --extra ${opencv_extra_hdrs} diff --git a/modules/matlab/README.md b/modules/matlab/README.md index 42237eccf..307fab84e 100644 --- a/modules/matlab/README.md +++ b/modules/matlab/README.md @@ -9,6 +9,8 @@ The Matlab code generator is fully integrated into the OpenCV build system. If c cmake -DMATLAB_ROOT_DIR=/Applications/MATLAB_R2013a.app .. +If you prefer using the gui version of cmake (cmake-gui), you can use the *Add Entry* option in the GUI to manually add the *path* variable `MATLAB_ROOT_DIR`. + Install ------- diff --git a/modules/matlab/generator/gen_matlab.py b/modules/matlab/generator/gen_matlab.py index e79441ea1..218505a61 100644 --- a/modules/matlab/generator/gen_matlab.py +++ b/modules/matlab/generator/gen_matlab.py @@ -29,19 +29,12 @@ class MatlabWrapperGenerator(object): # dynamically import the parsers from jinja2 import Environment, FileSystemLoader import hdr_parser - import rst_parser # parse each of the files and store in a dictionary # as a separate "namespace" parser = hdr_parser.CppHeaderParser() - rst = rst_parser.RstParser(parser) - rst_parser.verbose = False - rst_parser.show_warnings = False - rst_parser.show_errors = False - rst_parser.show_critical_errors = False ns = dict((key, []) for key in modules) - doc = dict((key, []) for key in modules) path_template = Template('${module}/include/opencv2/${module}.hpp') for module in modules: @@ -55,10 +48,6 @@ class MatlabWrapperGenerator(object): # parse the definitions ns[module] = parser.parse(header) - # parse the documentation - rst.parse(module, os.path.join(module_root, module)) - doc[module] = rst.definitions - rst.definitions = {} for extra in extras: module = extra.split("=")[0] @@ -97,7 +86,6 @@ class MatlabWrapperGenerator(object): tfunction = jtemplate.get_template('template_function_base.cpp') tclassm = jtemplate.get_template('template_class_base.m') tclassc = jtemplate.get_template('template_class_base.cpp') - tdoc = jtemplate.get_template('template_doc_base.m') tconst = jtemplate.get_template('template_map_base.m') # create the build directory @@ -121,10 +109,6 @@ class MatlabWrapperGenerator(object): populated = tfunction.render(fun=method, time=time, includes=namespace.name) with open(output_source_dir+'/'+method.name+'.cpp', 'wb') as f: f.write(populated.encode('utf-8')) - if namespace.name in doc and method.name in doc[namespace.name]: - populated = tdoc.render(fun=method, doc=doc[namespace.name][method.name], time=time) - with open(output_class_dir+'/'+method.name+'.m', 'wb') as f: - f.write(populated.encode('utf-8')) # classes for clss in namespace.classes: # cpp converter @@ -147,7 +131,6 @@ if __name__ == "__main__": """ Usage: python gen_matlab.py --jinja2 /path/to/jinja2/engine --hdrparser /path/to/hdr_parser/dir - --rstparser /path/to/rst_parser/dir --moduleroot [ /path/to/opencv/modules /path/to/opencv_contrib/modules etc ] --modules [core imgproc objdetect etc] --extra namespace=/path/to/extra/header.hpp @@ -158,8 +141,7 @@ if __name__ == "__main__": 1. constructs the headers to parse from the module root and list of modules 2. parses the headers using CppHeaderParser 3. refactors the definitions using ParseTree - 4. parses .rst docs using RstParser - 5. populates the templates for classes, function, enums and docs from the + 4. populates the templates for classes, function, enums from the definitions gen_matlab.py requires the following inputs: @@ -167,8 +149,6 @@ if __name__ == "__main__": e.g. ${CMAKE_SOURCE_DIR}/3rdparty --hdrparser the path to the header parser directory (opencv/modules/python/src2) - --rstparser the path to the rst parser directory - (opencv/modules/java/generator) --moduleroot (optional) paths to the opencv directories containing the modules --modules (optional - required if --moduleroot specified) the modules to produce bindings for. The path to the include directories @@ -187,17 +167,15 @@ if __name__ == "__main__": parser = ArgumentParser() parser.add_argument('--jinja2') parser.add_argument('--hdrparser') - parser.add_argument('--rstparser') parser.add_argument('--moduleroot', nargs='*', default=[], required=False) parser.add_argument('--modules', nargs='*', default=[], required=False) parser.add_argument('--extra', nargs='*', default=[], required=False) parser.add_argument('--outdir') args = parser.parse_args() - # add the hdr_parser and rst_parser modules to the path + # add the hdr_parser module to the path sys.path.append(args.jinja2) sys.path.append(args.hdrparser) - sys.path.append(args.rstparser) # create the generator mwg = MatlabWrapperGenerator() diff --git a/modules/optflow/CMakeLists.txt b/modules/optflow/CMakeLists.txt index 9887a3828..41029bcf4 100644 --- a/modules/optflow/CMakeLists.txt +++ b/modules/optflow/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Optical Flow Algorithms") -ocv_define_module(optflow opencv_core opencv_imgproc opencv_video opencv_highgui WRAP python) +ocv_define_module(optflow opencv_core opencv_imgproc opencv_video opencv_highgui opencv_ximgproc WRAP python) diff --git a/modules/optflow/include/opencv2/optflow.hpp b/modules/optflow/include/opencv2/optflow.hpp index a01b0c8ff..667adcb6a 100644 --- a/modules/optflow/include/opencv2/optflow.hpp +++ b/modules/optflow/include/opencv2/optflow.hpp @@ -109,7 +109,30 @@ CV_EXPORTS_W void calcOpticalFlowSF( InputArray from, InputArray to, OutputArray double sigma_dist, double sigma_color, int postprocess_window, double sigma_dist_fix, double sigma_color_fix, double occ_thr, int upscale_averaging_radius, double upscale_sigma_dist, - double upscale_sigma_color, double speed_up_thr ); + double upscale_sigma_color, double speed_up_thr ); + +/** @brief Fast dense optical flow based on PyrLK sparse matches interpolation. + +@param from first 8-bit 3-channel or 1-channel image. +@param to second 8-bit 3-channel or 1-channel image of the same size as from +@param flow computed flow image that has the same size as from and CV_32FC2 type +@param grid_step stride used in sparse match computation. Lower values usually + result in higher quality but slow down the algorithm. +@param k number of nearest-neighbor matches considered, when fitting a locally affine + model. Lower values can make the algorithm noticeably faster at the cost of + some quality degradation. +@param sigma parameter defining how fast the weights decrease in the locally-weighted affine + fitting. Higher values can help preserve fine details, lower values can help to get rid + of the noise in the output flow. +@param use_post_proc defines whether the ximgproc::fastGlobalSmootherFilter() is used + for post-processing after interpolation +@param fgs_lambda see the respective parameter of the ximgproc::fastGlobalSmootherFilter() +@param fgs_sigma see the respective parameter of the ximgproc::fastGlobalSmootherFilter() + */ +CV_EXPORTS_W void calcOpticalFlowSparseToDense ( InputArray from, InputArray to, OutputArray flow, + int grid_step = 8, int k = 128, float sigma = 0.05f, + bool use_post_proc = true, float fgs_lambda = 500.0f, + float fgs_sigma = 1.5f ); /** @brief Read a .flo file @@ -165,6 +188,9 @@ CV_EXPORTS_W Ptr createOptFlow_SimpleFlow(); //! Additional interface to the Farneback's algorithm - calcOpticalFlowFarneback() CV_EXPORTS_W Ptr createOptFlow_Farneback(); +//! Additional interface to the SparseToDenseFlow algorithm - calcOpticalFlowSparseToDense() +CV_EXPORTS_W Ptr createOptFlow_SparseToDense(); + //! @} } //optflow diff --git a/modules/optflow/samples/optical_flow_evaluation.cpp b/modules/optflow/samples/optical_flow_evaluation.cpp index c65412a3e..4ecc798d5 100644 --- a/modules/optflow/samples/optical_flow_evaluation.cpp +++ b/modules/optflow/samples/optical_flow_evaluation.cpp @@ -10,7 +10,7 @@ using namespace optflow; const String keys = "{help h usage ? | | print this message }" "{@image1 | | image1 }" "{@image2 | | image2 }" - "{@algorithm | | [farneback, simpleflow, tvl1 or deepflow] }" + "{@algorithm | | [farneback, simpleflow, tvl1, deepflow or sparsetodenseflow] }" "{@groundtruth | | path to the .flo file (optional), Middlebury format }" "{m measure |endpoint| error measure - [endpoint or angular] }" "{r region |all | region to compute stats about [all, discontinuities, untextured] }" @@ -249,6 +249,8 @@ int main( int argc, char** argv ) algorithm = createOptFlow_DualTVL1(); else if ( method == "deepflow" ) algorithm = createOptFlow_DeepFlow(); + else if ( method == "sparsetodenseflow" ) + algorithm = createOptFlow_SparseToDense(); else { printf("Wrong method!\n"); diff --git a/modules/optflow/src/deepflow.cpp b/modules/optflow/src/deepflow.cpp index 9e2fa3a63..284061a4c 100644 --- a/modules/optflow/src/deepflow.cpp +++ b/modules/optflow/src/deepflow.cpp @@ -152,7 +152,7 @@ Mat OpticalFlowDeepFlow::warpImage( const Mat input, const Mat flow ) pMapY[i] = j + pFlow[2 * i + 1]; } } - remap(input, output, mapX, mapY, interpolationType, BORDER_TRANSPARENT); + remap(input, output, mapX, mapY, interpolationType); return output; } void OpticalFlowDeepFlow::calc( InputArray _I0, InputArray _I1, InputOutputArray _flow ) diff --git a/modules/optflow/src/interfaces.cpp b/modules/optflow/src/interfaces.cpp index df510ebc3..d2830eb14 100644 --- a/modules/optflow/src/interfaces.cpp +++ b/modules/optflow/src/interfaces.cpp @@ -177,5 +177,42 @@ Ptr createOptFlow_Farneback() { return makePtr(); } + +class OpticalFlowSparseToDense : public DenseOpticalFlow +{ +public: + OpticalFlowSparseToDense(int _grid_step, int _k, float _sigma, bool _use_post_proc, float _fgs_lambda, float _fgs_sigma); + void calc(InputArray I0, InputArray I1, InputOutputArray flow); + void collectGarbage(); +protected: + int grid_step; + int k; + float sigma; + bool use_post_proc; + float fgs_lambda; + float fgs_sigma; +}; + +OpticalFlowSparseToDense::OpticalFlowSparseToDense(int _grid_step, int _k, float _sigma, bool _use_post_proc, float _fgs_lambda, float _fgs_sigma) +{ + grid_step = _grid_step; + k = _k; + sigma = _sigma; + use_post_proc = _use_post_proc; + fgs_lambda = _fgs_lambda; + fgs_sigma = _fgs_sigma; +} + +void OpticalFlowSparseToDense::calc(InputArray I0, InputArray I1, InputOutputArray flow) +{ + calcOpticalFlowSparseToDense(I0,I1,flow,grid_step,k,sigma,use_post_proc,fgs_lambda,fgs_sigma); +} + +void OpticalFlowSparseToDense::collectGarbage() {} + +Ptr createOptFlow_SparseToDense() +{ + return makePtr(8,128,0.05f,true,500.0f,1.5f); +} } } diff --git a/modules/optflow/src/motempl.cpp b/modules/optflow/src/motempl.cpp index 738c87964..ec1801311 100644 --- a/modules/optflow/src/motempl.cpp +++ b/modules/optflow/src/motempl.cpp @@ -62,7 +62,7 @@ static bool ocl_updateMotionHistory( InputArray _silhouette, InputOutputArray _m k.args(ocl::KernelArg::ReadOnlyNoSize(silh), ocl::KernelArg::ReadWrite(mhi), timestamp, delbound); - size_t globalsize[2] = { silh.cols, silh.rows }; + size_t globalsize[2] = { (size_t)silh.cols, (size_t)silh.rows }; return k.run(2, globalsize, NULL, false); } diff --git a/modules/optflow/src/sparsetodenseflow.cpp b/modules/optflow/src/sparsetodenseflow.cpp new file mode 100644 index 000000000..ad896b228 --- /dev/null +++ b/modules/optflow/src/sparsetodenseflow.cpp @@ -0,0 +1,112 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "precomp.hpp" +#include "opencv2/ximgproc/sparse_match_interpolator.hpp" +using namespace std; + +namespace cv { +namespace optflow { + +CV_EXPORTS_W void calcOpticalFlowSparseToDense(InputArray from, InputArray to, OutputArray flow, + int grid_step, int k, + float sigma, bool use_post_proc, + float fgs_lambda, float fgs_sigma) +{ + CV_Assert( grid_step>1 && k>3 && sigma>0.0001f && fgs_lambda>1.0f && fgs_sigma>0.01f ); + CV_Assert( !from.empty() && from.depth() == CV_8U && (from.channels() == 3 || from.channels() == 1) ); + CV_Assert( !to .empty() && to .depth() == CV_8U && (to .channels() == 3 || to .channels() == 1) ); + CV_Assert( from.sameSize(to) ); + + Mat prev = from.getMat(); + Mat cur = to.getMat(); + Mat prev_grayscale, cur_grayscale; + + while( (prev.cols/grid_step)*(prev.rows/grid_step) > SHRT_MAX ) //ensure that the number matches is not too big + grid_step*=2; + + if(prev.channels()==3) + { + cvtColor(prev,prev_grayscale,COLOR_BGR2GRAY); + cvtColor(cur, cur_grayscale, COLOR_BGR2GRAY); + } + else + { + prev.copyTo(prev_grayscale); + cur .copyTo(cur_grayscale); + } + + vector points; + vector dst_points; + vector status; + vector err; + vector points_filtered, dst_points_filtered; + + for(int i=0;i gd = ximgproc::createEdgeAwareInterpolator(); + gd->setK(k); + gd->setSigma(sigma); + gd->setUsePostProcessing(use_post_proc); + gd->setFGSLambda(fgs_lambda); + gd->setFGSSigma (fgs_sigma); + gd->interpolate(prev,points_filtered,cur,dst_points_filtered,dense_flow); +} + +} +} \ No newline at end of file diff --git a/modules/optflow/test/test_sparsetodenseflow.cpp b/modules/optflow/test/test_sparsetodenseflow.cpp new file mode 100644 index 000000000..a8d645d30 --- /dev/null +++ b/modules/optflow/test/test_sparsetodenseflow.cpp @@ -0,0 +1,146 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of Intel Corporation may not 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 Intel Corporation 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. +// +//M*/ + +#include "test_precomp.hpp" + +#include + +using namespace std; +using namespace cv; + +/* ///////////////////// sparsetodenseflow_test ///////////////////////// */ + +class CV_SparseToDenseFlowTest : public cvtest::BaseTest +{ +protected: + void run(int); +}; + +static bool isFlowCorrect(float u) { + return !cvIsNaN(u) && (fabs(u) < 1e9); +} + +static float calc_rmse(Mat flow1, Mat flow2) { + float sum = 0; + int counter = 0; + const int rows = flow1.rows; + const int cols = flow1.cols; + + for (int y = 0; y < rows; ++y) { + for (int x = 0; x < cols; ++x) { + Vec2f flow1_at_point = flow1.at(y, x); + Vec2f flow2_at_point = flow2.at(y, x); + + float u1 = flow1_at_point[0]; + float v1 = flow1_at_point[1]; + float u2 = flow2_at_point[0]; + float v2 = flow2_at_point[1]; + + if (isFlowCorrect(u1) && isFlowCorrect(u2) && isFlowCorrect(v1) && isFlowCorrect(v2)) { + sum += (u1-u2)*(u1-u2) + (v1-v2)*(v1-v2); + counter++; + } + } + } + return (float)sqrt(sum / (1e-9 + counter)); +} + +void CV_SparseToDenseFlowTest::run(int) { + const float MAX_RMSE = 0.6f; + const string frame1_path = ts->get_data_path() + "optflow/RubberWhale1.png"; + const string frame2_path = ts->get_data_path() + "optflow/RubberWhale2.png"; + const string gt_flow_path = ts->get_data_path() + "optflow/RubberWhale.flo"; + + Mat frame1 = imread(frame1_path); + Mat frame2 = imread(frame2_path); + + if (frame1.empty()) { + ts->printf(cvtest::TS::LOG, "could not read image %s\n", frame2_path.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + if (frame2.empty()) { + ts->printf(cvtest::TS::LOG, "could not read image %s\n", frame2_path.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + if (frame1.rows != frame2.rows && frame1.cols != frame2.cols) { + ts->printf(cvtest::TS::LOG, "images should be of equal sizes (%s and %s)", + frame1_path.c_str(), frame2_path.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + if (frame1.type() != 16 || frame2.type() != 16) { + ts->printf(cvtest::TS::LOG, "images should be of equal type CV_8UC3 (%s and %s)", + frame1_path.c_str(), frame2_path.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + Mat flow_gt = optflow::readOpticalFlow(gt_flow_path); + if(flow_gt.empty()) { + ts->printf(cvtest::TS::LOG, "error while reading flow data from file %s", + gt_flow_path.c_str()); + ts->set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + return; + } + + Mat flow; + optflow::calcOpticalFlowSparseToDense(frame1, frame2, flow); + + float rmse = calc_rmse(flow_gt, flow); + + ts->printf(cvtest::TS::LOG, "Optical flow estimation RMSE for SparseToDenseFlow algorithm : %lf\n", + rmse); + + if (rmse > MAX_RMSE) { + ts->printf( cvtest::TS::LOG, + "Too big rmse error : %lf ( >= %lf )\n", rmse, MAX_RMSE); + ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); + return; + } +} + + +TEST(Video_OpticalFlowSparseToDenseFlow, accuracy) { CV_SparseToDenseFlowTest test; test.safe_run(); } diff --git a/modules/saliency/src/motionSaliencyBinWangApr2014.cpp b/modules/saliency/src/motionSaliencyBinWangApr2014.cpp index ed244f1a5..a83f9295b 100644 --- a/modules/saliency/src/motionSaliencyBinWangApr2014.cpp +++ b/modules/saliency/src/motionSaliencyBinWangApr2014.cpp @@ -39,6 +39,7 @@ // //M*/ +#include #include "precomp.hpp" //TODO delete highgui include //#include @@ -81,7 +82,7 @@ bool MotionSaliencyBinWangApr2014::init() // Since data is even, the median is estimated using two values ​​that occupy // the position (n / 2) and ((n / 2) +1) (choose their arithmetic mean). - potentialBackground = Mat( imgSize.height, imgSize.width, CV_32FC2, Scalar( NAN, 0 ) ); + potentialBackground = Mat( imgSize.height, imgSize.width, CV_32FC2, Scalar( std::numeric_limits::quiet_NaN(), 0 ) ); backgroundModel.resize( K + 1 ); @@ -89,7 +90,7 @@ bool MotionSaliencyBinWangApr2014::init() { Mat* tmpm = new Mat; tmpm->create( imgSize.height, imgSize.width, CV_32FC2 ); - tmpm->setTo( Scalar( NAN, 0 ) ); + tmpm->setTo( Scalar( std::numeric_limits::quiet_NaN(), 0 ) ); Ptr tmp = Ptr( tmpm ); backgroundModel[i] = tmp; } @@ -418,50 +419,50 @@ bool MotionSaliencyBinWangApr2014::templateReplacement( const Mat& finalBFMask, if( i > 0 && j > 0 && i < ( backgroundModel[z]->rows - 1 ) && j < ( backgroundModel[z]->cols - 1 ) ) { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( j - (int) floor( roiSize / 2 ), i - (int) floor( roiSize / 2 ), roiSize, roiSize ) ); + backgroundModelROI = mv[0]( Rect( j - (int) floor((float) roiSize / 2 ), i - (int) floor((float) roiSize / 2 ), roiSize, roiSize ) ); } else if( i == 0 && j == 0 ) // upper leftt { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( j, i, (int) ceil( roiSize / 2 ), (int) ceil( roiSize / 2 ) ) ); + backgroundModelROI = mv[0]( Rect( j, i, (int) ceil((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ) ) ); } else if( j == 0 && i > 0 && i < ( backgroundModel[z]->rows - 1 ) ) // middle left { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( j, i - (int) floor( roiSize / 2 ), (int) ceil( roiSize / 2 ), roiSize ) ); + backgroundModelROI = mv[0]( Rect( j, i - (int) floor((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ), roiSize ) ); } else if( i == ( backgroundModel[z]->rows - 1 ) && j == 0 ) //down left { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( j, i - (int) floor( roiSize / 2 ), (int) ceil( roiSize / 2 ), (int) ceil( roiSize / 2 ) ) ); + backgroundModelROI = mv[0]( Rect( j, i - (int) floor((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ) ) ); } else if( i == 0 && j > 0 && j < ( backgroundModel[z]->cols - 1 ) ) // upper - middle { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( ( j - (int) floor( roiSize / 2 ) ), i, roiSize, (int) ceil( roiSize / 2 ) ) ); + backgroundModelROI = mv[0]( Rect( ( j - (int) floor((float) roiSize / 2 ) ), i, roiSize, (int) ceil((float) roiSize / 2 ) ) ); } else if( i == ( backgroundModel[z]->rows - 1 ) && j > 0 && j < ( backgroundModel[z]->cols - 1 ) ) //down middle { split( *backgroundModel[z], mv ); backgroundModelROI = mv[0]( - Rect( j - (int) floor( roiSize / 2 ), i - (int) floor( roiSize / 2 ), roiSize, (int) ceil( roiSize / 2 ) ) ); + Rect( j - (int) floor((float) roiSize / 2 ), i - (int) floor((float) roiSize / 2 ), roiSize, (int) ceil((float) roiSize / 2 ) ) ); } else if( i == 0 && j == ( backgroundModel[z]->cols - 1 ) ) // upper right { split( *backgroundModel[z], mv ); - backgroundModelROI = mv[0]( Rect( j - (int) floor( roiSize / 2 ), i, (int) ceil( roiSize / 2 ), (int) ceil( roiSize / 2 ) ) ); + backgroundModelROI = mv[0]( Rect( j - (int) floor((float) roiSize / 2 ), i, (int) ceil((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ) ) ); } else if( j == ( backgroundModel[z]->cols - 1 ) && i > 0 && i < ( backgroundModel[z]->rows - 1 ) ) // middle - right { split( *backgroundModel[z], mv ); backgroundModelROI = mv[0]( - Rect( j - (int) floor( roiSize / 2 ), i - (int) floor( roiSize / 2 ), (int) ceil( roiSize / 2 ), roiSize ) ); + Rect( j - (int) floor((float) roiSize / 2 ), i - (int) floor((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ), roiSize ) ); } else if( i == ( backgroundModel[z]->rows - 1 ) && j == ( backgroundModel[z]->cols - 1 ) ) // down right { split( *backgroundModel[z], mv ); backgroundModelROI = mv[0]( - Rect( j - (int) floor( roiSize / 2 ), i - (int) floor( roiSize / 2 ), (int) ceil( roiSize / 2 ), (int) ceil( roiSize / 2 ) ) ); + Rect( j - (int) floor((float) roiSize / 2 ), i - (int) floor((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ), (int) ceil((float) roiSize / 2 ) ) ); } /* Check if the value of current pixel BA in potentialBackground model is already contained in at least one of its neighbors' @@ -479,7 +480,7 @@ bool MotionSaliencyBinWangApr2014::templateReplacement( const Mat& finalBFMask, /////////////////// REPLACEMENT of backgroundModel template /////////////////// //replace TA with current TK backgroundModel[backgroundModel.size() - 1]->at( i, j ) = potentialBackground.at( i, j ); - potentialBackground.at( i, j )[0] = (float)NAN; + potentialBackground.at( i, j )[0] = std::numeric_limits::quiet_NaN(); potentialBackground.at( i, j )[1] = 0; break; @@ -489,7 +490,7 @@ bool MotionSaliencyBinWangApr2014::templateReplacement( const Mat& finalBFMask, else { backgroundModel[backgroundModel.size() - 1]->at( i, j ) = potentialBackground.at( i, j ); - potentialBackground.at( i, j )[0] = (float)NAN; + potentialBackground.at( i, j )[0] = std::numeric_limits::quiet_NaN(); potentialBackground.at( i, j )[1] = 0; } } // close if of EVALUATION diff --git a/modules/stereo/include/opencv2/stereo.hpp b/modules/stereo/include/opencv2/stereo.hpp index df31cbc0c..fe3ec351e 100644 --- a/modules/stereo/include/opencv2/stereo.hpp +++ b/modules/stereo/include/opencv2/stereo.hpp @@ -47,211 +47,234 @@ #include "opencv2/core.hpp" #include "opencv2/features2d.hpp" #include "opencv2/core/affine.hpp" +#include "../../stereo/src/descriptor.hpp" +#include "../../stereo/src/matching.hpp" /** @defgroup stereo Stereo Correspondance Algorithms - */ +*/ namespace cv { - namespace stereo - { - -//! @addtogroup stereo -//! @{ -// void correctMatches( InputArray F, InputArray points1, InputArray points2, - // OutputArray newPoints1, OutputArray newPoints2 ); - - /** @brief Filters off small noise blobs (speckles) in the disparity map - - @param img The input 16-bit signed disparity image - @param newVal The disparity value used to paint-off the speckles - @param maxSpeckleSize The maximum speckle size to consider it a speckle. Larger blobs are not - affected by the algorithm - @param maxDiff Maximum difference between neighbor disparity pixels to put them into the same - blob. Note that since StereoBM, StereoSGBM and may be other algorithms return a fixed-point - disparity map, where disparity values are multiplied by 16, this scale factor should be taken into - account when specifying this parameter value. - @param buf The optional temporary buffer to avoid memory allocation within the function. - */ - /** @brief The base class for stereo correspondence algorithms. - */ - class StereoMatcher : public Algorithm - { - public: - enum { DISP_SHIFT = 4, - DISP_SCALE = (1 << DISP_SHIFT) - }; - - /** @brief Computes disparity map for the specified stereo pair - - @param left Left 8-bit single-channel image. - @param right Right image of the same size and the same type as the left one. - @param disparity Output disparity map. It has the same size as the input images. Some algorithms, - like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value - has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. - */ - virtual void compute( InputArray left, InputArray right, - OutputArray disparity ) = 0; - - virtual int getMinDisparity() const = 0; - virtual void setMinDisparity(int minDisparity) = 0; - - virtual int getNumDisparities() const = 0; - virtual void setNumDisparities(int numDisparities) = 0; - - virtual int getBlockSize() const = 0; - virtual void setBlockSize(int blockSize) = 0; - - virtual int getSpeckleWindowSize() const = 0; - virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; - - virtual int getSpeckleRange() const = 0; - virtual void setSpeckleRange(int speckleRange) = 0; - - virtual int getDisp12MaxDiff() const = 0; - virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; - }; - - - /** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and - contributed to OpenCV by K. Konolige. - */ - class StereoBinaryBM : public StereoMatcher - { - public: - enum { PREFILTER_NORMALIZED_RESPONSE = 0, - PREFILTER_XSOBEL = 1 - }; - - virtual int getPreFilterType() const = 0; - virtual void setPreFilterType(int preFilterType) = 0; - - virtual int getPreFilterSize() const = 0; - virtual void setPreFilterSize(int preFilterSize) = 0; - - virtual int getPreFilterCap() const = 0; - virtual void setPreFilterCap(int preFilterCap) = 0; - - virtual int getTextureThreshold() const = 0; - virtual void setTextureThreshold(int textureThreshold) = 0; - - virtual int getUniquenessRatio() const = 0; - virtual void setUniquenessRatio(int uniquenessRatio) = 0; - - virtual int getSmallerBlockSize() const = 0; - virtual void setSmallerBlockSize(int blockSize) = 0; - - virtual Rect getROI1() const = 0; - virtual void setROI1(Rect roi1) = 0; - - virtual Rect getROI2() const = 0; - virtual void setROI2(Rect roi2) = 0; - - /** @brief Creates StereoBM object - - @param numDisparities the disparity search range. For each pixel algorithm will find the best - disparity from 0 (default minimum disparity) to numDisparities. The search range can then be - shifted by changing the minimum disparity. - @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd - (as the block is centered at the current pixel). Larger block size implies smoother, though less - accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher - chance for algorithm to find a wrong correspondence. - - The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for - a specific stereo pair. - */ - CV_EXPORTS static Ptr< cv::stereo::StereoBinaryBM > create(int numDisparities = 0, int blockSize = 21); - }; - - /** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original - one as follows: - - - By default, the algorithm is single-pass, which means that you consider only 5 directions - instead of 8. Set mode=StereoSGBM::MODE_HH in createStereoSGBM to run the full variant of the - algorithm but beware that it may consume a lot of memory. - - The algorithm matches blocks, not individual pixels. Though, setting blockSize=1 reduces the - blocks to single pixels. - - Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi - sub-pixel metric from @cite BT98 is used. Though, the color images are supported as well. - - Some pre- and post- processing steps from K. Konolige algorithm StereoBM are included, for - example: pre-filtering (StereoBM::PREFILTER_XSOBEL type) and post-filtering (uniqueness - check, quadratic interpolation and speckle filtering). - - @note - - (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found - at opencv_source_code/samples/python2/stereo_match.py - */ - class StereoBinarySGBM : public StereoMatcher - { - public: - enum - { - MODE_SGBM = 0, - MODE_HH = 1 - }; - - virtual int getPreFilterCap() const = 0; - virtual void setPreFilterCap(int preFilterCap) = 0; - - virtual int getUniquenessRatio() const = 0; - virtual void setUniquenessRatio(int uniquenessRatio) = 0; - - virtual int getP1() const = 0; - virtual void setP1(int P1) = 0; - - virtual int getP2() const = 0; - virtual void setP2(int P2) = 0; - - virtual int getMode() const = 0; - virtual void setMode(int mode) = 0; - - /** @brief Creates StereoSGBM object - - @param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes - rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. - @param numDisparities Maximum disparity minus minimum disparity. The value is always greater than - zero. In the current implementation, this parameter must be divisible by 16. - @param blockSize Matched block size. It must be an odd number \>=1 . Normally, it should be - somewhere in the 3..11 range. - @param P1 The first parameter controlling the disparity smoothness. See below. - @param P2 The second parameter controlling the disparity smoothness. The larger the values are, - the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 - between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor - pixels. The algorithm requires P2 \> P1 . See stereo_match.cpp sample where some reasonably good - P1 and P2 values are shown (like 8\*number_of_image_channels\*SADWindowSize\*SADWindowSize and - 32\*number_of_image_channels\*SADWindowSize\*SADWindowSize , respectively). - @param disp12MaxDiff Maximum allowed difference (in integer pixel units) in the left-right - disparity check. Set it to a non-positive value to disable the check. - @param preFilterCap Truncation value for the prefiltered image pixels. The algorithm first - computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. - The result values are passed to the Birchfield-Tomasi pixel cost function. - @param uniquenessRatio Margin in percentage by which the best (minimum) computed cost function - value should "win" the second best value to consider the found match correct. Normally, a value - within the 5-15 range is good enough. - @param speckleWindowSize Maximum size of smooth disparity regions to consider their noise speckles - and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the - 50-200 range. - @param speckleRange Maximum disparity variation within each connected component. If you do speckle - filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. - Normally, 1 or 2 is good enough. - @param mode Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming - algorithm. It will consume O(W\*H\*numDisparities) bytes, which is large for 640x480 stereo and - huge for HD-size pictures. By default, it is set to false . - - The first constructor initializes StereoSGBM with all the default parameters. So, you only have to - set StereoSGBM::numDisparities at minimum. The second constructor enables you to set each parameter - to a custom value. - */ - CV_EXPORTS static Ptr create(int minDisparity, int numDisparities, int blockSize, - int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, - int preFilterCap = 0, int uniquenessRatio = 0, - int speckleWindowSize = 0, int speckleRange = 0, - int mode = StereoBinarySGBM::MODE_SGBM); - }; - //! @} - }//stereo + namespace stereo + { + //! @addtogroup stereo + //! @{ + // void correctMatches( InputArray F, InputArray points1, InputArray points2, + // OutputArray newPoints1, OutputArray newPoints2 ); + /** @brief Filters off small noise blobs (speckles) in the disparity map + @param img The input 16-bit signed disparity image + @param newVal The disparity value used to paint-off the speckles + @param maxSpeckleSize The maximum speckle size to consider it a speckle. Larger blobs are not + affected by the algorithm + @param maxDiff Maximum difference between neighbor disparity pixels to put them into the same + blob. Note that since StereoBM, StereoSGBM and may be other algorithms return a fixed-point + disparity map, where disparity values are multiplied by 16, this scale factor should be taken into + account when specifying this parameter value. + @param buf The optional temporary buffer to avoid memory allocation within the function. + */ + /** @brief The base class for stereo correspondence algorithms. + */ + class StereoMatcher : public Algorithm + { + public: + enum { DISP_SHIFT = 4, + DISP_SCALE = (1 << DISP_SHIFT) + }; + + /** @brief Computes disparity map for the specified stereo pair + + @param left Left 8-bit single-channel image. + @param right Right image of the same size and the same type as the left one. + @param disparity Output disparity map. It has the same size as the input images. Some algorithms, + like StereoBM or StereoSGBM compute 16-bit fixed-point disparity map (where each disparity value + has 4 fractional bits), whereas other algorithms output 32-bit floating-point disparity map. + */ + virtual void compute( InputArray left, InputArray right, + OutputArray disparity ) = 0; + + virtual int getMinDisparity() const = 0; + virtual void setMinDisparity(int minDisparity) = 0; + + virtual int getNumDisparities() const = 0; + virtual void setNumDisparities(int numDisparities) = 0; + + virtual int getBlockSize() const = 0; + virtual void setBlockSize(int blockSize) = 0; + + virtual int getSpeckleWindowSize() const = 0; + virtual void setSpeckleWindowSize(int speckleWindowSize) = 0; + + virtual int getSpeckleRange() const = 0; + virtual void setSpeckleRange(int speckleRange) = 0; + + virtual int getDisp12MaxDiff() const = 0; + virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0; + + }; + //!speckle removal algorithms. These algorithms have the purpose of removing small regions + enum { + CV_SPECKLE_REMOVAL_ALGORITHM, CV_SPECKLE_REMOVAL_AVG_ALGORITHM + }; + //!subpixel interpolationm methods for disparities. + enum{ + CV_QUADRATIC_INTERPOLATION, CV_SIMETRICV_INTERPOLATION + }; + /** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and + contributed to OpenCV by K. Konolige. + */ + class StereoBinaryBM : public StereoMatcher + { + public: + enum { PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1 + }; + + virtual int getPreFilterType() const = 0; + virtual void setPreFilterType(int preFilterType) = 0; + + virtual int getPreFilterSize() const = 0; + virtual void setPreFilterSize(int preFilterSize) = 0; + + virtual int getPreFilterCap() const = 0; + virtual void setPreFilterCap(int preFilterCap) = 0; + + virtual int getTextureThreshold() const = 0; + virtual void setTextureThreshold(int textureThreshold) = 0; + + virtual int getUniquenessRatio() const = 0; + virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + virtual int getSmallerBlockSize() const = 0; + virtual void setSmallerBlockSize(int blockSize) = 0; + + virtual int getScalleFactor() const = 0 ; + virtual void setScalleFactor(int factor) = 0; + + virtual int getSpekleRemovalTechnique() const = 0 ; + virtual void setSpekleRemovalTechnique(int factor) = 0; + + virtual bool getUsePrefilter() const = 0 ; + virtual void setUsePrefilter(bool factor) = 0; + + virtual int getBinaryKernelType() const = 0; + virtual void setBinaryKernelType(int value) = 0; + + virtual int getAgregationWindowSize() const = 0; + virtual void setAgregationWindowSize(int value) = 0; + /** @brief Creates StereoBM object + + @param numDisparities the disparity search range. For each pixel algorithm will find the best + disparity from 0 (default minimum disparity) to numDisparities. The search range can then be + shifted by changing the minimum disparity. + @param blockSize the linear size of the blocks compared by the algorithm. The size should be odd + (as the block is centered at the current pixel). Larger block size implies smoother, though less + accurate disparity map. Smaller block size gives more detailed disparity map, but there is higher + chance for algorithm to find a wrong correspondence. + + The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for + a specific stereo pair. + */ + CV_EXPORTS static Ptr< cv::stereo::StereoBinaryBM > create(int numDisparities = 0, int blockSize = 9); + }; + + /** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original + one as follows: + + - By default, the algorithm is single-pass, which means that you consider only 5 directions + instead of 8. Set mode=StereoSGBM::MODE_HH in createStereoSGBM to run the full variant of the + algorithm but beware that it may consume a lot of memory. + - The algorithm matches blocks, not individual pixels. Though, setting blockSize=1 reduces the + blocks to single pixels. + - Mutual information cost function is not implemented. Instead, a simpler Birchfield-Tomasi + sub-pixel metric from @cite BT98 is used. Though, the color images are supported as well. + - Some pre- and post- processing steps from K. Konolige algorithm StereoBM are included, for + example: pre-filtering (StereoBM::PREFILTER_XSOBEL type) and post-filtering (uniqueness + check, quadratic interpolation and speckle filtering). + + @note + - (Python) An example illustrating the use of the StereoSGBM matching algorithm can be found + at opencv_source_code/samples/python2/stereo_match.py + */ + class StereoBinarySGBM : public StereoMatcher + { + public: + enum + { + MODE_SGBM = 0, + MODE_HH = 1 + }; + + virtual int getPreFilterCap() const = 0; + virtual void setPreFilterCap(int preFilterCap) = 0; + + virtual int getUniquenessRatio() const = 0; + virtual void setUniquenessRatio(int uniquenessRatio) = 0; + + virtual int getP1() const = 0; + virtual void setP1(int P1) = 0; + + virtual int getP2() const = 0; + virtual void setP2(int P2) = 0; + + virtual int getMode() const = 0; + virtual void setMode(int mode) = 0; + + virtual int getSpekleRemovalTechnique() const = 0 ; + virtual void setSpekleRemovalTechnique(int factor) = 0; + + virtual int getBinaryKernelType() const = 0; + virtual void setBinaryKernelType(int value) = 0; + + virtual int getSubPixelInterpolationMethod() const = 0; + virtual void setSubPixelInterpolationMethod(int value) = 0; + + /** @brief Creates StereoSGBM object + + @param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes + rectification algorithms can shift images, so this parameter needs to be adjusted accordingly. + @param numDisparities Maximum disparity minus minimum disparity. The value is always greater than + zero. In the current implementation, this parameter must be divisible by 16. + @param blockSize Matched block size. It must be an odd number \>=1 . Normally, it should be + somewhere in the 3..11 range. + @param P1 The first parameter controlling the disparity smoothness.This parameter is used for the case of slanted surfaces (not fronto parallel). + @param P2 The second parameter controlling the disparity smoothness.This parameter is used for "solving" the depth discontinuities problem. + The larger the values are, the smoother the disparity is. P1 is the penalty on the disparity change by plus or minus 1 + between neighbor pixels. P2 is the penalty on the disparity change by more than 1 between neighbor + pixels. The algorithm requires P2 \> P1 . See stereo_match.cpp sample where some reasonably good + P1 and P2 values are shown (like 8\*number_of_image_channels\*SADWindowSize\*SADWindowSize and + 32\*number_of_image_channels\*SADWindowSize\*SADWindowSize , respectively). + @param disp12MaxDiff Maximum allowed difference (in integer pixel units) in the left-right + disparity check. Set it to a non-positive value to disable the check. + @param preFilterCap Truncation value for the prefiltered image pixels. The algorithm first + computes x-derivative at each pixel and clips its value by [-preFilterCap, preFilterCap] interval. + The result values are passed to the Birchfield-Tomasi pixel cost function. + @param uniquenessRatio Margin in percentage by which the best (minimum) computed cost function + value should "win" the second best value to consider the found match correct. Normally, a value + within the 5-15 range is good enough. + @param speckleWindowSize Maximum size of smooth disparity regions to consider their noise speckles + and invalidate. Set it to 0 to disable speckle filtering. Otherwise, set it somewhere in the + 50-200 range. + @param speckleRange Maximum disparity variation within each connected component. If you do speckle + filtering, set the parameter to a positive value, it will be implicitly multiplied by 16. + Normally, 1 or 2 is good enough. + @param mode Set it to StereoSGBM::MODE_HH to run the full-scale two-pass dynamic programming + algorithm. It will consume O(W\*H\*numDisparities) bytes, which is large for 640x480 stereo and + huge for HD-size pictures. By default, it is set to false . + + The first constructor initializes StereoSGBM with all the default parameters. So, you only have to + set StereoSGBM::numDisparities at minimum. The second constructor enables you to set each parameter + to a custom value. + */ + CV_EXPORTS static Ptr create(int minDisparity, int numDisparities, int blockSize, + int P1 = 100, int P2 = 1000, int disp12MaxDiff = 1, + int preFilterCap = 0, int uniquenessRatio = 5, + int speckleWindowSize = 400, int speckleRange = 200, + int mode = StereoBinarySGBM::MODE_SGBM); + }; + //! @} + }//stereo } // cv #ifndef DISABLE_OPENCV_24_COMPATIBILITY diff --git a/modules/stereo/perf/perf_bm.cpp b/modules/stereo/perf/perf_bm.cpp new file mode 100644 index 000000000..88aeb6a0d --- /dev/null +++ b/modules/stereo/perf/perf_bm.cpp @@ -0,0 +1,118 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace cv::stereo; +using namespace perf; + +typedef std::tr1::tuple s_bm_test_t; +typedef perf::TestBaseWithParam s_bm; + +PERF_TEST_P( s_bm, sgm_perf, + testing::Combine( + testing::Values( cv::Size(512, 283), cv::Size(320, 240)), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_8UC1,CV_8U,CV_16S ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + + Mat left(sz, matType); + Mat right(sz, matType); + Mat out1(sz, sdepth); + Ptr sgbm = StereoBinarySGBM::create(0, 16, 5); + sgbm->setBinaryKernelType(CV_DENSE_CENSUS); + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.1) + .iterations(20); + TEST_CYCLE() + { + sgbm->compute(left, right, out1); + } + SANITY_CHECK(out1); +} +PERF_TEST_P( s_bm, bm_perf, + testing::Combine( + testing::Values( cv::Size(512, 383), cv::Size(320, 240) ), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_8UC1,CV_8U ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + + Mat left(sz, matType); + Mat right(sz, matType); + Mat out1(sz, sdepth); + Ptr sbm = StereoBinaryBM::create(16, 9); + // we set the corresponding parameters + sbm->setPreFilterCap(31); + sbm->setMinDisparity(0); + sbm->setTextureThreshold(10); + sbm->setUniquenessRatio(0); + sbm->setSpeckleWindowSize(400); + sbm->setDisp12MaxDiff(0); + sbm->setAgregationWindowSize(11); + // the user can choose between the average speckle removal algorithm or + // the classical version that was implemented in OpenCV + sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); + sbm->setUsePrefilter(false); + + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.1) + .iterations(20); + TEST_CYCLE() + { + sbm->compute(left, right, out1); + } + SANITY_CHECK(out1); +} diff --git a/modules/stereo/perf/perf_descriptor.cpp b/modules/stereo/perf/perf_descriptor.cpp new file mode 100644 index 000000000..27d57fbd1 --- /dev/null +++ b/modules/stereo/perf/perf_descriptor.cpp @@ -0,0 +1,143 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ +#include "perf_precomp.hpp" + +using namespace std; +using namespace cv; +using namespace cv::stereo; +using namespace perf; + +typedef std::tr1::tuple descript_params_t; +typedef perf::TestBaseWithParam descript_params; + +PERF_TEST_P( descript_params, census_sparse_descriptor, + testing::Combine( + testing::Values( TYPICAL_MAT_SIZES ), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_32SC4,CV_32S ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + Mat left(sz, matType); + Mat out1(sz, sdepth); + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.01); + TEST_CYCLE() + { + censusTransform(left,9,out1,CV_SPARSE_CENSUS); + } + SANITY_CHECK(out1); +} +PERF_TEST_P( descript_params, star_census_transform, + testing::Combine( + testing::Values( TYPICAL_MAT_SIZES ), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_32SC4,CV_32S ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + Mat left(sz, matType); + Mat out1(sz, sdepth); + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.01); + TEST_CYCLE() + { + starCensusTransform(left,9,out1); + } + SANITY_CHECK(out1); +} +PERF_TEST_P( descript_params, modified_census_transform, + testing::Combine( + testing::Values( TYPICAL_MAT_SIZES ), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_32SC4,CV_32S ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + + Mat left(sz, matType); + Mat out1(sz, sdepth); + + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.01); + TEST_CYCLE() + { + modifiedCensusTransform(left,9,out1,CV_MODIFIED_CENSUS_TRANSFORM); + } + SANITY_CHECK(out1); +} +PERF_TEST_P( descript_params, center_symetric_census, + testing::Combine( + testing::Values( TYPICAL_MAT_SIZES ), + testing::Values( CV_8UC1,CV_8U ), + testing::Values( CV_32SC4,CV_32S ) + ) + ) +{ + Size sz = std::tr1::get<0>(GetParam()); + int matType = std::tr1::get<1>(GetParam()); + int sdepth = std::tr1::get<2>(GetParam()); + + Mat left(sz, matType); + Mat out1(sz, sdepth); + + declare.in(left, WARMUP_RNG) + .out(out1) + .time(0.01); + TEST_CYCLE() + { + symetricCensusTransform(left,7,out1,CV_CS_CENSUS); + } + SANITY_CHECK(out1); +} diff --git a/modules/stereo/perf/perf_main.cpp b/modules/stereo/perf/perf_main.cpp new file mode 100644 index 000000000..657393c4b --- /dev/null +++ b/modules/stereo/perf/perf_main.cpp @@ -0,0 +1,44 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ +#include "perf_precomp.hpp" + +CV_PERF_TEST_MAIN(stereo) diff --git a/modules/stereo/perf/perf_precomp.hpp b/modules/stereo/perf/perf_precomp.hpp new file mode 100644 index 000000000..23ed07281 --- /dev/null +++ b/modules/stereo/perf/perf_precomp.hpp @@ -0,0 +1,32 @@ +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wmissing-declarations" +# if defined __clang__ || defined __APPLE__ +# pragma GCC diagnostic ignored "-Wmissing-prototypes" +# pragma GCC diagnostic ignored "-Wextra" +# endif +#endif + +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include +#include "opencv2/ts.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/stereo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/features2d.hpp" +#include "opencv2/core/utility.hpp" +#include "opencv2/core/private.hpp" +#include "opencv2/core/cvdef.h" +#include "opencv2/core.hpp" +#include "opencv2/highgui.hpp" +#include "opencv2/calib3d.hpp" + +#include +#include + +#ifdef GTEST_CREATE_SHARED_LIBRARY +#error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined +#endif + +#endif diff --git a/modules/stereo/samples/sample.cpp b/modules/stereo/samples/sample.cpp new file mode 100644 index 000000000..0431751bd --- /dev/null +++ b/modules/stereo/samples/sample.cpp @@ -0,0 +1,196 @@ +#include "opencv2/stereo.hpp" +#include "opencv2/imgproc.hpp" +#include "opencv2/highgui.hpp" +#include +#include +#include + +using namespace std; +using namespace cv; +using namespace cv::stereo; + +enum { STEREO_BINARY_BM, STEREO_BINARY_SGM }; +static cv::CommandLineParser parse_argument_values(int argc, char **argv, string &left, string &right, int &kernel_size, int &number_of_disparities, + int &aggregation_window, int &P1, int &P2, float &scale, int &algo, int &binary_descriptor_type, int &success); +int main(int argc, char** argv) +{ + string left, right; + int kernel_size = 0, number_of_disparities = 0, aggregation_window = 0, P1 = 0, P2 = 0; + float scale = 4; + int algo = STEREO_BINARY_BM; + int binary_descriptor_type = 0; + int success; + // here we extract the values that were added as arguments + // we also test to see if they are provided correcly + cv::CommandLineParser parser = + parse_argument_values(argc, argv, left, right, + kernel_size, + number_of_disparities, + aggregation_window, + P1, P2, + scale, + algo, binary_descriptor_type,success); + if (!parser.check() || !success) + { + parser.printMessage(); + return 1; + } + // verify if the user inputs the correct number of parameters + Mat image1, image2; + // we read a pair of images from the disk + image1 = imread(left, CV_8UC1); + image2 = imread(right, CV_8UC1); + // verify if they are loaded correctly + if (image1.empty() || image2.empty()) + { + cout << " --(!) Error reading images \n"; + + parser.printMessage(); + return 1; + } + // we display the parsed parameters + const char *b[7] = { "CV_DENSE_CENSUS", "CV_SPARSE_CENSUS", "CV_CS_CENSUS", "CV_MODIFIED_CS_CENSUS", + "CV_MODIFIED_CENSUS_TRANSFORM", "CV_MEAN_VARIATION", "CV_STAR_KERNEL" }; + cout << "Program Name: " << argv[0]; + cout << "\nPath to left image " << left << " \n" << "Path to right image " << right << "\n"; + cout << "\nkernel size " << kernel_size << "\n" + << "numberOfDisparities " << number_of_disparities << "\n" + << "aggregationWindow " << aggregation_window << "\n" + << "scallingFactor " << scale << "\n" << "Descriptor name : " << b[binary_descriptor_type] << "\n"; + + Mat imgDisparity16S2 = Mat(image1.rows, image1.cols, CV_16S); + Mat imgDisparity8U2 = Mat(image1.rows, image1.cols, CV_8UC1); + imshow("Original Left image", image1); + + if (algo == STEREO_BINARY_BM) + { + Ptr sbm = StereoBinaryBM::create(number_of_disparities, kernel_size); + // we set the corresponding parameters + sbm->setPreFilterCap(31); + sbm->setMinDisparity(0); + sbm->setTextureThreshold(10); + sbm->setUniquenessRatio(0); + sbm->setSpeckleWindowSize(400); // speckle size + sbm->setSpeckleRange(200); + sbm->setDisp12MaxDiff(0); + sbm->setScalleFactor((int)scale); // the scaling factor + sbm->setBinaryKernelType(binary_descriptor_type); // binary descriptor kernel + sbm->setAgregationWindowSize(aggregation_window); + // the user can choose between the average speckle removal algorithm or + // the classical version that was implemented in OpenCV + sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); + sbm->setUsePrefilter(false); + //-- calculate the disparity image + sbm->compute(image1, image2, imgDisparity8U2); + imshow("Disparity", imgDisparity8U2); + } + else if (algo == STEREO_BINARY_SGM) + { + // we set the corresponding parameters + Ptr sgbm = StereoBinarySGBM::create(0, number_of_disparities, kernel_size); + // setting the penalties for sgbm + sgbm->setP1(P1); + sgbm->setP2(P2); + sgbm->setMinDisparity(0); + sgbm->setUniquenessRatio(5); + sgbm->setSpeckleWindowSize(400); + sgbm->setSpeckleRange(0); + sgbm->setDisp12MaxDiff(1); + sgbm->setBinaryKernelType(binary_descriptor_type); + sgbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); + sgbm->setSubPixelInterpolationMethod(CV_SIMETRICV_INTERPOLATION); + sgbm->compute(image1, image2, imgDisparity16S2); + /*Alternative for scalling + imgDisparity16S2.convertTo(imgDisparity8U2, CV_8UC1, scale); + */ + double minVal; double maxVal; + minMaxLoc(imgDisparity16S2, &minVal, &maxVal); + imgDisparity16S2.convertTo(imgDisparity8U2, CV_8UC1, 255 / (maxVal - minVal)); + //show the disparity image + imshow("Windowsgm", imgDisparity8U2); + } + waitKey(0); + return 0; +} +static cv::CommandLineParser parse_argument_values(int argc, char **argv, string &left, string &right, int &kernel_size, int &number_of_disparities, + int &aggregation_window, int &P1, int &P2, float &scale, int &algo, int &binary_descriptor_type, int &success) +{ + static const char* keys = + "{ @left | | }" + "{ @right | | }" + "{ k kernel_size | 9 | }" + "{ d disparity | 128 | }" + "{ w aggregation_window | 9 | }" + "{ P1 | 100 | }" + "{ P2 | 1000 | }" + "{ b binary_descriptor | 4 | Index of the descriptor type:\n 0 - CV_DENSE_CENSUS,\n 1 - CV_SPARSE_CENSUS,\n 2 - CV_CS_CENSUS,\n 3 - CV_MODIFIED_CS_CENSUS,\n 4 - CV_MODIFIED_CENSUS_TRANSFORM,\n 5 - CV_MEAN_VARIATION,\n 6 - CV_STAR_KERNEL}" + "{ s scale | 1.01593 | }" + "{ a algorithm | sgm | }" + ; + cv::CommandLineParser parser( argc, argv, keys ); + + left = parser.get(0); + right = parser.get(1); + kernel_size = parser.get("kernel_size"); + number_of_disparities = parser.get("disparity"); + aggregation_window = parser.get("aggregation_window"); + P1 = parser.get("P1"); + P2 = parser.get("P2"); + binary_descriptor_type = parser.get("binary_descriptor"); + scale = parser.get("scale"); + algo = parser.get("algorithm") == "sgm" ? STEREO_BINARY_SGM : STEREO_BINARY_BM; + + parser.about("\nDemo stereo matching converting L and R images into disparity images using BM and SGBM\n"); + + success = 1; + //TEST if the provided parameters are correct + if(binary_descriptor_type == CV_DENSE_CENSUS && kernel_size > 5) + { + cout << "For the dense census transform the maximum kernel size should be 5\n"; + success = 0; + } + if((binary_descriptor_type == CV_MEAN_VARIATION || binary_descriptor_type == CV_MODIFIED_CENSUS_TRANSFORM || binary_descriptor_type == CV_STAR_KERNEL) && kernel_size != 9) + { + cout <<" For Mean variation and the modified census transform the kernel size should be equal to 9\n"; + success = 0; + } + if((binary_descriptor_type == CV_CS_CENSUS || binary_descriptor_type == CV_MODIFIED_CS_CENSUS) && kernel_size > 7) + { + cout << " The kernel size should be smaller or equal to 7 for the CS census and modified center symetric census\n"; + success = 0; + } + if(binary_descriptor_type == CV_SPARSE_CENSUS && kernel_size > 11) + { + cout << "The kernel size for the sparse census must be smaller or equal to 11\n"; + success = 0; + } + if(number_of_disparities < 10) + { + cout << "Number of disparities should be greater than 10\n"; + success = 0; + } + if(aggregation_window < 3) + { + cout << "Aggregation window should be > 3"; + success = 0; + } + if(scale < 1) + { + cout << "The scale should be a positive number \n"; + success = 0; + } + if(P1 != 0) + { + if(P2 / P1 < 2) + { + cout << "You should probably choose a greater P2 penalty\n"; + success = 0; + } + } + else + { + cout << " Penalties should be greater than 0\n"; + success = 0; + } + return parser; +} diff --git a/modules/stereo/src/descriptor.cpp b/modules/stereo/src/descriptor.cpp new file mode 100644 index 000000000..547956d25 --- /dev/null +++ b/modules/stereo/src/descriptor.cpp @@ -0,0 +1,241 @@ +//By downloading, copying, installing or using the software you agree to this license. +//If you do not agree to this license, do not download, install, +//copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +//Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +//Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +//Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +//Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +//Copyright (C) 2015, OpenCV Foundation, all rights reserved. +//Copyright (C) 2015, Itseez Inc., all rights reserved. +//Third party copyrights are property of their respective owners. +// +//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 names of the copyright holders nor the names of the 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 copyright holders 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. + +/*****************************************************************************************************************\ +* The file contains the implemented descriptors * +\******************************************************************************************************************/ +#include "precomp.hpp" +#include "descriptor.hpp" + +namespace cv +{ + namespace stereo + { + //function that performs the census transform on two images. + //Two variants of census are offered a sparse version whcih takes every second pixel as well as dense version + CV_EXPORTS void censusTransform(const Mat &image1, const Mat &image2, int kernelSize, Mat &dist1, Mat &dist2, const int type) + { + CV_Assert(image1.size() == image2.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(image1.type() == CV_8UC1 && image2.type() == CV_8UC1); + CV_Assert(type != CV_DENSE_CENSUS || type != CV_SPARSE_CENSUS); + CV_Assert(kernelSize <= ((type == 0) ? 5 : 11)); + int n2 = (kernelSize) / 2; + uint8_t *images[] = {image1.data, image2.data}; + int *costs[] = {(int *)dist1.data,(int *)dist2.data}; + int stride = (int)image1.step; + if(type == CV_DENSE_CENSUS) + { + parallel_for_( Range(n2, image1.rows - n2), + CombinedDescriptor<1,1,1,2,CensusKernel<2> >(image1.cols, image1.rows,stride,n2,costs,CensusKernel<2>(images),n2)); + } + else if(type == CV_SPARSE_CENSUS) + { + parallel_for_( Range(n2, image1.rows - n2), + CombinedDescriptor<2,2,1,2,CensusKernel<2> >(image1.cols, image1.rows, stride,n2,costs,CensusKernel<2>(images),n2)); + } + } + //function that performs census on one image + CV_EXPORTS void censusTransform(const Mat &image1, int kernelSize, Mat &dist1, const int type) + { + CV_Assert(image1.size() == dist1.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(image1.type() == CV_8UC1); + CV_Assert(type != CV_DENSE_CENSUS || type != CV_SPARSE_CENSUS); + CV_Assert(kernelSize <= ((type == 0) ? 5 : 11)); + int n2 = (kernelSize) / 2; + uint8_t *images[] = {image1.data}; + int *costs[] = {(int *)dist1.data}; + int stride = (int)image1.step; + if(type == CV_DENSE_CENSUS) + { + parallel_for_( Range(n2, image1.rows - n2), + CombinedDescriptor<1,1,1,1,CensusKernel<1> >(image1.cols, image1.rows,stride,n2,costs,CensusKernel<1>(images),n2)); + } + else if(type == CV_SPARSE_CENSUS) + { + parallel_for_( Range(n2, image1.rows - n2), + CombinedDescriptor<2,2,1,1,CensusKernel<1> >(image1.cols, image1.rows,stride,n2,costs,CensusKernel<1>(images),n2)); + } + } + //in a 9x9 kernel only certain positions are choosen for comparison + CV_EXPORTS void starCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2) + { + CV_Assert(img1.size() == img2.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1 && img2.type() == CV_8UC1); + CV_Assert(kernelSize >= 7); + int n2 = (kernelSize) >> 1; + Mat images[] = {img1, img2}; + int *date[] = { (int *)dist1.data, (int *)dist2.data}; + parallel_for_(Range(n2, img1.rows - n2), StarKernelCensus<2>(images, n2,date)); + } + //single version of star census + CV_EXPORTS void starCensusTransform(const Mat &img1, int kernelSize, Mat &dist) + { + CV_Assert(img1.size() == dist.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1); + CV_Assert(kernelSize >= 7); + int n2 = (kernelSize) >> 1; + Mat images[] = {img1}; + int *date[] = { (int *)dist.data}; + parallel_for_(Range(n2, img1.rows - n2), StarKernelCensus<1>(images, n2,date)); + } + //Modified census transforms + //the first one deals with small illumination changes + //the sencond modified census transform is invariant to noise; i.e. + //if the current pixel with whom we are dooing the comparison is a noise, this descriptor will provide a better result by comparing with the mean of the window + //otherwise if the pixel is not noise the information is strengthend + CV_EXPORTS void modifiedCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1,Mat &dist2, const int type, int t, const Mat &IntegralImage1, const Mat &IntegralImage2 ) + { + CV_Assert(img1.size() == img2.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1 && img2.type() == CV_8UC1); + CV_Assert(type != CV_MODIFIED_CENSUS_TRANSFORM || type != CV_MEAN_VARIATION); + CV_Assert(kernelSize <= 9); + int n2 = (kernelSize - 1) >> 1; + uint8_t *images[] = {img1.data, img2.data}; + int *date[] = { (int *)dist1.data, (int *)dist2.data}; + int stride = (int)img1.cols; + if(type == CV_MODIFIED_CENSUS_TRANSFORM) + { + //MCT + parallel_for_( Range(n2, img1.rows - n2), + CombinedDescriptor<2,4,2, 2,MCTKernel<2> >(img1.cols, img1.rows,stride,n2,date,MCTKernel<2>(images,t),n2)); + } + else if(type == CV_MEAN_VARIATION) + { + //MV + int *integral[2]; + integral[0] = (int *)IntegralImage1.data; + integral[1] = (int *)IntegralImage2.data; + parallel_for_( Range(n2, img1.rows - n2), + CombinedDescriptor<2,3,2,2, MVKernel<2> >(img1.cols, img1.rows,stride,n2,date,MVKernel<2>(images,integral),n2)); + } + } + CV_EXPORTS void modifiedCensusTransform(const Mat &img1, int kernelSize, Mat &dist, const int type, int t , Mat const &IntegralImage) + { + CV_Assert(img1.size() == dist.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1); + CV_Assert(type != CV_MODIFIED_CENSUS_TRANSFORM || type != CV_MEAN_VARIATION); + CV_Assert(kernelSize <= 9); + int n2 = (kernelSize - 1) >> 1; + uint8_t *images[] = {img1.data}; + int *date[] = { (int *)dist.data}; + int stride = (int)img1.step; + if(type == CV_MODIFIED_CENSUS_TRANSFORM) + { + //MCT + parallel_for_(Range(n2, img1.rows - n2), + CombinedDescriptor<2,4,2, 1,MCTKernel<1> >(img1.cols, img1.rows,stride,n2,date,MCTKernel<1>(images,t),n2)); + } + else if(type == CV_MEAN_VARIATION) + { + //MV + int *integral[] = { (int *)IntegralImage.data}; + parallel_for_(Range(n2, img1.rows - n2), + CombinedDescriptor<2,3,2,1, MVKernel<1> >(img1.cols, img1.rows,stride,n2,date,MVKernel<1>(images,integral),n2)); + } + } + //different versions of simetric census + //These variants since they do not compare with the center they are invariant to noise + CV_EXPORTS void symetricCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2, const int type) + { + CV_Assert(img1.size() == img2.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1 && img2.type() == CV_8UC1); + CV_Assert(type != CV_CS_CENSUS || type != CV_MODIFIED_CS_CENSUS); + CV_Assert(kernelSize <= 7); + int n2 = kernelSize >> 1; + uint8_t *images[] = {img1.data, img2.data}; + Mat imag[] = {img1, img2}; + int *date[] = { (int *)dist1.data, (int *)dist2.data}; + int stride = (int)img1.step; + if(type == CV_CS_CENSUS) + { + parallel_for_(Range(n2, img1.rows - n2), SymetricCensus<2>(imag, n2,date)); + } + else if(type == CV_MODIFIED_CS_CENSUS) + { + parallel_for_(Range(n2, img1.rows - n2), + CombinedDescriptor<1,1,1,2,ModifiedCsCensus<2> >(img1.cols, img1.rows,stride,n2,date,ModifiedCsCensus<2>(images,n2),1)); + } + } + CV_EXPORTS void symetricCensusTransform(const Mat &img1, int kernelSize, Mat &dist1, const int type) + { + CV_Assert(img1.size() == dist1.size()); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(img1.type() == CV_8UC1); + CV_Assert(type != CV_MODIFIED_CS_CENSUS || type != CV_CS_CENSUS); + CV_Assert(kernelSize <= 7); + int n2 = kernelSize >> 1; + uint8_t *images[] = {img1.data}; + Mat imag[] = {img1}; + int *date[] = { (int *)dist1.data}; + int stride = (int)img1.step; + if(type == CV_CS_CENSUS) + { + parallel_for_( Range(n2, img1.rows - n2), SymetricCensus<1>(imag, n2,date)); + } + else if(type == CV_MODIFIED_CS_CENSUS) + { + parallel_for_( Range(n2, img1.rows - n2), + CombinedDescriptor<1,1,1,1,ModifiedCsCensus<1> >(img1.cols, img1.rows,stride,n2,date,ModifiedCsCensus<1>(images,n2),1)); + } + } + //integral image computation used in the Mean Variation Census Transform + void imageMeanKernelSize(const Mat &image, int windowSize, Mat &cost) + { + CV_Assert(image.size > 0); + CV_Assert(cost.size > 0); + CV_Assert(windowSize % 2 != 0); + int win = windowSize / 2; + float scalling = ((float) 1) / (windowSize * windowSize); + int height = image.rows; + cost.setTo(0); + int *c = (int *)cost.data; + parallel_for_(Range(win + 1, height - win - 1),MeanKernelIntegralImage(image,win,scalling,c)); + } + } +} diff --git a/modules/stereo/src/descriptor.hpp b/modules/stereo/src/descriptor.hpp new file mode 100644 index 000000000..6cdab8f33 --- /dev/null +++ b/modules/stereo/src/descriptor.hpp @@ -0,0 +1,453 @@ +//By downloading, copying, installing or using the software you agree to this license. +//If you do not agree to this license, do not download, install, +//copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +//Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +//Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +//Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +//Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +//Copyright (C) 2015, OpenCV Foundation, all rights reserved. +//Copyright (C) 2015, Itseez Inc., all rights reserved. +//Third party copyrights are property of their respective owners. +// +//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 names of the copyright holders nor the names of the 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 copyright holders 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. + +/*****************************************************************************************************************\ +* The interface contains the main descriptors that will be implemented in the descriptor class * +\*****************************************************************************************************************/ + +#include "precomp.hpp" +#include +#ifndef _OPENCV_DESCRIPTOR_HPP_ +#define _OPENCV_DESCRIPTOR_HPP_ +#ifdef __cplusplus + +namespace cv +{ + namespace stereo + { + //types of supported kernels + enum { + CV_DENSE_CENSUS, CV_SPARSE_CENSUS, + CV_CS_CENSUS, CV_MODIFIED_CS_CENSUS, CV_MODIFIED_CENSUS_TRANSFORM, + CV_MEAN_VARIATION, CV_STAR_KERNEL + }; + //!Mean Variation is a robust kernel that compares a pixel + //!not just with the center but also with the mean of the window + template + struct MVKernel + { + uint8_t *image[num_images]; + int *integralImage[num_images]; + int stop; + MVKernel(){} + MVKernel(uint8_t **images, int **integral) + { + for(int i = 0; i < num_images; i++) + { + image[i] = images[i]; + integralImage[i] = integral[i]; + } + stop = num_images; + } + void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int c[num_images]) const + { + (void)w2; + for (int i = 0; i < stop; i++) + { + if (image[i][rrWidth + jj] > image[i][rWidth + j]) + { + c[i] = c[i] + 1; + } + c[i] = c[i] << 1; + if (integralImage[i][rrWidth + jj] > image[i][rWidth + j]) + { + c[i] = c[i] + 1; + } + c[i] = c[i] << 1; + } + } + }; + //!Compares pixels from a patch giving high weights to pixels in which + //!the intensity is higher. The other pixels receive a lower weight + template + struct MCTKernel + { + uint8_t *image[num_images]; + int t,imageStop; + MCTKernel(){} + MCTKernel(uint8_t ** images, int threshold) + { + for(int i = 0; i < num_images; i++) + { + image[i] = images[i]; + } + imageStop = num_images; + t = threshold; + } + void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int c[num_images]) const + { + (void)w2; + for(int i = 0; i < imageStop; i++) + { + if (image[i][rrWidth + jj] > image[i][rWidth + j] - t) + { + c[i] = c[i] << 1; + c[i] = c[i] + 1; + c[i] = c[i] << 1; + c[i] = c[i] + 1; + } + else if (image[i][rWidth + j] - t < image[i][rrWidth + jj] && image[i][rWidth + j] + t >= image[i][rrWidth + jj]) + { + c[i] = c[i] << 2; + c[i] = c[i] + 1; + } + else + { + c[i] <<= 2; + } + } + } + }; + //!A madified cs census that compares a pixel with the imediat neightbour starting + //!from the center + template + struct ModifiedCsCensus + { + uint8_t *image[num_images]; + int n2; + int imageStop; + ModifiedCsCensus(){} + ModifiedCsCensus(uint8_t **images, int ker) + { + for(int i = 0; i < num_images; i++) + image[i] = images[i]; + imageStop = num_images; + n2 = ker; + } + void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int c[num_images]) const + { + (void)j; + (void)rWidth; + for(int i = 0; i < imageStop; i++) + { + if (image[i][(rrWidth + jj)] > image[i][(w2 + (jj + n2))]) + { + c[i] = c[i] + 1; + } + c[i] = c[i] * 2; + } + } + }; + //!A kernel in which a pixel is compared with the center of the window + template + struct CensusKernel + { + uint8_t *image[num_images]; + int imageStop; + CensusKernel(){} + CensusKernel(uint8_t **images) + { + for(int i = 0; i < num_images; i++) + image[i] = images[i]; + imageStop = num_images; + } + void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int c[num_images]) const + { + (void)w2; + for(int i = 0; i < imageStop; i++) + { + ////compare a pixel with the center from the kernel + if (image[i][rrWidth + jj] > image[i][rWidth + j]) + { + c[i] += 1; + } + c[i] <<= 1; + } + } + }; + //template clas which efficiently combines the descriptors + template + class CombinedDescriptor:public ParallelLoopBody + { + private: + int width, height,n2; + int stride_; + int *dst[nr_img]; + Kernel kernel_; + int n2_stop; + public: + CombinedDescriptor(int w, int h,int stride, int k2, int **distance, Kernel kernel,int k2Stop) + { + width = w; + height = h; + n2 = k2; + stride_ = stride; + for(int i = 0; i < nr_img; i++) + dst[i] = distance[i]; + kernel_ = kernel; + n2_stop = k2Stop; + } + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end ; i++) + { + int rWidth = i * stride_; + for (int j = n2 + 2; j <= width - n2 - 2; j++) + { + int c[nr_img]; + memset(c,0,nr_img); + for(int step = step_start; step <= step_end; step += step_inc) + { + for (int ii = - n2; ii <= + n2_stop; ii += step) + { + int rrWidth = (ii + i) * stride_; + int rrWidthC = (ii + i + n2) * stride_; + for (int jj = j - n2; jj <= j + n2; jj += step) + { + if (ii != i || jj != j) + { + kernel_(rrWidth,rrWidthC, rWidth, jj, j,c); + } + } + } + } + for(int l = 0; l < nr_img; l++) + dst[l][rWidth + j] = c[l]; + } + } + } + }; + //!calculate the mean of every windowSizexWindwoSize block from the integral Image + //!this is a preprocessing for MV kernel + class MeanKernelIntegralImage : public ParallelLoopBody + { + private: + int *img; + int windowSize,width; + float scalling; + int *c; + public: + MeanKernelIntegralImage(const cv::Mat &image, int window,float scale, int *cost): + img((int *)image.data),windowSize(window) ,width(image.cols) ,scalling(scale) , c(cost){}; + void operator()(const cv::Range &r) const{ + for (int i = r.start; i <= r.end; i++) + { + int iw = i * width; + for (int j = windowSize + 1; j <= width - windowSize - 1; j++) + { + c[iw + j] = (int)((img[(i + windowSize - 1) * width + j + windowSize - 1] + img[(i - windowSize - 1) * width + j - windowSize - 1] + - img[(i + windowSize) * width + j - windowSize] - img[(i - windowSize) * width + j + windowSize]) * scalling); + } + } + } + }; + //!implementation for the star kernel descriptor + template + class StarKernelCensus:public ParallelLoopBody + { + private: + uint8_t *image[num_images]; + int *dst[num_images]; + int n2, width, height, im_num,stride_; + public: + StarKernelCensus(const cv::Mat *img, int k2, int **distance) + { + for(int i = 0; i < num_images; i++) + { + image[i] = img[i].data; + dst[i] = distance[i]; + } + n2 = k2; + width = img[0].cols; + height = img[0].rows; + im_num = num_images; + stride_ = (int)img[0].step; + } + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end ; i++) + { + int rWidth = i * stride_; + for (int j = n2; j <= width - n2; j++) + { + for(int d = 0 ; d < im_num; d++) + { + int c = 0; + for(int step = 4; step > 0; step--) + { + for (int ii = i - step; ii <= i + step; ii += step) + { + int rrWidth = ii * stride_; + for (int jj = j - step; jj <= j + step; jj += step) + { + if (image[d][rrWidth + jj] > image[d][rWidth + j]) + { + c = c + 1; + } + c = c * 2; + } + } + } + for (int ii = -1; ii <= +1; ii++) + { + int rrWidth = (ii + i) * stride_; + if (i == -1) + { + if (ii + i != i) + { + if (image[d][rrWidth + j] > image[d][rWidth + j]) + { + c = c + 1; + } + c = c * 2; + } + } + else if (i == 0) + { + for (int j2 = -1; j2 <= 1; j2 += 2) + { + if (ii + i != i) + { + if (image[d][rrWidth + j + j2] > image[d][rWidth + j]) + { + c = c + 1; + } + c = c * 2; + } + } + } + else + { + if (ii + i != i) + { + if (image[d][rrWidth + j] > image[d][rWidth + j]) + { + c = c + 1; + } + c = c * 2; + } + } + } + dst[d][rWidth + j] = c; + } + } + } + } + }; + //!paralel implementation of the center symetric census + template + class SymetricCensus:public ParallelLoopBody + { + private: + uint8_t *image[num_images]; + int *dst[num_images]; + int n2, width, height, im_num,stride_; + public: + SymetricCensus(const cv::Mat *img, int k2, int **distance) + { + for(int i = 0; i < num_images; i++) + { + image[i] = img[i].data; + dst[i] = distance[i]; + } + n2 = k2; + width = img[0].cols; + height = img[0].rows; + im_num = num_images; + stride_ = (int)img[0].step; + } + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end ; i++) + { + int distV = i*stride_; + for (int j = n2; j <= width - n2; j++) + { + for(int d = 0; d < im_num; d++) + { + int c = 0; + //the classic center symetric census which compares the curent pixel with its symetric not its center. + for (int ii = -n2; ii <= 0; ii++) + { + int rrWidth = (ii + i) * stride_; + for (int jj = -n2; jj <= +n2; jj++) + { + if (image[d][(rrWidth + (jj + j))] > image[d][((ii * (-1) + i) * width + (-1 * jj) + j)]) + { + c = c + 1; + } + c = c * 2; + if(ii == 0 && jj < 0) + { + if (image[d][(i * width + (jj + j))] > image[d][(i * width + (-1 * jj) + j)]) + { + c = c + 1; + } + c = c * 2; + } + } + } + dst[d][(distV + j)] = c; + } + } + } + } + }; + /** + Two variations of census applied on input images + Implementation of a census transform which is taking into account just the some pixels from the census kernel thus allowing for larger block sizes + **/ + //void applyCensusOnImages(const cv::Mat &im1,const cv::Mat &im2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type); + CV_EXPORTS void censusTransform(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type); + //single image census transform + CV_EXPORTS void censusTransform(const cv::Mat &image1, int kernelSize, cv::Mat &dist1, const int type); + /** + STANDARD_MCT - Modified census which is memorizing for each pixel 2 bits and includes a tolerance to the pixel comparison + MCT_MEAN_VARIATION - Implementation of a modified census transform which is also taking into account the variation to the mean of the window not just the center pixel + **/ + CV_EXPORTS void modifiedCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2, const int type, int t = 0 , const cv::Mat &IntegralImage1 = cv::Mat::zeros(100,100,CV_8UC1), const cv::Mat &IntegralImage2 = cv::Mat::zeros(100,100,CV_8UC1)); + //single version of modified census transform descriptor + CV_EXPORTS void modifiedCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist, const int type, int t = 0 ,const cv::Mat &IntegralImage = cv::Mat::zeros(100,100,CV_8UC1)); + /**The classical center symetric census + A modified version of cs census which is comparing a pixel with its correspondent after the center + **/ + CV_EXPORTS void symetricCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type); + //single version of census transform + CV_EXPORTS void symetricCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist1, const int type); + //in a 9x9 kernel only certain positions are choosen + CV_EXPORTS void starCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2); + //single image version of star kernel + CV_EXPORTS void starCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist); + //integral image computation used in the Mean Variation Census Transform + void imageMeanKernelSize(const cv::Mat &img, int windowSize, cv::Mat &c); + } +} +#endif +#endif +/*End of file*/ diff --git a/modules/stereo/src/matching.hpp b/modules/stereo/src/matching.hpp new file mode 100644 index 000000000..dab3816d8 --- /dev/null +++ b/modules/stereo/src/matching.hpp @@ -0,0 +1,620 @@ +//By downloading, copying, installing or using the software you agree to this license. +//If you do not agree to this license, do not download, install, +//copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// (3-clause BSD License) +// +//Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +//Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +//Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +//Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +//Copyright (C) 2015, OpenCV Foundation, all rights reserved. +//Copyright (C) 2015, Itseez Inc., all rights reserved. +//Third party copyrights are property of their respective owners. +// +//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 names of the copyright holders nor the names of the 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 copyright holders 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. + +/*****************************************************************************************************************\ +* The interface contains the main methods for computing the matching between the left and right images * +* * +\******************************************************************************************************************/ +#include "precomp.hpp" +#include + +#ifndef _OPENCV_MATCHING_HPP_ +#define _OPENCV_MATCHING_HPP_ +#ifdef __cplusplus + +namespace cv +{ + namespace stereo + { + class Matching + { + private: + //!The maximum disparity + int maxDisparity; + //!the factor by which we are multiplying the disparity + int scallingFactor; + //!the confidence to which a min disparity found is good or not + double confidenceCheck; + //!the LUT used in case SSE is not available + int hamLut[65537]; + //!function used for getting the minimum disparity from the cost volume" + static int minim(short *c, int iwpj, int widthDisp,const double confidence, const int search_region) + { + double mini, mini2, mini3; + mini = mini2 = mini3 = DBL_MAX; + int index = 0; + int iw = iwpj; + int widthDisp2; + widthDisp2 = widthDisp; + widthDisp -= 1; + for (int i = 0; i <= widthDisp; i++) + { + if (c[(iw + i * search_region) * widthDisp2 + i] < mini) + { + mini3 = mini2; + mini2 = mini; + mini = c[(iw + i * search_region) * widthDisp2 + i]; + index = i; + } + else if (c[(iw + i * search_region) * widthDisp2 + i] < mini2) + { + mini3 = mini2; + mini2 = c[(iw + i * search_region) * widthDisp2 + i]; + } + else if (c[(iw + i * search_region) * widthDisp2 + i] < mini3) + { + mini3 = c[(iw + i * search_region) * widthDisp2 + i]; + } + } + if(mini != 0) + { + if (mini3 / mini <= confidence) + return index; + } + return -1; + } + //!Interpolate in order to obtain better results + //!function for refining the disparity at sub pixel using simetric v + static double symetricVInterpolation(short *c, int iwjp, int widthDisp, int winDisp,const int search_region) + { + if (winDisp == 0 || winDisp == widthDisp - 1) + return winDisp; + double m2m1, m3m1, m3, m2, m1; + m2 = c[(iwjp + (winDisp - 1) * search_region) * widthDisp + winDisp - 1]; + m3 = c[(iwjp + (winDisp + 1) * search_region)* widthDisp + winDisp + 1]; + m1 = c[(iwjp + winDisp * search_region) * widthDisp + winDisp]; + m2m1 = m2 - m1; + m3m1 = m3 - m1; + if (m2m1 == 0 || m3m1 == 0) return winDisp; + double p; + p = 0; + if (m2 > m3) + { + p = (0.5 - 0.25 * ((m3m1 * m3m1) / (m2m1 * m2m1) + (m3m1 / m2m1))); + } + else + { + p = -1 * (0.5 - 0.25 * ((m2m1 * m2m1) / (m3m1 * m3m1) + (m2m1 / m3m1))); + } + if (p >= -0.5 && p <= 0.5) + p = winDisp + p; + return p; + } + //!a pre processing function that generates the Hamming LUT in case the algorithm will ever be used on platform where SSE is not available + void hammingLut() + { + for (int i = 0; i <= 65536; i++) + { + int dist = 0; + int j = i; + //we number the bits from our number + while (j) + { + dist = dist + 1; + j = j & (j - 1); + } + hamLut[i] = dist; + } + } + //!the class used in computing the hamming distance + class hammingDistance : public ParallelLoopBody + { + private: + int *left, *right; + short *c; + int v,kernelSize, width, height; + int MASK; + int *hammLut; + public : + hammingDistance(const Mat &leftImage, const Mat &rightImage, short *cost, int maxDisp, int kerSize, int *hammingLUT): + left((int *)leftImage.data), right((int *)rightImage.data), c(cost), v(maxDisp),kernelSize(kerSize),width(leftImage.cols), height(leftImage.rows), MASK(65535), hammLut(hammingLUT){} + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end ; i++) + { + int iw = i * width; + for (int j = kernelSize; j < width - kernelSize; j++) + { + int j2; + int xorul; + int iwj; + iwj = iw + j; + for (int d = 0; d <= v; d++) + { + j2 = (0 > j - d) ? (0) : (j - d); + xorul = left[(iwj)] ^ right[(iw + j2)]; +#if CV_SSE4_1 + c[(iwj)* (v + 1) + d] = (short)_mm_popcnt_u32(xorul); +#else + c[(iwj)* (v + 1) + d] = (short)(hammLut[xorul & MASK] + hammLut[(xorul >> 16) & MASK]); +#endif + } + } + } + } + }; + //!cost aggregation + class agregateCost:public ParallelLoopBody + { + private: + int win; + short *c, *parSum; + int maxDisp,width, height; + public: + agregateCost(const Mat &partialSums, int windowSize, int maxDispa, Mat &cost) + { + win = windowSize / 2; + c = (short *)cost.data; + maxDisp = maxDispa; + width = cost.cols / ( maxDisp + 1) - 1; + height = cost.rows - 1; + parSum = (short *)partialSums.data; + } + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end; i++) + { + int iwi = (i - 1) * width; + for (int j = win + 1; j <= width - win - 1; j++) + { + int w1 = ((i + win + 1) * width + j + win) * (maxDisp + 1); + int w2 = ((i - win) * width + j - win - 1) * (maxDisp + 1); + int w3 = ((i + win + 1) * width + j - win - 1) * (maxDisp + 1); + int w4 = ((i - win) * width + j + win) * (maxDisp + 1); + int w = (iwi + j - 1) * (maxDisp + 1); + for (int d = 0; d <= maxDisp; d++) + { + c[w + d] = parSum[w1 + d] + parSum[w2 + d] + - parSum[w3 + d] - parSum[w4 + d]; + } + } + } + } + }; + //!class that is responsable for generating the disparity map + class makeMap:public ParallelLoopBody + { + private: + //enum used to notify wether we are searching on the vertical ie (lr) or diagonal (rl) + enum {CV_VERTICAL_SEARCH, CV_DIAGONAL_SEARCH}; + int width,disparity,scallingFact,th; + double confCheck; + uint8_t *map; + short *c; + public: + makeMap(const Mat &costVolume, int threshold, int maxDisp, double confidence,int scale, Mat &mapFinal) + { + c = (short *)costVolume.data; + map = mapFinal.data; + disparity = maxDisp; + width = costVolume.cols / ( disparity + 1) - 1; + th = threshold; + scallingFact = scale; + confCheck = confidence; + } + void operator()(const cv::Range &r) const { + for (int i = r.start; i <= r.end ; i++) + { + int lr; + int v = -1; + double p1, p2; + int iw = i * width; + for (int j = 0; j < width; j++) + { + lr = Matching:: minim(c, iw + j, disparity + 1, confCheck,CV_VERTICAL_SEARCH); + if (lr != -1) + { + v = Matching::minim(c, iw + j - lr, disparity + 1, confCheck,CV_DIAGONAL_SEARCH); + if (v != -1) + { + p1 = Matching::symetricVInterpolation(c, iw + j - lr, disparity + 1, v,CV_DIAGONAL_SEARCH); + p2 = Matching::symetricVInterpolation(c, iw + j, disparity + 1, lr,CV_VERTICAL_SEARCH); + if (abs(p1 - p2) <= th) + map[iw + j] = (uint8_t)((p2)* scallingFact); + else + { + map[iw + j] = 0; + } + } + else + { + if (width - j <= disparity) + { + p2 = Matching::symetricVInterpolation(c, iw + j, disparity + 1, lr,CV_VERTICAL_SEARCH); + map[iw + j] = (uint8_t)(p2* scallingFact); + } + } + } + else + { + map[iw + j] = 0; + } + } + } + } + }; + //!median 1x9 paralelized filter + template + class Median1x9:public ParallelLoopBody + { + private: + T *original; + T *filtered; + int height, width; + public: + Median1x9(const Mat &originalImage, Mat &filteredImage) + { + original = (T *)originalImage.data; + filtered = (T *)filteredImage.data; + height = originalImage.rows; + width = originalImage.cols; + } + void operator()(const cv::Range &r) const{ + for (int m = r.start; m <= r.end; m++) + { + for (int n = 4; n < width - 4; ++n) + { + int k = 0; + T window[9]; + for (int i = n - 4; i <= n + 4; ++i) + window[k++] = original[m * width + i]; + for (int j = 0; j < 5; ++j) + { + int min = j; + for (int l = j + 1; l < 9; ++l) + if (window[l] < window[min]) + min = l; + const T temp = window[j]; + window[j] = window[min]; + window[min] = temp; + } + filtered[m * width + n] = window[4]; + } + } + } + }; + //!median 9x1 paralelized filter + template + class Median9x1:public ParallelLoopBody + { + private: + T *original; + T *filtered; + int height, width; + public: + Median9x1(const Mat &originalImage, Mat &filteredImage) + { + original = (T *)originalImage.data; + filtered = (T *)filteredImage.data; + height = originalImage.rows; + width = originalImage.cols; + } + void operator()(const Range &r) const{ + for (int n = r.start; n <= r.end; ++n) + { + for (int m = 4; m < height - 4; ++m) + { + int k = 0; + T window[9]; + for (int i = m - 4; i <= m + 4; ++i) + window[k++] = original[i * width + n]; + for (int j = 0; j < 5; j++) + { + int min = j; + for (int l = j + 1; l < 9; ++l) + if (window[l] < window[min]) + min = l; + const T temp = window[j]; + window[j] = window[min]; + window[min] = temp; + } + filtered[m * width + n] = window[4]; + } + } + } + }; + protected: + //arrays used in the region removal + Mat speckleY; + Mat speckleX; + Mat puss; + //int *specklePointX; + //int *specklePointY; + //long long *pus; + int previous_size; + //!method for setting the maximum disparity + void setMaxDisparity(int val) + { + CV_Assert(val > 10); + this->maxDisparity = val; + } + //!method for getting the disparity + int getMaxDisparity() + { + return this->maxDisparity; + } + //! a number by which the disparity will be multiplied for better display + void setScallingFactor(int val) + { + CV_Assert(val > 0); + this->scallingFactor = val; + } + //!method for getting the scalling factor + int getScallingFactor() + { + return scallingFactor; + } + //!setter for the confidence check + void setConfidence(double val) + { + CV_Assert(val >= 1); + this->confidenceCheck = val; + } + //getter for confidence check + double getConfidence() + { + return confidenceCheck; + } + //! Hamming distance computation method + //! leftImage and rightImage are the two transformed images + //! the cost is the resulted cost volume and kernel Size is the size of the matching window + void hammingDistanceBlockMatching(const Mat &leftImage, const Mat &rightImage, Mat &cost, const int kernelSize= 9) + { + CV_Assert(leftImage.cols == rightImage.cols); + CV_Assert(leftImage.rows == rightImage.rows); + CV_Assert(kernelSize % 2 != 0); + CV_Assert(cost.rows == leftImage.rows); + CV_Assert(cost.cols / (maxDisparity + 1) == leftImage.cols); + short *c = (short *)cost.data; + memset(c, 0, sizeof(c[0]) * leftImage.cols * leftImage.rows * (maxDisparity + 1)); + parallel_for_(cv::Range(kernelSize / 2,leftImage.rows - kernelSize / 2), hammingDistance(leftImage,rightImage,(short *)cost.data,maxDisparity,kernelSize / 2,hamLut)); + } + //preprocessing the cost volume in order to get it ready for aggregation + void costGathering(const Mat &hammingDistanceCost, Mat &cost) + { + CV_Assert(hammingDistanceCost.rows == hammingDistanceCost.rows); + CV_Assert(hammingDistanceCost.type() == CV_16S); + CV_Assert(cost.type() == CV_16S); + int maxDisp = maxDisparity; + int width = cost.cols / ( maxDisp + 1) - 1; + int height = cost.rows - 1; + short *c = (short *)cost.data; + short *ham = (short *)hammingDistanceCost.data; + memset(c, 0, sizeof(c[0]) * (width + 1) * (height + 1) * (maxDisp + 1)); + for (int i = 1; i <= height; i++) + { + int iw = i * width; + int iwi = (i - 1) * width; + for (int j = 1; j <= width; j++) + { + int iwj = (iw + j) * (maxDisp + 1); + int iwjmu = (iw + j - 1) * (maxDisp + 1); + int iwijmu = (iwi + j - 1) * (maxDisp + 1); + for (int d = 0; d <= maxDisp; d++) + { + c[iwj + d] = ham[iwijmu + d] + c[iwjmu + d]; + } + } + } + for (int i = 1; i <= height; i++) + { + for (int j = 1; j <= width; j++) + { + int iwj = (i * width + j) * (maxDisp + 1); + int iwjmu = ((i - 1) * width + j) * (maxDisp + 1); + for (int d = 0; d <= maxDisp; d++) + { + c[iwj + d] += c[iwjmu + d]; + } + } + } + } + //!The aggregation on the cost volume + void blockAgregation(const Mat &partialSums, int windowSize, Mat &cost) + { + CV_Assert(windowSize % 2 != 0); + CV_Assert(partialSums.rows == cost.rows); + CV_Assert(partialSums.cols == cost.cols); + int win = windowSize / 2; + short *c = (short *)cost.data; + int maxDisp = maxDisparity; + int width = cost.cols / ( maxDisp + 1) - 1; + int height = cost.rows - 1; + memset(c, 0, sizeof(c[0]) * width * height * (maxDisp + 1)); + parallel_for_(cv::Range(win + 1,height - win - 1), agregateCost(partialSums,windowSize,maxDisp,cost)); + } + //!remove small regions that have an area smaller than t, we fill the region with the average of the good pixels around it + template + void smallRegionRemoval(const Mat ¤tMap, int t, Mat &out) + { + CV_Assert(currentMap.cols == out.cols); + CV_Assert(currentMap.rows == out.rows); + CV_Assert(t >= 0); + int *pus = (int *)puss.data; + int *specklePointX = (int *)speckleX.data; + int *specklePointY = (int *)speckleY.data; + memset(pus, 0, previous_size * sizeof(pus[0])); + T *map = (T *)currentMap.data; + T *outputMap = (T *)out.data; + int height = currentMap.rows; + int width = currentMap.cols; + T k = 1; + int st, dr; + int di[] = { -1, -1, -1, 0, 1, 1, 1, 0 }, + dj[] = { -1, 0, 1, 1, 1, 0, -1, -1 }; + int speckle_size = 0; + st = 0; + dr = 0; + for (int i = 1; i < height - 1; i++) + { + int iw = i * width; + for (int j = 1; j < width - 1; j++) + { + if (map[iw + j] != 0) + { + outputMap[iw + j] = map[iw + j]; + } + else if (map[iw + j] == 0) + { + T nr = 1; + T avg = 0; + speckle_size = dr; + specklePointX[dr] = i; + specklePointY[dr] = j; + pus[i * width + j] = 1; + dr++; + map[iw + j] = k; + while (st < dr) + { + int ii = specklePointX[st]; + int jj = specklePointY[st]; + //going on 8 directions + for (int d = 0; d < 8; d++) + {//if insisde + if (ii + di[d] >= 0 && ii + di[d] < height && jj + dj[d] >= 0 && jj + dj[d] < width && + pus[(ii + di[d]) * width + jj + dj[d]] == 0) + { + T val = map[(ii + di[d]) * width + jj + dj[d]]; + if (val == 0) + { + map[(ii + di[d]) * width + jj + dj[d]] = k; + specklePointX[dr] = (ii + di[d]); + specklePointY[dr] = (jj + dj[d]); + dr++; + pus[(ii + di[d]) * width + jj + dj[d]] = 1; + }//this means that my point is a good point to be used in computing the final filling value + else if (val >= 1 && val < 250) + { + avg += val; + nr++; + } + } + } + st++; + }//if hole size is smaller than a specified threshold we fill the respective hole with the average of the good neighbours + if (st - speckle_size <= t) + { + T fillValue = (T)(avg / nr); + while (speckle_size < st) + { + int ii = specklePointX[speckle_size]; + int jj = specklePointY[speckle_size]; + outputMap[ii * width + jj] = fillValue; + speckle_size++; + } + } + } + } + } + } + //!Method responsible for generating the disparity map + //!function for generating disparity maps at sub pixel level + /* costVolume - represents the cost volume + * width, height - represent the width and height of the iage + *disparity - represents the maximum disparity + *map - is the disparity map that will result + *th - is the LR threshold + */ + void dispartyMapFormation(const Mat &costVolume, Mat &mapFinal, int th) + { + uint8_t *map = mapFinal.data; + int disparity = maxDisparity; + int width = costVolume.cols / ( disparity + 1) - 1; + int height = costVolume.rows - 1; + memset(map, 0, sizeof(map[0]) * width * height); + parallel_for_(Range(0,height - 1), makeMap(costVolume,th,disparity,confidenceCheck,scallingFactor,mapFinal)); + } + public: + //!a median filter of 1x9 and 9x1 + //!1x9 median filter + template + void Median1x9Filter(const Mat &originalImage, Mat &filteredImage) + { + CV_Assert(originalImage.rows == filteredImage.rows); + CV_Assert(originalImage.cols == filteredImage.cols); + parallel_for_(Range(1,originalImage.rows - 2), Median1x9(originalImage,filteredImage)); + } + //!9x1 median filter + template + void Median9x1Filter(const Mat &originalImage, Mat &filteredImage) + { + CV_Assert(originalImage.cols == filteredImage.cols); + CV_Assert(originalImage.cols == filteredImage.cols); + parallel_for_(Range(1,originalImage.cols - 2), Median9x1(originalImage,filteredImage)); + } + //!constructor for the matching class + //!maxDisp - represents the maximum disparity + Matching(void) + { + hammingLut(); + } + ~Matching(void) + { + } + //constructor for the matching class + //maxDisp - represents the maximum disparity + //confidence - represents the confidence check + Matching(int maxDisp, int scalling = 4, int confidence = 6) + { + //set the maximum disparity + setMaxDisparity(maxDisp); + //set scalling factor + setScallingFactor(scalling); + //set the value for the confidence + setConfidence(confidence); + //generate the hamming lut in case SSE is not available + hammingLut(); + } + }; + } +} +#endif +#endif +/*End of file*/ \ No newline at end of file diff --git a/modules/stereo/src/precomp.hpp b/modules/stereo/src/precomp.hpp index cbabeeced..cbb1ffd2a 100644 --- a/modules/stereo/src/precomp.hpp +++ b/modules/stereo/src/precomp.hpp @@ -56,4 +56,3 @@ #include #endif - diff --git a/modules/stereo/src/stereo_binary_bm.cpp b/modules/stereo/src/stereo_binary_bm.cpp index 5f1e48e26..ce262e76d 100644 --- a/modules/stereo/src/stereo_binary_bm.cpp +++ b/modules/stereo/src/stereo_binary_bm.cpp @@ -46,693 +46,482 @@ \****************************************************************************************/ #include "precomp.hpp" +#include "descriptor.hpp" +#include "matching.hpp" #include #include namespace cv { - namespace stereo - { - struct StereoBinaryBMParams - { - StereoBinaryBMParams(int _numDisparities = 64, int _SADWindowSize = 9) - { - preFilterType = StereoBinaryBM::PREFILTER_XSOBEL; - preFilterSize = 9; - preFilterCap = 31; - SADWindowSize = _SADWindowSize; - minDisparity = 0; - numDisparities = _numDisparities > 0 ? _numDisparities : 64; - textureThreshold = 10; - uniquenessRatio = 15; - speckleRange = speckleWindowSize = 0; - roi1 = roi2 = Rect(0, 0, 0, 0); - disp12MaxDiff = -1; - dispType = CV_16S; - } - - int preFilterType; - int preFilterSize; - int preFilterCap; - int SADWindowSize; - int minDisparity; - int numDisparities; - int textureThreshold; - int uniquenessRatio; - int speckleRange; - int speckleWindowSize; - Rect roi1, roi2; - int disp12MaxDiff; - int dispType; - }; - - static void prefilterNorm(const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf) - { - int x, y, wsz2 = winsize / 2; - int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32); - int scale_g = winsize*winsize / 8, scale_s = (1024 + scale_g) / (scale_g * 2); - const int OFS = 256 * 5, TABSZ = OFS * 2 + 256; - uchar tab[TABSZ]; - const uchar* sptr = src.ptr(); - int srcstep = (int)src.step; - Size size = src.size(); - - scale_g *= scale_s; - - for (x = 0; x < TABSZ; x++) - tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero); - - for (x = 0; x < size.width; x++) - vsum[x] = (ushort)(sptr[x] * (wsz2 + 2)); - - for (y = 1; y < wsz2; y++) - { - for (x = 0; x < size.width; x++) - vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]); - } - - for (y = 0; y < size.height; y++) - { - const uchar* top = sptr + srcstep*MAX(y - wsz2 - 1, 0); - const uchar* bottom = sptr + srcstep*MIN(y + wsz2, size.height - 1); - const uchar* prev = sptr + srcstep*MAX(y - 1, 0); - const uchar* curr = sptr + srcstep*y; - const uchar* next = sptr + srcstep*MIN(y + 1, size.height - 1); - uchar* dptr = dst.ptr(y); - - for (x = 0; x < size.width; x++) - vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]); - - for (x = 0; x <= wsz2; x++) - { - vsum[-x - 1] = vsum[0]; - vsum[size.width + x] = vsum[size.width - 1]; - } - - int sum = vsum[0] * (wsz2 + 1); - for (x = 1; x <= wsz2; x++) - sum += vsum[x]; - - int val = ((curr[0] * 5 + curr[1] + prev[0] + next[0])*scale_g - sum*scale_s) >> 10; - dptr[0] = tab[val + OFS]; - - for (x = 1; x < size.width - 1; x++) - { - sum += vsum[x + wsz2] - vsum[x - wsz2 - 1]; - val = ((curr[x] * 4 + curr[x - 1] + curr[x + 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10; - dptr[x] = tab[val + OFS]; - } - - sum += vsum[x + wsz2] - vsum[x - wsz2 - 1]; - val = ((curr[x] * 5 + curr[x - 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10; - dptr[x] = tab[val + OFS]; - } - } - - static void - prefilterXSobel(const Mat& src, Mat& dst, int ftzero) - { - int x, y; - const int OFS = 256 * 4, TABSZ = OFS * 2 + 256; - uchar tab[TABSZ]; - Size size = src.size(); - - for (x = 0; x < TABSZ; x++) - tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero); - uchar val0 = tab[0 + OFS]; + namespace stereo + { + + struct StereoBinaryBMParams + { + StereoBinaryBMParams(int _numDisparities = 64, int _kernelSize = 9) + { + preFilterType = StereoBinaryBM::PREFILTER_XSOBEL; + preFilterSize = 9; + preFilterCap = 31; + kernelSize = _kernelSize; + minDisparity = 0; + numDisparities = _numDisparities > 0 ? _numDisparities : 64; + textureThreshold = 10; + uniquenessRatio = 15; + speckleRange = speckleWindowSize = 0; + disp12MaxDiff = -1; + dispType = CV_16S; + usePrefilter = false; + regionRemoval = 1; + scalling = 4; + kernelType = CV_MODIFIED_CENSUS_TRANSFORM; + agregationWindowSize = 9; + } + + int preFilterType; + int preFilterSize; + int preFilterCap; + int kernelSize; + int minDisparity; + int numDisparities; + int textureThreshold; + int uniquenessRatio; + int speckleRange; + int speckleWindowSize; + int disp12MaxDiff; + int dispType; + int scalling; + bool usePrefilter; + int regionRemoval; + int kernelType; + int agregationWindowSize; + }; + + static void prefilterNorm(const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf) + { + int x, y, wsz2 = winsize / 2; + int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32); + int scale_g = winsize*winsize / 8, scale_s = (1024 + scale_g) / (scale_g * 2); + const int OFS = 256 * 5, TABSZ = OFS * 2 + 256; + uchar tab[TABSZ]; + const uchar* sptr = src.ptr(); + int srcstep = (int)src.step; + Size size = src.size(); + + scale_g *= scale_s; + + for (x = 0; x < TABSZ; x++) + tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero); + + for (x = 0; x < size.width; x++) + vsum[x] = (ushort)(sptr[x] * (wsz2 + 2)); + for (y = 1; y < wsz2; y++) + { + for (x = 0; x < size.width; x++) + vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]); + } + for (y = 0; y < size.height; y++) + { + const uchar* top = sptr + srcstep*MAX(y - wsz2 - 1, 0); + const uchar* bottom = sptr + srcstep*MIN(y + wsz2, size.height - 1); + const uchar* prev = sptr + srcstep*MAX(y - 1, 0); + const uchar* curr = sptr + srcstep*y; + const uchar* next = sptr + srcstep*MIN(y + 1, size.height - 1); + uchar* dptr = dst.ptr(y); + for (x = 0; x < size.width; x++) + vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]); + + for (x = 0; x <= wsz2; x++) + { + vsum[-x - 1] = vsum[0]; + vsum[size.width + x] = vsum[size.width - 1]; + } + + int sum = vsum[0] * (wsz2 + 1); + for (x = 1; x <= wsz2; x++) + sum += vsum[x]; + int val = ((curr[0] * 5 + curr[1] + prev[0] + next[0])*scale_g - sum*scale_s) >> 10; + dptr[0] = tab[val + OFS]; + for (x = 1; x < size.width - 1; x++) + { + sum += vsum[x + wsz2] - vsum[x - wsz2 - 1]; + val = ((curr[x] * 4 + curr[x - 1] + curr[x + 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10; + dptr[x] = tab[val + OFS]; + } + + sum += vsum[x + wsz2] - vsum[x - wsz2 - 1]; + val = ((curr[x] * 5 + curr[x - 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10; + dptr[x] = tab[val + OFS]; + } + } + + static void + prefilterXSobel(const Mat& src, Mat& dst, int ftzero) + { + int x, y; + const int OFS = 256 * 4, TABSZ = OFS * 2 + 256; + uchar tab[TABSZ]; + Size size = src.size(); + + for (x = 0; x < TABSZ; x++) + tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero); + uchar val0 = tab[0 + OFS]; #if CV_SSE2 - volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); + volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); #endif - for (y = 0; y < size.height - 1; y += 2) - { - const uchar* srow1 = src.ptr(y); - const uchar* srow0 = y > 0 ? srow1 - src.step : size.height > 1 ? srow1 + src.step : srow1; - const uchar* srow2 = y < size.height - 1 ? srow1 + src.step : size.height > 1 ? srow1 - src.step : srow1; - const uchar* srow3 = y < size.height - 2 ? srow1 + src.step * 2 : srow1; - uchar* dptr0 = dst.ptr(y); - uchar* dptr1 = dptr0 + dst.step; + for (y = 0; y < size.height - 1; y += 2) + { + const uchar* srow1 = src.ptr(y); + const uchar* srow0 = y > 0 ? srow1 - src.step : size.height > 1 ? srow1 + src.step : srow1; + const uchar* srow2 = y < size.height - 1 ? srow1 + src.step : size.height > 1 ? srow1 - src.step : srow1; + const uchar* srow3 = y < size.height - 2 ? srow1 + src.step * 2 : srow1; + uchar* dptr0 = dst.ptr(y); + uchar* dptr1 = dptr0 + dst.step; - dptr0[0] = dptr0[size.width - 1] = dptr1[0] = dptr1[size.width - 1] = val0; - x = 1; + dptr0[0] = dptr0[size.width - 1] = dptr1[0] = dptr1[size.width - 1] = val0; + x = 1; #if CV_SSE2 - if (useSIMD) - { - __m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero), - ftz2 = _mm_set1_epi8(cv::saturate_cast(ftzero * 2)); - for (; x <= size.width - 9; x += 8) - { - __m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z); - __m128i c1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x - 1)), z); - __m128i d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x + 1)), z); - __m128i d1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x + 1)), z); - - d0 = _mm_sub_epi16(d0, c0); - d1 = _mm_sub_epi16(d1, c1); - - __m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z); - __m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x - 1)), z); - __m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z); - __m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x + 1)), z); - - d2 = _mm_sub_epi16(d2, c2); - d3 = _mm_sub_epi16(d3, c3); - - __m128i v0 = _mm_add_epi16(d0, _mm_add_epi16(d2, _mm_add_epi16(d1, d1))); - __m128i v1 = _mm_add_epi16(d1, _mm_add_epi16(d3, _mm_add_epi16(d2, d2))); - v0 = _mm_packus_epi16(_mm_add_epi16(v0, ftz), _mm_add_epi16(v1, ftz)); - v0 = _mm_min_epu8(v0, ftz2); - - _mm_storel_epi64((__m128i*)(dptr0 + x), v0); - _mm_storel_epi64((__m128i*)(dptr1 + x), _mm_unpackhi_epi64(v0, v0)); - } - } + if (useSIMD) + { + __m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero), + ftz2 = _mm_set1_epi8(cv::saturate_cast(ftzero * 2)); + for (; x <= size.width - 9; x += 8) + { + __m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z); + __m128i c1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x - 1)), z); + __m128i d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x + 1)), z); + __m128i d1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x + 1)), z); + + d0 = _mm_sub_epi16(d0, c0); + d1 = _mm_sub_epi16(d1, c1); + + __m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z); + __m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x - 1)), z); + __m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z); + __m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x + 1)), z); + + d2 = _mm_sub_epi16(d2, c2); + d3 = _mm_sub_epi16(d3, c3); + + __m128i v0 = _mm_add_epi16(d0, _mm_add_epi16(d2, _mm_add_epi16(d1, d1))); + __m128i v1 = _mm_add_epi16(d1, _mm_add_epi16(d3, _mm_add_epi16(d2, d2))); + v0 = _mm_packus_epi16(_mm_add_epi16(v0, ftz), _mm_add_epi16(v1, ftz)); + v0 = _mm_min_epu8(v0, ftz2); + + _mm_storel_epi64((__m128i*)(dptr0 + x), v0); + _mm_storel_epi64((__m128i*)(dptr1 + x), _mm_unpackhi_epi64(v0, v0)); + } + } #endif - for (; x < size.width - 1; x++) - { - int d0 = srow0[x + 1] - srow0[x - 1], d1 = srow1[x + 1] - srow1[x - 1], - d2 = srow2[x + 1] - srow2[x - 1], d3 = srow3[x + 1] - srow3[x - 1]; - int v0 = tab[d0 + d1 * 2 + d2 + OFS]; - int v1 = tab[d1 + d2 * 2 + d3 + OFS]; - dptr0[x] = (uchar)v0; - dptr1[x] = (uchar)v1; - } - } - - for (; y < size.height; y++) - { - uchar* dptr = dst.ptr(y); - for (x = 0; x < size.width; x++) - dptr[x] = val0; - } - } - - static const int DISPARITY_SHIFT = 4; - - static void - findStereoCorrespondenceBM(const Mat& left, const Mat& right, - Mat& disp, Mat& cost, const StereoBinaryBMParams& state, - uchar* buf, int _dy0, int _dy1) - { - const int ALIGN = 16; - int x, y, d; - int wsz = state.SADWindowSize, wsz2 = wsz / 2; - int dy0 = MIN(_dy0, wsz2 + 1), dy1 = MIN(_dy1, wsz2 + 1); - int ndisp = state.numDisparities; - int mindisp = state.minDisparity; - int lofs = MAX(ndisp - 1 + mindisp, 0); - int rofs = -MIN(ndisp - 1 + mindisp, 0); - int width = left.cols, height = left.rows; - int width1 = width - rofs - ndisp + 1; - int ftzero = state.preFilterCap; - int textureThreshold = state.textureThreshold; - int uniquenessRatio = state.uniquenessRatio; - short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT); - - int *sad, *hsad0, *hsad, *hsad_sub, *htext; - uchar *cbuf0, *cbuf; - const uchar* lptr0 = left.ptr() + lofs; - const uchar* rptr0 = right.ptr() + rofs; - const uchar *lptr, *lptr_sub, *rptr; - short* dptr = disp.ptr(); - int sstep = (int)left.step; - int dstep = (int)(disp.step / sizeof(dptr[0])); - int cstep = (height + dy0 + dy1)*ndisp; - int costbuf = 0; - int coststep = cost.data ? (int)(cost.step / sizeof(costbuf)) : 0; - const int TABSZ = 256; - uchar tab[TABSZ]; - - sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN); - hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN); - htext = (int*)alignPtr((int*)(hsad0 + (height + dy1)*ndisp) + wsz2 + 2, ALIGN); - cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN); - - for (x = 0; x < TABSZ; x++) - tab[x] = (uchar)std::abs(x - ftzero); - - // initialize buffers - memset(hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0])); - memset(htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0])); - - for (x = -wsz2 - 1; x < wsz2; x++) - { - hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp; - lptr = lptr0 + std::min(std::max(x, -lofs), width - lofs - 1) - dy0*sstep; - rptr = rptr0 + std::min(std::max(x, -rofs), width - rofs - 1) - dy0*sstep; - for (y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep) - { - int lval = lptr[0]; - for (d = 0; d < ndisp; d++) - { - int diff = std::abs(lval - rptr[d]); - cbuf[d] = (uchar)diff; - hsad[d] = (int)(hsad[d] + diff); - } - htext[y] += tab[lval]; - } - } - - // initialize the left and right borders of the disparity map - for (y = 0; y < height; y++) - { - for (x = 0; x < lofs; x++) - dptr[y*dstep + x] = FILTERED; - for (x = lofs + width1; x < width; x++) - dptr[y*dstep + x] = FILTERED; - } - dptr += lofs; - - for (x = 0; x < width1; x++, dptr++) - { - int* costptr = cost.data ? cost.ptr() + lofs + x : &costbuf; - int x0 = x - wsz2 - 1, x1 = x + wsz2; - const uchar* cbuf_sub = cbuf0 + ((x0 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp; - cbuf = cbuf0 + ((x1 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp; - hsad = hsad0 - dy0*ndisp; - lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width - 1 - lofs) - dy0*sstep; - lptr = lptr0 + MIN(MAX(x1, -lofs), width - 1 - lofs) - dy0*sstep; - rptr = rptr0 + MIN(MAX(x1, -rofs), width - 1 - rofs) - dy0*sstep; - - for (y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp, - hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep) - { - int lval = lptr[0]; - for (d = 0; d < ndisp; d++) - { - int diff = std::abs(lval - rptr[d]); - cbuf[d] = (uchar)diff; - hsad[d] = hsad[d] + diff - cbuf_sub[d]; - } - htext[y] += tab[lval] - tab[lptr_sub[0]]; - } - - // fill borders - for (y = dy1; y <= wsz2; y++) - htext[height + y] = htext[height + dy1 - 1]; - for (y = -wsz2 - 1; y < -dy0; y++) - htext[y] = htext[-dy0]; - - // initialize sums - int tsum = 0; - { - for (d = 0; d < ndisp; d++) - sad[d] = (int)(hsad0[d - ndisp*dy0] * (wsz2 + 2 - dy0)); - - hsad = hsad0 + (1 - dy0)*ndisp; - for (y = 1 - dy0; y < wsz2; y++, hsad += ndisp) - for (d = 0; d < ndisp; d++) - sad[d] = (int)(sad[d] + hsad[d]); - - for (y = -wsz2 - 1; y < wsz2; y++) - tsum += htext[y]; - } - // finally, start the real processing - { - for (y = 0; y < height; y++) - { - int minsad = INT_MAX, mind = -1; - hsad = hsad0 + MIN(y + wsz2, height + dy1 - 1)*ndisp; - hsad_sub = hsad0 + MAX(y - wsz2 - 1, -dy0)*ndisp; - - for (d = 0; d < ndisp; d++) - { - int currsad = sad[d] + hsad[d] - hsad_sub[d]; - sad[d] = currsad; - if (currsad < minsad) - { - minsad = currsad; - mind = d; - } - } - - tsum += htext[y + wsz2] - htext[y - wsz2 - 1]; - if (tsum < textureThreshold) - { - dptr[y*dstep] = FILTERED; - continue; - } - - if (uniquenessRatio > 0) - { - int thresh = minsad + (minsad * uniquenessRatio / 100); - for (d = 0; d < ndisp; d++) - { - if ((d < mind - 1 || d > mind + 1) && sad[d] <= thresh) - break; - } - if (d < ndisp) - { - dptr[y*dstep] = FILTERED; - continue; - } - } - - { - sad[-1] = sad[1]; - sad[ndisp] = sad[ndisp - 2]; - int p = sad[mind + 1], n = sad[mind - 1]; - d = p + n - 2 * sad[mind] + std::abs(p - n); - dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp) * 256 + (d != 0 ? (p - n) * 256 / d : 0) + 15) >> 4); - costptr[y*coststep] = sad[mind]; - } - } - } - } - } - - - struct PrefilterInvoker : public ParallelLoopBody - { - PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right, - uchar* buf0, uchar* buf1, StereoBinaryBMParams* _state) - { - imgs0[0] = &left0; imgs0[1] = &right0; - imgs[0] = &left; imgs[1] = &right; - buf[0] = buf0; buf[1] = buf1; - state = _state; - } - - void operator()(const Range& range) const - { - for (int i = range.start; i < range.end; i++) - { - if (state->preFilterType == StereoBinaryBM::PREFILTER_NORMALIZED_RESPONSE) - prefilterNorm(*imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i]); - else - prefilterXSobel(*imgs0[i], *imgs[i], state->preFilterCap); - } - } - - const Mat* imgs0[2]; - Mat* imgs[2]; - uchar* buf[2]; - StereoBinaryBMParams* state; - }; - - struct FindStereoCorrespInvoker : public ParallelLoopBody - { - FindStereoCorrespInvoker(const Mat& _left, const Mat& _right, - Mat& _disp, StereoBinaryBMParams* _state, - int _nstripes, size_t _stripeBufSize, - bool _useShorts, Rect _validDisparityRect, - Mat& _slidingSumBuf, Mat& _cost) - { - left = &_left; right = &_right; - disp = &_disp; state = _state; - nstripes = _nstripes; stripeBufSize = _stripeBufSize; - useShorts = _useShorts; - validDisparityRect = _validDisparityRect; - slidingSumBuf = &_slidingSumBuf; - cost = &_cost; - } - - void operator()(const Range& range) const - { - int cols = left->cols, rows = left->rows; - int _row0 = std::min(cvRound(range.start * rows / nstripes), rows); - int _row1 = std::min(cvRound(range.end * rows / nstripes), rows); - uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize; - int FILTERED = (state->minDisparity - 1) * 16; - - Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0); - if (roi.height == 0) - return; - int row0 = roi.y; - int row1 = roi.y + roi.height; - - Mat part; - if (row0 > _row0) - { - part = disp->rowRange(_row0, row0); - part = Scalar::all(FILTERED); - } - if (_row1 > row1) - { - part = disp->rowRange(row1, _row1); - part = Scalar::all(FILTERED); - } - - Mat left_i = left->rowRange(row0, row1); - Mat right_i = right->rowRange(row0, row1); - Mat disp_i = disp->rowRange(row0, row1); - Mat cost_i = state->disp12MaxDiff >= 0 ? cost->rowRange(row0, row1) : Mat(); - - findStereoCorrespondenceBM(left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1); - - if (state->disp12MaxDiff >= 0) - validateDisparity(disp_i, cost_i, state->minDisparity, state->numDisparities, state->disp12MaxDiff); - - if (roi.x > 0) - { - part = disp_i.colRange(0, roi.x); - part = Scalar::all(FILTERED); - } - if (roi.x + roi.width < cols) - { - part = disp_i.colRange(roi.x + roi.width, cols); - part = Scalar::all(FILTERED); - } - } - - protected: - const Mat *left, *right; - Mat* disp, *slidingSumBuf, *cost; - StereoBinaryBMParams *state; - - int nstripes; - size_t stripeBufSize; - bool useShorts; - Rect validDisparityRect; - }; - - class StereoBinaryBMImpl : public StereoBinaryBM - { - public: - StereoBinaryBMImpl() - { - params = StereoBinaryBMParams(); - } - - StereoBinaryBMImpl(int _numDisparities, int _SADWindowSize) - { - params = StereoBinaryBMParams(_numDisparities, _SADWindowSize); - } - - void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr) - { - int dtype = disparr.fixedType() ? disparr.type() : params.dispType; - Size leftsize = leftarr.size(); - - if (leftarr.size() != rightarr.size()) - CV_Error(Error::StsUnmatchedSizes, "All the images must have the same size"); - - if (leftarr.type() != CV_8UC1 || rightarr.type() != CV_8UC1) - CV_Error(Error::StsUnsupportedFormat, "Both input images must have CV_8UC1"); - - if (dtype != CV_16SC1 && dtype != CV_32FC1) - CV_Error(Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format"); - - if (params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && - params.preFilterType != PREFILTER_XSOBEL) - CV_Error(Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE"); - - if (params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0) - CV_Error(Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255"); - - if (params.preFilterCap < 1 || params.preFilterCap > 63) - CV_Error(Error::StsOutOfRange, "preFilterCap must be within 1..63"); - - if (params.SADWindowSize < 5 || params.SADWindowSize > 255 || params.SADWindowSize % 2 == 0 || - params.SADWindowSize >= std::min(leftsize.width, leftsize.height)) - CV_Error(Error::StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height"); - - if (params.numDisparities <= 0 || params.numDisparities % 16 != 0) - CV_Error(Error::StsOutOfRange, "numDisparities must be positive and divisble by 16"); - - if (params.textureThreshold < 0) - CV_Error(Error::StsOutOfRange, "texture threshold must be non-negative"); - - if (params.uniquenessRatio < 0) - CV_Error(Error::StsOutOfRange, "uniqueness ratio must be non-negative"); - - int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT; - - - Mat left0 = leftarr.getMat(), right0 = rightarr.getMat(); - disparr.create(left0.size(), dtype); - Mat disp0 = disparr.getMat(); - - preFilteredImg0.create(left0.size(), CV_8U); - preFilteredImg1.create(left0.size(), CV_8U); - cost.create(left0.size(), CV_16S); - - Mat left = preFilteredImg0, right = preFilteredImg1; - - int mindisp = params.minDisparity; - int ndisp = params.numDisparities; - - int width = left0.cols; - int height = left0.rows; - int lofs = std::max(ndisp - 1 + mindisp, 0); - int rofs = -std::min(ndisp - 1 + mindisp, 0); - int width1 = width - rofs - ndisp + 1; - - if (lofs >= width || rofs >= width || width1 < 1) - { - disp0 = Scalar::all(FILTERED * (disp0.type() < CV_32F ? 1 : 1. / (1 << DISPARITY_SHIFT))); - return; - } - - Mat disp = disp0; - if (dtype == CV_32F) - { - dispbuf.create(disp0.size(), CV_16S); - disp = dispbuf; - } - - int wsz = params.SADWindowSize; - int bufSize0 = (int)((ndisp + 2)*sizeof(int)); - bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int)); - bufSize0 += (int)((height + wsz + 2)*sizeof(int)); - bufSize0 += (int)((height + wsz + 2)*ndisp*(wsz + 2)*sizeof(uchar) + 256); - - int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256); - int bufSize2 = 0; - if (params.speckleRange >= 0 && params.speckleWindowSize > 0) - bufSize2 = width*height*(sizeof(Point_) + sizeof(int) + sizeof(uchar)); - -#if CV_SSE2 - bool useShorts = params.preFilterCap <= 31 && params.SADWindowSize <= 21 && checkHardwareSupport(CV_CPU_SSE2); -#else - const bool useShorts = false; -#endif - - const double SAD_overhead_coeff = 10.0; - double N0 = 8000000 / (useShorts ? 1 : 4); // approx tbb's min number instructions reasonable for one thread - double maxStripeSize = std::min(std::max(N0 / (width * ndisp), (wsz - 1) * SAD_overhead_coeff), (double)height); - int nstripes = cvCeil(height / maxStripeSize); - int bufSize = std::max(bufSize0 * nstripes, std::max(bufSize1 * 2, bufSize2)); - - if (slidingSumBuf.cols < bufSize) - slidingSumBuf.create(1, bufSize, CV_8U); - - uchar *_buf = slidingSumBuf.ptr(); - - parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, ¶ms), 1); - - Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2; - validDisparityRect = getValidDisparityROI(R1.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect, - R2.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect, - params.minDisparity, params.numDisparities, - params.SADWindowSize); - - parallel_for_(Range(0, nstripes), - FindStereoCorrespInvoker(left, right, disp, ¶ms, nstripes, - bufSize0, useShorts, validDisparityRect, - slidingSumBuf, cost)); - - if (params.speckleRange >= 0 && params.speckleWindowSize > 0) - filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); - - if (disp0.data != disp.data) - disp.convertTo(disp0, disp0.type(), 1. / (1 << DISPARITY_SHIFT), 0); - } - - int getMinDisparity() const { return params.minDisparity; } - void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } - - int getNumDisparities() const { return params.numDisparities; } - void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } - - int getBlockSize() const { return params.SADWindowSize; } - void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } - - int getSpeckleWindowSize() const { return params.speckleWindowSize; } - void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } - - int getSpeckleRange() const { return params.speckleRange; } - void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } - - int getDisp12MaxDiff() const { return params.disp12MaxDiff; } - void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } - - int getPreFilterType() const { return params.preFilterType; } - void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; } - - int getPreFilterSize() const { return params.preFilterSize; } - void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; } - - int getPreFilterCap() const { return params.preFilterCap; } - void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } - - int getTextureThreshold() const { return params.textureThreshold; } - void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; } - - int getUniquenessRatio() const { return params.uniquenessRatio; } - void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } - - int getSmallerBlockSize() const { return 0; } - void setSmallerBlockSize(int) {} - - Rect getROI1() const { return params.roi1; } - void setROI1(Rect roi1) { params.roi1 = roi1; } - - Rect getROI2() const { return params.roi2; } - void setROI2(Rect roi2) { params.roi2 = roi2; } - - void write(FileStorage& fs) const - { - fs << "name" << name_ - << "minDisparity" << params.minDisparity - << "numDisparities" << params.numDisparities - << "blockSize" << params.SADWindowSize - << "speckleWindowSize" << params.speckleWindowSize - << "speckleRange" << params.speckleRange - << "disp12MaxDiff" << params.disp12MaxDiff - << "preFilterType" << params.preFilterType - << "preFilterSize" << params.preFilterSize - << "preFilterCap" << params.preFilterCap - << "textureThreshold" << params.textureThreshold - << "uniquenessRatio" << params.uniquenessRatio; - } - - void read(const FileNode& fn) - { - FileNode n = fn["name"]; - CV_Assert(n.isString() && String(n) == name_); - params.minDisparity = (int)fn["minDisparity"]; - params.numDisparities = (int)fn["numDisparities"]; - params.SADWindowSize = (int)fn["blockSize"]; - params.speckleWindowSize = (int)fn["speckleWindowSize"]; - params.speckleRange = (int)fn["speckleRange"]; - params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; - params.preFilterType = (int)fn["preFilterType"]; - params.preFilterSize = (int)fn["preFilterSize"]; - params.preFilterCap = (int)fn["preFilterCap"]; - params.textureThreshold = (int)fn["textureThreshold"]; - params.uniquenessRatio = (int)fn["uniquenessRatio"]; - params.roi1 = params.roi2 = Rect(); - } - - StereoBinaryBMParams params; - Mat preFilteredImg0, preFilteredImg1, cost, dispbuf; - Mat slidingSumBuf; - - static const char* name_; - }; - - const char* StereoBinaryBMImpl::name_ = "StereoMatcher.BM"; - - Ptr StereoBinaryBM::create(int _numDisparities, int _SADWindowSize) - { - return makePtr(_numDisparities, _SADWindowSize); - } - } + for (; x < size.width - 1; x++) + { + int d0 = srow0[x + 1] - srow0[x - 1], d1 = srow1[x + 1] - srow1[x - 1], + d2 = srow2[x + 1] - srow2[x - 1], d3 = srow3[x + 1] - srow3[x - 1]; + int v0 = tab[d0 + d1 * 2 + d2 + OFS]; + int v1 = tab[d1 + d2 * 2 + d3 + OFS]; + dptr0[x] = (uchar)v0; + dptr1[x] = (uchar)v1; + } + } + + for (; y < size.height; y++) + { + uchar* dptr = dst.ptr(y); + for (x = 0; x < size.width; x++) + dptr[x] = val0; + } + } + + static const int DISPARITY_SHIFT = 4; + + struct PrefilterInvoker : public ParallelLoopBody + { + PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right, + uchar* buf0, uchar* buf1, StereoBinaryBMParams* _state) + { + imgs0[0] = &left0; imgs0[1] = &right0; + imgs[0] = &left; imgs[1] = &right; + buf[0] = buf0; buf[1] = buf1; + state = _state; + } + + void operator()(const Range& range) const + { + for (int i = range.start; i < range.end; i++) + { + if (state->preFilterType == StereoBinaryBM::PREFILTER_NORMALIZED_RESPONSE) + prefilterNorm(*imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i]); + else + prefilterXSobel(*imgs0[i], *imgs[i], state->preFilterCap); + } + } + + const Mat* imgs0[2]; + Mat* imgs[2]; + uchar* buf[2]; + StereoBinaryBMParams* state; + }; + + class StereoBinaryBMImpl : public StereoBinaryBM, public Matching + { + public: + StereoBinaryBMImpl(): Matching(64) + { + params = StereoBinaryBMParams(); + } + + StereoBinaryBMImpl(int _numDisparities, int _kernelSize) : Matching(_numDisparities) + { + params = StereoBinaryBMParams(_numDisparities, _kernelSize); + previous_size = 0; + } + + void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr) + { + int dtype = disparr.fixedType() ? disparr.type() : params.dispType; + Size leftsize = leftarr.size(); + + if (leftarr.size() != rightarr.size()) + CV_Error(Error::StsUnmatchedSizes, "All the images must have the same size"); + + if (leftarr.type() != CV_8UC1 || rightarr.type() != CV_8UC1) + CV_Error(Error::StsUnsupportedFormat, "Both input images must have CV_8UC1"); + + if (dtype != CV_16SC1 && dtype != CV_32FC1) + CV_Error(Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format"); + + if (params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && + params.preFilterType != PREFILTER_XSOBEL) + CV_Error(Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE"); + + if (params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0) + CV_Error(Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255"); + + if (params.preFilterCap < 1 || params.preFilterCap > 63) + CV_Error(Error::StsOutOfRange, "preFilterCap must be within 1..63"); + + if (params.kernelSize < 5 || params.kernelSize > 255 || params.kernelSize % 2 == 0 || + params.kernelSize >= std::min(leftsize.width, leftsize.height)) + CV_Error(Error::StsOutOfRange, "kernelSize must be odd, be within 5..255 and be not larger than image width or height"); + + if (params.numDisparities <= 0 || params.numDisparities % 16 != 0) + CV_Error(Error::StsOutOfRange, "numDisparities must be positive and divisble by 16"); + + if (params.textureThreshold < 0) + CV_Error(Error::StsOutOfRange, "texture threshold must be non-negative"); + + if (params.uniquenessRatio < 0) + CV_Error(Error::StsOutOfRange, "uniqueness ratio must be non-negative"); + + int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT; + + Mat left0 = leftarr.getMat(), right0 = rightarr.getMat(); + Mat disp0 = disparr.getMat(); + + int width = left0.cols; + int height = left0.rows; + if(previous_size != width * height) + { + previous_size = width * height; + speckleX.create(height,width,CV_32SC4); + speckleY.create(height,width,CV_32SC4); + puss.create(height,width,CV_32SC4); + + censusImage[0].create(left0.rows,left0.cols,CV_32SC4); + censusImage[1].create(left0.rows,left0.cols,CV_32SC4); + + partialSumsLR.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S); + agregatedHammingLRCost.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S); + hammingDistance.create(left0.rows, left0.cols * (params.numDisparities + 1),CV_16S); + + preFilteredImg0.create(left0.size(), CV_8U); + preFilteredImg1.create(left0.size(), CV_8U); + + aux.create(height,width,CV_8UC1); + } + + Mat left = preFilteredImg0, right = preFilteredImg1; + + int ndisp = params.numDisparities; + + int wsz = params.kernelSize; + int bufSize0 = (int)((ndisp + 2)*sizeof(int)); + bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int)); + bufSize0 += (int)((height + wsz + 2)*sizeof(int)); + bufSize0 += (int)((height + wsz + 2)*ndisp*(wsz + 2)*sizeof(uchar) + 256); + + int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256); + if(params.usePrefilter == true) + { + uchar *_buf = slidingSumBuf.ptr(); + + parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, ¶ms), 1); + } + else if(params.usePrefilter == false) + { + left = left0; + right = right0; + } + if(params.kernelType == CV_SPARSE_CENSUS) + { + censusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_SPARSE_CENSUS); + } + else if(params.kernelType == CV_DENSE_CENSUS) + { + censusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_SPARSE_CENSUS); + } + else if(params.kernelType == CV_CS_CENSUS) + { + symetricCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_CS_CENSUS); + } + else if(params.kernelType == CV_MODIFIED_CS_CENSUS) + { + symetricCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MODIFIED_CS_CENSUS); + } + else if(params.kernelType == CV_MODIFIED_CENSUS_TRANSFORM) + { + modifiedCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MODIFIED_CENSUS_TRANSFORM,0); + } + else if(params.kernelType == CV_MEAN_VARIATION) + { + parSumsIntensityImage[0].create(left0.rows, left0.cols,CV_32SC4); + parSumsIntensityImage[1].create(left0.rows, left0.cols,CV_32SC4); + Integral[0].create(left0.rows,left0.cols,CV_32SC4); + Integral[1].create(left0.rows,left0.cols,CV_32SC4); + integral(left, parSumsIntensityImage[0],CV_32S); + integral(right, parSumsIntensityImage[1],CV_32S); + imageMeanKernelSize(parSumsIntensityImage[0], params.kernelSize,Integral[0]); + imageMeanKernelSize(parSumsIntensityImage[1], params.kernelSize, Integral[1]); + modifiedCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MEAN_VARIATION,0,Integral[0], Integral[1]); + } + else if(params.kernelType == CV_STAR_KERNEL) + { + starCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1]); + } + hammingDistanceBlockMatching(censusImage[0], censusImage[1], hammingDistance); + costGathering(hammingDistance, partialSumsLR); + blockAgregation(partialSumsLR, params.agregationWindowSize, agregatedHammingLRCost); + dispartyMapFormation(agregatedHammingLRCost, disp0, 3); + Median1x9Filter(disp0, aux); + Median9x1Filter(aux,disp0); + + if(params.regionRemoval == CV_SPECKLE_REMOVAL_AVG_ALGORITHM) + { + smallRegionRemoval(disp0,params.speckleWindowSize,disp0); + } + else if(params.regionRemoval == CV_SPECKLE_REMOVAL_ALGORITHM) + { + if (params.speckleRange >= 0 && params.speckleWindowSize > 0) + filterSpeckles(disp0, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); + } + } + int getAgregationWindowSize() const { return params.agregationWindowSize;} + void setAgregationWindowSize(int value = 9) { CV_Assert(value % 2 != 0); params.agregationWindowSize = value;} + + int getBinaryKernelType() const { return params.kernelType;} + void setBinaryKernelType(int value = CV_MODIFIED_CENSUS_TRANSFORM) { CV_Assert(value < 7); params.kernelType = value; } + + int getSpekleRemovalTechnique() const { return params.regionRemoval;} + void setSpekleRemovalTechnique(int factor = CV_SPECKLE_REMOVAL_AVG_ALGORITHM) {CV_Assert(factor < 2); params.regionRemoval = factor; } + + bool getUsePrefilter() const { return params.usePrefilter;} + void setUsePrefilter(bool value = false) { params.usePrefilter = value;} + + int getScalleFactor() const { return params.scalling;} + void setScalleFactor(int factor = 4) {CV_Assert(factor > 0); params.scalling = factor; setScallingFactor(factor);} + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) {CV_Assert(minDisparity >= 0); params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) {CV_Assert(numDisparities > 0); params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.kernelSize; } + void setBlockSize(int blockSize) {CV_Assert(blockSize % 2 != 0); params.kernelSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) {CV_Assert(speckleWindowSize >= 0); params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) {CV_Assert(speckleRange >= 0); params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) {CV_Assert(disp12MaxDiff >= 0); params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterType() const { return params.preFilterType; } + void setPreFilterType(int preFilterType) { CV_Assert(preFilterType >= 0); params.preFilterType = preFilterType; } + + int getPreFilterSize() const { return params.preFilterSize; } + void setPreFilterSize(int preFilterSize) { CV_Assert(preFilterSize >= 0); params.preFilterSize = preFilterSize; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) {CV_Assert(preFilterCap >= 0); params.preFilterCap = preFilterCap; } + + int getTextureThreshold() const { return params.textureThreshold; } + void setTextureThreshold(int textureThreshold) {CV_Assert(textureThreshold >= 0); params.textureThreshold = textureThreshold; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) {CV_Assert(uniquenessRatio >= 0); params.uniquenessRatio = uniquenessRatio; } + + int getSmallerBlockSize() const { return 0; } + void setSmallerBlockSize(int) {} + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.kernelSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterType" << params.preFilterType + << "preFilterSize" << params.preFilterSize + << "preFilterCap" << params.preFilterCap + << "textureThreshold" << params.textureThreshold + << "uniquenessRatio" << params.uniquenessRatio; + } + + void read(const FileNode& fn) + { + FileNode n = fn["name"]; + CV_Assert(n.isString() && String(n) == name_); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.kernelSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterType = (int)fn["preFilterType"]; + params.preFilterSize = (int)fn["preFilterSize"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.textureThreshold = (int)fn["textureThreshold"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + } + + StereoBinaryBMParams params; + Mat preFilteredImg0, preFilteredImg1, cost, dispbuf; + Mat slidingSumBuf; + Mat parSumsIntensityImage[2]; + Mat Integral[2]; + Mat censusImage[2]; + Mat hammingDistance; + Mat partialSumsLR; + Mat agregatedHammingLRCost; + Mat aux; + static const char* name_; + }; + + const char* StereoBinaryBMImpl::name_ = "StereoBinaryMatcher.BM"; + + Ptr StereoBinaryBM::create(int _numDisparities, int _kernelSize) + { + return makePtr(_numDisparities, _kernelSize); + } + } } - /* End of file. */ - diff --git a/modules/stereo/src/stereo_binary_sgbm.cpp b/modules/stereo/src/stereo_binary_sgbm.cpp index 702195b4f..ed311e809 100644 --- a/modules/stereo/src/stereo_binary_sgbm.cpp +++ b/modules/stereo/src/stereo_binary_sgbm.cpp @@ -40,919 +40,789 @@ // the use of this software, even if advised of the possibility of such damage. // //M*/ - /* This is a variation of "Stereo Processing by Semiglobal Matching and Mutual Information" by Heiko Hirschmuller. - We match blocks rather than individual pixels, thus the algorithm is called SGBM (Semi-global block matching) */ #include "precomp.hpp" #include +#include +#include namespace cv { - namespace stereo - { - typedef uchar PixType; - typedef short CostType; - typedef short DispType; - - enum { NR = 16, NR2 = NR/2 }; - - - struct StereoBinarySGBMParams - { - StereoBinarySGBMParams() - { - minDisparity = numDisparities = 0; - SADWindowSize = 0; - P1 = P2 = 0; - disp12MaxDiff = 0; - preFilterCap = 0; - uniquenessRatio = 0; - speckleWindowSize = 0; - speckleRange = 0; - mode = StereoBinarySGBM::MODE_SGBM; - } - - StereoBinarySGBMParams( int _minDisparity, int _numDisparities, int _SADWindowSize, - int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, - int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - int _mode ) - { - minDisparity = _minDisparity; - numDisparities = _numDisparities; - SADWindowSize = _SADWindowSize; - P1 = _P1; - P2 = _P2; - disp12MaxDiff = _disp12MaxDiff; - preFilterCap = _preFilterCap; - uniquenessRatio = _uniquenessRatio; - speckleWindowSize = _speckleWindowSize; - speckleRange = _speckleRange; - mode = _mode; - } - - int minDisparity; - int numDisparities; - int SADWindowSize; - int preFilterCap; - int uniquenessRatio; - int P1; - int P2; - int speckleWindowSize; - int speckleRange; - int disp12MaxDiff; - int mode; - }; - - /* - For each pixel row1[x], max(-maxD, 0) <= minX <= x < maxX <= width - max(0, -minD), - and for each disparity minD<=d(y), *row2 = img2.ptr(y); - PixType *prow1 = buffer + width2*2, *prow2 = prow1 + width*cn*2; - - tab += tabOfs; - - for( c = 0; c < cn*2; c++ ) - { - prow1[width*c] = prow1[width*c + width-1] = - prow2[width*c] = prow2[width*c + width-1] = tab[0]; - } - - int n1 = y > 0 ? -(int)img1.step : 0, s1 = y < img1.rows-1 ? (int)img1.step : 0; - int n2 = y > 0 ? -(int)img2.step : 0, s2 = y < img2.rows-1 ? (int)img2.step : 0; - - if( cn == 1 ) - { - for( x = 1; x < width-1; x++ ) - { - prow1[x] = tab[(row1[x+1] - row1[x-1])*2 + row1[x+n1+1] - row1[x+n1-1] + row1[x+s1+1] - row1[x+s1-1]]; - prow2[width-1-x] = tab[(row2[x+1] - row2[x-1])*2 + row2[x+n2+1] - row2[x+n2-1] + row2[x+s2+1] - row2[x+s2-1]]; - - prow1[x+width] = row1[x]; - prow2[width-1-x+width] = row2[x]; - } - } - else - { - for( x = 1; x < width-1; x++ ) - { - prow1[x] = tab[(row1[x*3+3] - row1[x*3-3])*2 + row1[x*3+n1+3] - row1[x*3+n1-3] + row1[x*3+s1+3] - row1[x*3+s1-3]]; - prow1[x+width] = tab[(row1[x*3+4] - row1[x*3-2])*2 + row1[x*3+n1+4] - row1[x*3+n1-2] + row1[x*3+s1+4] - row1[x*3+s1-2]]; - prow1[x+width*2] = tab[(row1[x*3+5] - row1[x*3-1])*2 + row1[x*3+n1+5] - row1[x*3+n1-1] + row1[x*3+s1+5] - row1[x*3+s1-1]]; - - prow2[width-1-x] = tab[(row2[x*3+3] - row2[x*3-3])*2 + row2[x*3+n2+3] - row2[x*3+n2-3] + row2[x*3+s2+3] - row2[x*3+s2-3]]; - prow2[width-1-x+width] = tab[(row2[x*3+4] - row2[x*3-2])*2 + row2[x*3+n2+4] - row2[x*3+n2-2] + row2[x*3+s2+4] - row2[x*3+s2-2]]; - prow2[width-1-x+width*2] = tab[(row2[x*3+5] - row2[x*3-1])*2 + row2[x*3+n2+5] - row2[x*3+n2-1] + row2[x*3+s2+5] - row2[x*3+s2-1]]; - - prow1[x+width*3] = row1[x*3]; - prow1[x+width*4] = row1[x*3+1]; - prow1[x+width*5] = row1[x*3+2]; - - prow2[width-1-x+width*3] = row2[x*3]; - prow2[width-1-x+width*4] = row2[x*3+1]; - prow2[width-1-x+width*5] = row2[x*3+2]; - } - } - - memset( cost, 0, width1*D*sizeof(cost[0]) ); - - buffer -= minX2; - cost -= minX1*D + minD; // simplify the cost indices inside the loop - + namespace stereo + { + typedef uchar PixType; + typedef short CostType; + typedef short DispType; + enum { NR = 16, NR2 = NR/2 }; + + struct StereoBinarySGBMParams + { + StereoBinarySGBMParams() + { + minDisparity = numDisparities = 0; + kernelSize = 0; + P1 = P2 = 0; + disp12MaxDiff = 0; + preFilterCap = 0; + uniquenessRatio = 0; + speckleWindowSize = 0; + speckleRange = 0; + mode = StereoBinarySGBM::MODE_SGBM; + } + StereoBinarySGBMParams( int _minDisparity, int _numDisparities, int _SADWindowSize, + int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, + int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, + int _mode ) + { + minDisparity = _minDisparity; + numDisparities = _numDisparities; + kernelSize = _SADWindowSize; + P1 = _P1; + P2 = _P2; + disp12MaxDiff = _disp12MaxDiff; + preFilterCap = _preFilterCap; + uniquenessRatio = _uniquenessRatio; + speckleWindowSize = _speckleWindowSize; + speckleRange = _speckleRange; + mode = _mode; + regionRemoval = 1; + kernelType = CV_MODIFIED_CENSUS_TRANSFORM; + subpixelInterpolationMethod = CV_QUADRATIC_INTERPOLATION; + } + int minDisparity; + int numDisparities; + int kernelSize; + int preFilterCap; + int uniquenessRatio; + int P1; + int P2; + int speckleWindowSize; + int speckleRange; + int disp12MaxDiff; + int mode; + int regionRemoval; + int kernelType; + int subpixelInterpolationMethod; + }; + + /* + computes disparity for "roi" in img1 w.r.t. img2 and write it to disp1buf. + that is, disp1buf(x, y)=d means that img1(x+roi.x, y+roi.y) ~ img2(x+roi.x-d, y+roi.y). + minD <= d < maxD. + disp2full is the reverse disparity map, that is: + disp2full(x+roi.x,y+roi.y)=d means that img2(x+roi.x, y+roi.y) ~ img1(x+roi.x+d, y+roi.y) + note that disp1buf will have the same size as the roi and + disp2full will have the same size as img1 (or img2). + On exit disp2buf is not the final disparity, it is an intermediate result that becomes + final after all the tiles are processed. + the disparity in disp1buf is written with sub-pixel accuracy + (4 fractional bits, see StereoSGBM::DISP_SCALE), + using quadratic interpolation, while the disparity in disp2buf + is written as is, without interpolation. + disp2cost also has the same size as img1 (or img2). + It contains the minimum current cost, used to find the best disparity, corresponding to the minimal cost. + */ + static void computeDisparityBinarySGBM( const Mat& img1, const Mat& img2, + Mat& disp1, const StereoBinarySGBMParams& params, + Mat& buffer,const Mat& hamDist) + { #if CV_SSE2 - volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); + static const uchar LSBTab[] = + { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 + }; + + volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); #endif -#if 1 - for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width ) - { - int diff_scale = c < cn ? 0 : 2; - - // precompute - // v0 = min(row2[x-1/2], row2[x], row2[x+1/2]) and - // v1 = max(row2[x-1/2], row2[x], row2[x+1/2]) and - for( x = minX2; x < maxX2; x++ ) - { - int v = prow2[x]; - int vl = x > 0 ? (v + prow2[x-1])/2 : v; - int vr = x < width-1 ? (v + prow2[x+1])/2 : v; - int v0 = std::min(vl, vr); v0 = std::min(v0, v); - int v1 = std::max(vl, vr); v1 = std::max(v1, v); - buffer[x] = (PixType)v0; - buffer[x + width2] = (PixType)v1; - } - - for( x = minX1; x < maxX1; x++ ) - { - int u = prow1[x]; - int ul = x > 0 ? (u + prow1[x-1])/2 : u; - int ur = x < width-1 ? (u + prow1[x+1])/2 : u; - int u0 = std::min(ul, ur); u0 = std::min(u0, u); - int u1 = std::max(ul, ur); u1 = std::max(u1, u); + const int ALIGN = 16; + const int DISP_SHIFT = StereoMatcher::DISP_SHIFT; + const int DISP_SCALE = (1 << DISP_SHIFT); + const CostType MAX_COST = SHRT_MAX; + int minD = params.minDisparity, maxD = minD + params.numDisparities; + Size kernelSize; + kernelSize.width = kernelSize.height = params.kernelSize > 0 ? params.kernelSize : 5; + int uniquenessRatio = params.uniquenessRatio >= 0 ? params.uniquenessRatio : 10; + int disp12MaxDiff = params.disp12MaxDiff > 0 ? params.disp12MaxDiff : 1; + int P1 = params.P1 > 0 ? params.P1 : 2, P2 = std::max(params.P2 > 0 ? params.P2 : 5, P1+1); + int k, width = disp1.cols, height = disp1.rows; + int minX1 = std::max(-maxD, 0), maxX1 = width + std::min(minD, 0); + int D = maxD - minD, width1 = maxX1 - minX1; + int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; + int SW2 = kernelSize.width/2, SH2 = kernelSize.height/2; + bool fullDP = params.mode == StereoBinarySGBM::MODE_HH; + int npasses = fullDP ? 2 : 1; + + if( minX1 >= maxX1 ) + { + disp1 = Scalar::all(INVALID_DISP_SCALED); + return; + } + CV_Assert( D % 16 == 0 ); + // NR - the number of directions. the loop on x below that computes Lr assumes that NR == 8. + // if you change NR, please, modify the loop as well. + int D2 = D+16, NRD2 = NR2*D2; + // the number of L_r(.,.) and min_k L_r(.,.) lines in the buffer: + // for 8-way dynamic programming we need the current row and + // the previous row, i.e. 2 rows in total + const int NLR = 2; + const int LrBorder = NLR - 1; + int ww = img2.cols; + short *ham; + ham = (short *)hamDist.data; + // for each possible stereo match (img1(x,y) <=> img2(x-d,y)) + // we keep pixel difference cost (C) and the summary cost over NR directions (S). + // we also keep all the partial costs for the previous line L_r(x,d) and also min_k L_r(x, k) + size_t costBufSize = width1*D; + size_t CSBufSize = costBufSize*(fullDP ? height : 1); + size_t minLrSize = (width1 + LrBorder*2)*NR2, LrSize = minLrSize*D2; + int hsumBufNRows = SH2*2 + 2; + size_t totalBufSize = (LrSize + minLrSize)*NLR*sizeof(CostType) + // minLr[] and Lr[] + costBufSize*(hsumBufNRows + 1)*sizeof(CostType) + // hsumBuf, pixdiff + CSBufSize*2*sizeof(CostType) + // C, S + width*16*img1.channels()*sizeof(PixType) + // temp buffer for computing per-pixel cost + width*(sizeof(CostType) + sizeof(DispType)) + 1024; // disp2cost + disp2 + if( buffer.empty() || !buffer.isContinuous() || + buffer.cols*buffer.rows*buffer.elemSize() < totalBufSize ) + buffer.create(1, (int)totalBufSize, CV_8U); + // summary cost over different (nDirs) directions + CostType* Cbuf = (CostType*)alignPtr(buffer.ptr(), ALIGN); + CostType* Sbuf = Cbuf + CSBufSize; + CostType* hsumBuf = Sbuf + CSBufSize; + CostType* pixDiff = hsumBuf + costBufSize*hsumBufNRows; + CostType* disp2cost = pixDiff + costBufSize + (LrSize + minLrSize)*NLR; + DispType* disp2ptr = (DispType*)(disp2cost + width); + // PixType* tempBuf = (PixType*)(disp2ptr + width); + // add P2 to every C(x,y). it saves a few operations in the inner loops + for( k = 0; k < width1*D; k++ ) + Cbuf[k] = (CostType)P2; + for( int pass = 1; pass <= npasses; pass++ ) + { + int x1, y1, x2, y2, dx, dy; + if( pass == 1 ) + { + y1 = 0; y2 = height; dy = 1; + x1 = 0; x2 = width1; dx = 1; + } + else + { + y1 = height-1; y2 = -1; dy = -1; + x1 = width1-1; x2 = -1; dx = -1; + } + CostType *Lr[NLR]={0}, *minLr[NLR]={0}; + for( k = 0; k < NLR; k++ ) + { + // shift Lr[k] and minLr[k] pointers, because we allocated them with the borders, + // and will occasionally use negative indices with the arrays + // we need to shift Lr[k] pointers by 1, to give the space for d=-1. + // however, then the alignment will be imperfect, i.e. bad for SSE, + // thus we shift the pointers by 8 (8*sizeof(short) == 16 - ideal alignment) + Lr[k] = pixDiff + costBufSize + LrSize*k + NRD2*LrBorder + 8; + memset( Lr[k] - LrBorder*NRD2 - 8, 0, LrSize*sizeof(CostType) ); + minLr[k] = pixDiff + costBufSize + LrSize*NLR + minLrSize*k + NR2*LrBorder; + memset( minLr[k] - LrBorder*NR2, 0, minLrSize*sizeof(CostType) ); + } + for( int y = y1; y != y2; y += dy ) + { + int x, d; + DispType* disp1ptr = disp1.ptr(y); + CostType* C = Cbuf + (!fullDP ? 0 : y*costBufSize); + CostType* S = Sbuf + (!fullDP ? 0 : y*costBufSize); + if( pass == 1 ) // compute C on the first pass, and reuse it on the second pass, if any. + { + int dy1 = y == 0 ? 0 : y + SH2, dy2 = y == 0 ? SH2 : dy1; + for( k = dy1; k <= dy2; k++ ) + { + CostType* hsumAdd = hsumBuf + (std::min(k, height-1) % hsumBufNRows)*costBufSize; + if( k < height ) + { + for(int ii = 0; ii <= ww; ii++) + { + for(int dd = 0; dd <= params.numDisparities; dd++) + { + pixDiff[ii * (params.numDisparities)+ dd] = (CostType)(ham[(k * (ww) + ii) * (params.numDisparities +1) + dd]); + } + } + memset(hsumAdd, 0, D*sizeof(CostType)); + for( x = 0; x <= SW2*D; x += D ) + { + int scale = x == 0 ? SW2 + 1 : 1; + for( d = 0; d < D; d++ ) + hsumAdd[d] = (CostType)(hsumAdd[d] + pixDiff[x + d]*scale); + } + + if( y > 0 ) + { + const CostType* hsumSub = hsumBuf + (std::max(y - SH2 - 1, 0) % hsumBufNRows)*costBufSize; + const CostType* Cprev = !fullDP || y == 0 ? C : C - costBufSize; + + for( x = D; x < width1*D; x += D ) + { + const CostType* pixAdd = pixDiff + std::min(x + SW2*D, (width1-1)*D); + const CostType* pixSub = pixDiff + std::max(x - (SW2+1)*D, 0); #if CV_SSE2 - if( useSIMD ) - { - __m128i _u = _mm_set1_epi8((char)u), _u0 = _mm_set1_epi8((char)u0); - __m128i _u1 = _mm_set1_epi8((char)u1), z = _mm_setzero_si128(); - __m128i ds = _mm_cvtsi32_si128(diff_scale); - - for( int d = minD; d < maxD; d += 16 ) - { - __m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-x-1 + d)); - __m128i _v0 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d)); - __m128i _v1 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d + width2)); - __m128i c0 = _mm_max_epu8(_mm_subs_epu8(_u, _v1), _mm_subs_epu8(_v0, _u)); - __m128i c1 = _mm_max_epu8(_mm_subs_epu8(_v, _u1), _mm_subs_epu8(_u0, _v)); - __m128i diff = _mm_min_epu8(c0, c1); - - c0 = _mm_load_si128((__m128i*)(cost + x*D + d)); - c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8)); - - _mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_srl_epi16(_mm_unpacklo_epi8(diff,z), ds))); - _mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_srl_epi16(_mm_unpackhi_epi8(diff,z), ds))); - } - } - else -#endif - { - for( int d = minD; d < maxD; d++ ) - { - int v = prow2[width-x-1 + d]; - int v0 = buffer[width-x-1 + d]; - int v1 = buffer[width-x-1 + d + width2]; - int c0 = std::max(0, u - v1); c0 = std::max(c0, v0 - u); - int c1 = std::max(0, v - u1); c1 = std::max(c1, u0 - v); - - cost[x*D + d] = (CostType)(cost[x*D+d] + (std::min(c0, c1) >> diff_scale)); - } - } - } - } -#else - for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width ) - { - for( x = minX1; x < maxX1; x++ ) - { - int u = prow1[x]; -#if CV_SSE2 - if( useSIMD ) - { - __m128i _u = _mm_set1_epi8(u), z = _mm_setzero_si128(); - - for( int d = minD; d < maxD; d += 16 ) - { - __m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-1-x + d)); - __m128i diff = _mm_adds_epu8(_mm_subs_epu8(_u,_v), _mm_subs_epu8(_v,_u)); - __m128i c0 = _mm_load_si128((__m128i*)(cost + x*D + d)); - __m128i c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8)); - - _mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_unpacklo_epi8(diff,z))); - _mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_unpackhi_epi8(diff,z))); - } - } - else -#endif - { - for( int d = minD; d < maxD; d++ ) - { - int v = prow2[width-1-x + d]; - cost[x*D + d] = (CostType)(cost[x*D + d] + (CostType)std::abs(u - v)); - } - } - } - } -#endif - } - - - /* - computes disparity for "roi" in img1 w.r.t. img2 and write it to disp1buf. - that is, disp1buf(x, y)=d means that img1(x+roi.x, y+roi.y) ~ img2(x+roi.x-d, y+roi.y). - minD <= d < maxD. - disp2full is the reverse disparity map, that is: - disp2full(x+roi.x,y+roi.y)=d means that img2(x+roi.x, y+roi.y) ~ img1(x+roi.x+d, y+roi.y) - - note that disp1buf will have the same size as the roi and - disp2full will have the same size as img1 (or img2). - On exit disp2buf is not the final disparity, it is an intermediate result that becomes - final after all the tiles are processed. - - the disparity in disp1buf is written with sub-pixel accuracy - (4 fractional bits, see StereoSGBM::DISP_SCALE), - using quadratic interpolation, while the disparity in disp2buf - is written as is, without interpolation. - - disp2cost also has the same size as img1 (or img2). - It contains the minimum current cost, used to find the best disparity, corresponding to the minimal cost. - */ - static void computeDisparityBinarySGBM( const Mat& img1, const Mat& img2, - Mat& disp1, const StereoBinarySGBMParams& params, - Mat& buffer ) - { -#if CV_SSE2 - static const uchar LSBTab[] = - { - 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, - 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 - }; - - volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); + if( useSIMD ) + { + for( d = 0; d < D; d += 8 ) + { + __m128i hv = _mm_load_si128((const __m128i*)(hsumAdd + x - D + d)); + __m128i Cx = _mm_load_si128((__m128i*)(Cprev + x + d)); + hv = _mm_adds_epi16(_mm_subs_epi16(hv, + _mm_load_si128((const __m128i*)(pixSub + d))), + _mm_load_si128((const __m128i*)(pixAdd + d))); + Cx = _mm_adds_epi16(_mm_subs_epi16(Cx, + _mm_load_si128((const __m128i*)(hsumSub + x + d))), + hv); + _mm_store_si128((__m128i*)(hsumAdd + x + d), hv); + _mm_store_si128((__m128i*)(C + x + d), Cx); + } + } + else #endif - - const int ALIGN = 16; - const int DISP_SHIFT = StereoMatcher::DISP_SHIFT; - const int DISP_SCALE = (1 << DISP_SHIFT); - const CostType MAX_COST = SHRT_MAX; - - int minD = params.minDisparity, maxD = minD + params.numDisparities; - Size SADWindowSize; - SADWindowSize.width = SADWindowSize.height = params.SADWindowSize > 0 ? params.SADWindowSize : 5; - int ftzero = std::max(params.preFilterCap, 15) | 1; - int uniquenessRatio = params.uniquenessRatio >= 0 ? params.uniquenessRatio : 10; - int disp12MaxDiff = params.disp12MaxDiff > 0 ? params.disp12MaxDiff : 1; - int P1 = params.P1 > 0 ? params.P1 : 2, P2 = std::max(params.P2 > 0 ? params.P2 : 5, P1+1); - int k, width = disp1.cols, height = disp1.rows; - int minX1 = std::max(-maxD, 0), maxX1 = width + std::min(minD, 0); - int D = maxD - minD, width1 = maxX1 - minX1; - int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE; - int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2; - bool fullDP = params.mode == StereoBinarySGBM::MODE_HH; - int npasses = fullDP ? 2 : 1; - const int TAB_OFS = 256*4, TAB_SIZE = 256 + TAB_OFS*2; - PixType clipTab[TAB_SIZE]; - - for( k = 0; k < TAB_SIZE; k++ ) - clipTab[k] = (PixType)(std::min(std::max(k - TAB_OFS, -ftzero), ftzero) + ftzero); - - if( minX1 >= maxX1 ) - { - disp1 = Scalar::all(INVALID_DISP_SCALED); - return; - } - - CV_Assert( D % 16 == 0 ); - - // NR - the number of directions. the loop on x below that computes Lr assumes that NR == 8. - // if you change NR, please, modify the loop as well. - int D2 = D+16, NRD2 = NR2*D2; - - // the number of L_r(.,.) and min_k L_r(.,.) lines in the buffer: - // for 8-way dynamic programming we need the current row and - // the previous row, i.e. 2 rows in total - const int NLR = 2; - const int LrBorder = NLR - 1; - - // for each possible stereo match (img1(x,y) <=> img2(x-d,y)) - // we keep pixel difference cost (C) and the summary cost over NR directions (S). - // we also keep all the partial costs for the previous line L_r(x,d) and also min_k L_r(x, k) - size_t costBufSize = width1*D; - size_t CSBufSize = costBufSize*(fullDP ? height : 1); - size_t minLrSize = (width1 + LrBorder*2)*NR2, LrSize = minLrSize*D2; - int hsumBufNRows = SH2*2 + 2; - size_t totalBufSize = (LrSize + minLrSize)*NLR*sizeof(CostType) + // minLr[] and Lr[] - costBufSize*(hsumBufNRows + 1)*sizeof(CostType) + // hsumBuf, pixdiff - CSBufSize*2*sizeof(CostType) + // C, S - width*16*img1.channels()*sizeof(PixType) + // temp buffer for computing per-pixel cost - width*(sizeof(CostType) + sizeof(DispType)) + 1024; // disp2cost + disp2 - - if( buffer.empty() || !buffer.isContinuous() || - buffer.cols*buffer.rows*buffer.elemSize() < totalBufSize ) - buffer.create(1, (int)totalBufSize, CV_8U); - - // summary cost over different (nDirs) directions - CostType* Cbuf = (CostType*)alignPtr(buffer.ptr(), ALIGN); - CostType* Sbuf = Cbuf + CSBufSize; - CostType* hsumBuf = Sbuf + CSBufSize; - CostType* pixDiff = hsumBuf + costBufSize*hsumBufNRows; - - CostType* disp2cost = pixDiff + costBufSize + (LrSize + minLrSize)*NLR; - DispType* disp2ptr = (DispType*)(disp2cost + width); - PixType* tempBuf = (PixType*)(disp2ptr + width); - - // add P2 to every C(x,y). it saves a few operations in the inner loops - for( k = 0; k < width1*D; k++ ) - Cbuf[k] = (CostType)P2; - - for( int pass = 1; pass <= npasses; pass++ ) - { - int x1, y1, x2, y2, dx, dy; - - if( pass == 1 ) - { - y1 = 0; y2 = height; dy = 1; - x1 = 0; x2 = width1; dx = 1; - } - else - { - y1 = height-1; y2 = -1; dy = -1; - x1 = width1-1; x2 = -1; dx = -1; - } - - CostType *Lr[NLR]={0}, *minLr[NLR]={0}; - - for( k = 0; k < NLR; k++ ) - { - // shift Lr[k] and minLr[k] pointers, because we allocated them with the borders, - // and will occasionally use negative indices with the arrays - // we need to shift Lr[k] pointers by 1, to give the space for d=-1. - // however, then the alignment will be imperfect, i.e. bad for SSE, - // thus we shift the pointers by 8 (8*sizeof(short) == 16 - ideal alignment) - Lr[k] = pixDiff + costBufSize + LrSize*k + NRD2*LrBorder + 8; - memset( Lr[k] - LrBorder*NRD2 - 8, 0, LrSize*sizeof(CostType) ); - minLr[k] = pixDiff + costBufSize + LrSize*NLR + minLrSize*k + NR2*LrBorder; - memset( minLr[k] - LrBorder*NR2, 0, minLrSize*sizeof(CostType) ); - } - - for( int y = y1; y != y2; y += dy ) - { - int x, d; - DispType* disp1ptr = disp1.ptr(y); - CostType* C = Cbuf + (!fullDP ? 0 : y*costBufSize); - CostType* S = Sbuf + (!fullDP ? 0 : y*costBufSize); - - if( pass == 1 ) // compute C on the first pass, and reuse it on the second pass, if any. - { - int dy1 = y == 0 ? 0 : y + SH2, dy2 = y == 0 ? SH2 : dy1; - - for( k = dy1; k <= dy2; k++ ) - { - CostType* hsumAdd = hsumBuf + (std::min(k, height-1) % hsumBufNRows)*costBufSize; - - if( k < height ) - { - calcPixelCostBT( img1, img2, k, minD, maxD, pixDiff, tempBuf, clipTab, TAB_OFS, ftzero ); - - memset(hsumAdd, 0, D*sizeof(CostType)); - for( x = 0; x <= SW2*D; x += D ) - { - int scale = x == 0 ? SW2 + 1 : 1; - for( d = 0; d < D; d++ ) - hsumAdd[d] = (CostType)(hsumAdd[d] + pixDiff[x + d]*scale); - } - - if( y > 0 ) - { - const CostType* hsumSub = hsumBuf + (std::max(y - SH2 - 1, 0) % hsumBufNRows)*costBufSize; - const CostType* Cprev = !fullDP || y == 0 ? C : C - costBufSize; - - for( x = D; x < width1*D; x += D ) - { - const CostType* pixAdd = pixDiff + std::min(x + SW2*D, (width1-1)*D); - const CostType* pixSub = pixDiff + std::max(x - (SW2+1)*D, 0); - + { + for( d = 0; d < D; d++ ) + { + int hv = hsumAdd[x + d] = (CostType)(hsumAdd[x - D + d] + pixAdd[d] - pixSub[d]); + C[x + d] = (CostType)(Cprev[x + d] + hv - hsumSub[x + d]); + } + } + } + } + else + { + for( x = D; x < width1*D; x += D ) + { + const CostType* pixAdd = pixDiff + std::min(x + SW2*D, (width1-1)*D); + const CostType* pixSub = pixDiff + std::max(x - (SW2+1)*D, 0); + for( d = 0; d < D; d++ ) + hsumAdd[x + d] = (CostType)(hsumAdd[x - D + d] + pixAdd[d] - pixSub[d]); + } + } + } + if( y == 0 ) + { + int scale = k == 0 ? SH2 + 1 : 1; + for( x = 0; x < width1*D; x++ ) + C[x] = (CostType)(C[x] + hsumAdd[x]*scale); + } + } + // also, clear the S buffer + for( k = 0; k < width1*D; k++ ) + S[k] = 0; + } + // clear the left and the right borders + memset( Lr[0] - NRD2*LrBorder - 8, 0, NRD2*LrBorder*sizeof(CostType) ); + memset( Lr[0] + width1*NRD2 - 8, 0, NRD2*LrBorder*sizeof(CostType) ); + memset( minLr[0] - NR2*LrBorder, 0, NR2*LrBorder*sizeof(CostType) ); + memset( minLr[0] + width1*NR2, 0, NR2*LrBorder*sizeof(CostType) ); + /* + [formula 13 in the paper] + compute L_r(p, d) = C(p, d) + + min(L_r(p-r, d), + L_r(p-r, d-1) + P1, + L_r(p-r, d+1) + P1, + min_k L_r(p-r, k) + P2) - min_k L_r(p-r, k) + where p = (x,y), r is one of the directions. + we process all the directions at once: + 0: r=(-dx, 0) + 1: r=(-1, -dy) + 2: r=(0, -dy) + 3: r=(1, -dy) + 4: r=(-2, -dy) + 5: r=(-1, -dy*2) + 6: r=(1, -dy*2) + 7: r=(2, -dy) + */ + for( x = x1; x != x2; x += dx ) + { + int xm = x*NR2, xd = xm*D2; + int delta0 = minLr[0][xm - dx*NR2] + P2, delta1 = minLr[1][xm - NR2 + 1] + P2; + int delta2 = minLr[1][xm + 2] + P2, delta3 = minLr[1][xm + NR2 + 3] + P2; + CostType* Lr_p0 = Lr[0] + xd - dx*NRD2; + CostType* Lr_p1 = Lr[1] + xd - NRD2 + D2; + CostType* Lr_p2 = Lr[1] + xd + D2*2; + CostType* Lr_p3 = Lr[1] + xd + NRD2 + D2*3; + Lr_p0[-1] = Lr_p0[D] = Lr_p1[-1] = Lr_p1[D] = + Lr_p2[-1] = Lr_p2[D] = Lr_p3[-1] = Lr_p3[D] = MAX_COST; + CostType* Lr_p = Lr[0] + xd; + const CostType* Cp = C + x*D; + CostType* Sp = S + x*D; #if CV_SSE2 - if( useSIMD ) - { - for( d = 0; d < D; d += 8 ) - { - __m128i hv = _mm_load_si128((const __m128i*)(hsumAdd + x - D + d)); - __m128i Cx = _mm_load_si128((__m128i*)(Cprev + x + d)); - hv = _mm_adds_epi16(_mm_subs_epi16(hv, - _mm_load_si128((const __m128i*)(pixSub + d))), - _mm_load_si128((const __m128i*)(pixAdd + d))); - Cx = _mm_adds_epi16(_mm_subs_epi16(Cx, - _mm_load_si128((const __m128i*)(hsumSub + x + d))), - hv); - _mm_store_si128((__m128i*)(hsumAdd + x + d), hv); - _mm_store_si128((__m128i*)(C + x + d), Cx); - } - } - else + if( useSIMD ) + { + __m128i _P1 = _mm_set1_epi16((short)P1); + __m128i _delta0 = _mm_set1_epi16((short)delta0); + __m128i _delta1 = _mm_set1_epi16((short)delta1); + __m128i _delta2 = _mm_set1_epi16((short)delta2); + __m128i _delta3 = _mm_set1_epi16((short)delta3); + __m128i _minL0 = _mm_set1_epi16((short)MAX_COST); + for( d = 0; d < D; d += 8 ) + { + __m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d)); + __m128i L0, L1, L2, L3; + L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d)); + L1 = _mm_load_si128((const __m128i*)(Lr_p1 + d)); + L2 = _mm_load_si128((const __m128i*)(Lr_p2 + d)); + L3 = _mm_load_si128((const __m128i*)(Lr_p3 + d)); + L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d - 1)), _P1)); + L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d + 1)), _P1)); + L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d - 1)), _P1)); + L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d + 1)), _P1)); + L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d - 1)), _P1)); + L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d + 1)), _P1)); + L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d - 1)), _P1)); + L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d + 1)), _P1)); + L0 = _mm_min_epi16(L0, _delta0); + L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd); + L1 = _mm_min_epi16(L1, _delta1); + L1 = _mm_adds_epi16(_mm_subs_epi16(L1, _delta1), Cpd); + L2 = _mm_min_epi16(L2, _delta2); + L2 = _mm_adds_epi16(_mm_subs_epi16(L2, _delta2), Cpd); + L3 = _mm_min_epi16(L3, _delta3); + L3 = _mm_adds_epi16(_mm_subs_epi16(L3, _delta3), Cpd); + _mm_store_si128( (__m128i*)(Lr_p + d), L0); + _mm_store_si128( (__m128i*)(Lr_p + d + D2), L1); + _mm_store_si128( (__m128i*)(Lr_p + d + D2*2), L2); + _mm_store_si128( (__m128i*)(Lr_p + d + D2*3), L3); + __m128i t0 = _mm_min_epi16(_mm_unpacklo_epi16(L0, L2), _mm_unpackhi_epi16(L0, L2)); + __m128i t1 = _mm_min_epi16(_mm_unpacklo_epi16(L1, L3), _mm_unpackhi_epi16(L1, L3)); + t0 = _mm_min_epi16(_mm_unpacklo_epi16(t0, t1), _mm_unpackhi_epi16(t0, t1)); + _minL0 = _mm_min_epi16(_minL0, t0); + __m128i Sval = _mm_load_si128((const __m128i*)(Sp + d)); + L0 = _mm_adds_epi16(L0, L1); + L2 = _mm_adds_epi16(L2, L3); + Sval = _mm_adds_epi16(Sval, L0); + Sval = _mm_adds_epi16(Sval, L2); + _mm_store_si128((__m128i*)(Sp + d), Sval); + } + _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8)); + _mm_storel_epi64((__m128i*)&minLr[0][xm], _minL0); + } + else #endif - { - for( d = 0; d < D; d++ ) - { - int hv = hsumAdd[x + d] = (CostType)(hsumAdd[x - D + d] + pixAdd[d] - pixSub[d]); - C[x + d] = (CostType)(Cprev[x + d] + hv - hsumSub[x + d]); - } - } - } - } - else - { - for( x = D; x < width1*D; x += D ) - { - const CostType* pixAdd = pixDiff + std::min(x + SW2*D, (width1-1)*D); - const CostType* pixSub = pixDiff + std::max(x - (SW2+1)*D, 0); - - for( d = 0; d < D; d++ ) - hsumAdd[x + d] = (CostType)(hsumAdd[x - D + d] + pixAdd[d] - pixSub[d]); - } - } - } - - if( y == 0 ) - { - int scale = k == 0 ? SH2 + 1 : 1; - for( x = 0; x < width1*D; x++ ) - C[x] = (CostType)(C[x] + hsumAdd[x]*scale); - } - } - - // also, clear the S buffer - for( k = 0; k < width1*D; k++ ) - S[k] = 0; - } - - // clear the left and the right borders - memset( Lr[0] - NRD2*LrBorder - 8, 0, NRD2*LrBorder*sizeof(CostType) ); - memset( Lr[0] + width1*NRD2 - 8, 0, NRD2*LrBorder*sizeof(CostType) ); - memset( minLr[0] - NR2*LrBorder, 0, NR2*LrBorder*sizeof(CostType) ); - memset( minLr[0] + width1*NR2, 0, NR2*LrBorder*sizeof(CostType) ); - - /* - [formula 13 in the paper] - compute L_r(p, d) = C(p, d) + - min(L_r(p-r, d), - L_r(p-r, d-1) + P1, - L_r(p-r, d+1) + P1, - min_k L_r(p-r, k) + P2) - min_k L_r(p-r, k) - where p = (x,y), r is one of the directions. - we process all the directions at once: - 0: r=(-dx, 0) - 1: r=(-1, -dy) - 2: r=(0, -dy) - 3: r=(1, -dy) - 4: r=(-2, -dy) - 5: r=(-1, -dy*2) - 6: r=(1, -dy*2) - 7: r=(2, -dy) - */ - for( x = x1; x != x2; x += dx ) - { - int xm = x*NR2, xd = xm*D2; - - int delta0 = minLr[0][xm - dx*NR2] + P2, delta1 = minLr[1][xm - NR2 + 1] + P2; - int delta2 = minLr[1][xm + 2] + P2, delta3 = minLr[1][xm + NR2 + 3] + P2; - - CostType* Lr_p0 = Lr[0] + xd - dx*NRD2; - CostType* Lr_p1 = Lr[1] + xd - NRD2 + D2; - CostType* Lr_p2 = Lr[1] + xd + D2*2; - CostType* Lr_p3 = Lr[1] + xd + NRD2 + D2*3; - - Lr_p0[-1] = Lr_p0[D] = Lr_p1[-1] = Lr_p1[D] = - Lr_p2[-1] = Lr_p2[D] = Lr_p3[-1] = Lr_p3[D] = MAX_COST; - - CostType* Lr_p = Lr[0] + xd; - const CostType* Cp = C + x*D; - CostType* Sp = S + x*D; - -#if CV_SSE2 - if( useSIMD ) - { - __m128i _P1 = _mm_set1_epi16((short)P1); - - __m128i _delta0 = _mm_set1_epi16((short)delta0); - __m128i _delta1 = _mm_set1_epi16((short)delta1); - __m128i _delta2 = _mm_set1_epi16((short)delta2); - __m128i _delta3 = _mm_set1_epi16((short)delta3); - __m128i _minL0 = _mm_set1_epi16((short)MAX_COST); - - for( d = 0; d < D; d += 8 ) - { - __m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d)); - __m128i L0, L1, L2, L3; - - L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d)); - L1 = _mm_load_si128((const __m128i*)(Lr_p1 + d)); - L2 = _mm_load_si128((const __m128i*)(Lr_p2 + d)); - L3 = _mm_load_si128((const __m128i*)(Lr_p3 + d)); - - L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d - 1)), _P1)); - L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d + 1)), _P1)); - - L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d - 1)), _P1)); - L1 = _mm_min_epi16(L1, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p1 + d + 1)), _P1)); - - L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d - 1)), _P1)); - L2 = _mm_min_epi16(L2, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p2 + d + 1)), _P1)); - - L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d - 1)), _P1)); - L3 = _mm_min_epi16(L3, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p3 + d + 1)), _P1)); - - L0 = _mm_min_epi16(L0, _delta0); - L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd); - - L1 = _mm_min_epi16(L1, _delta1); - L1 = _mm_adds_epi16(_mm_subs_epi16(L1, _delta1), Cpd); - - L2 = _mm_min_epi16(L2, _delta2); - L2 = _mm_adds_epi16(_mm_subs_epi16(L2, _delta2), Cpd); - - L3 = _mm_min_epi16(L3, _delta3); - L3 = _mm_adds_epi16(_mm_subs_epi16(L3, _delta3), Cpd); - - _mm_store_si128( (__m128i*)(Lr_p + d), L0); - _mm_store_si128( (__m128i*)(Lr_p + d + D2), L1); - _mm_store_si128( (__m128i*)(Lr_p + d + D2*2), L2); - _mm_store_si128( (__m128i*)(Lr_p + d + D2*3), L3); - - __m128i t0 = _mm_min_epi16(_mm_unpacklo_epi16(L0, L2), _mm_unpackhi_epi16(L0, L2)); - __m128i t1 = _mm_min_epi16(_mm_unpacklo_epi16(L1, L3), _mm_unpackhi_epi16(L1, L3)); - t0 = _mm_min_epi16(_mm_unpacklo_epi16(t0, t1), _mm_unpackhi_epi16(t0, t1)); - _minL0 = _mm_min_epi16(_minL0, t0); - - __m128i Sval = _mm_load_si128((const __m128i*)(Sp + d)); - - L0 = _mm_adds_epi16(L0, L1); - L2 = _mm_adds_epi16(L2, L3); - Sval = _mm_adds_epi16(Sval, L0); - Sval = _mm_adds_epi16(Sval, L2); - - _mm_store_si128((__m128i*)(Sp + d), Sval); - } - - _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8)); - _mm_storel_epi64((__m128i*)&minLr[0][xm], _minL0); - } - else -#endif - { - int minL0 = MAX_COST, minL1 = MAX_COST, minL2 = MAX_COST, minL3 = MAX_COST; - - for( d = 0; d < D; d++ ) - { - int Cpd = Cp[d], L0, L1, L2, L3; - - L0 = Cpd + std::min((int)Lr_p0[d], std::min(Lr_p0[d-1] + P1, std::min(Lr_p0[d+1] + P1, delta0))) - delta0; - L1 = Cpd + std::min((int)Lr_p1[d], std::min(Lr_p1[d-1] + P1, std::min(Lr_p1[d+1] + P1, delta1))) - delta1; - L2 = Cpd + std::min((int)Lr_p2[d], std::min(Lr_p2[d-1] + P1, std::min(Lr_p2[d+1] + P1, delta2))) - delta2; - L3 = Cpd + std::min((int)Lr_p3[d], std::min(Lr_p3[d-1] + P1, std::min(Lr_p3[d+1] + P1, delta3))) - delta3; - - Lr_p[d] = (CostType)L0; - minL0 = std::min(minL0, L0); - - Lr_p[d + D2] = (CostType)L1; - minL1 = std::min(minL1, L1); - - Lr_p[d + D2*2] = (CostType)L2; - minL2 = std::min(minL2, L2); - - Lr_p[d + D2*3] = (CostType)L3; - minL3 = std::min(minL3, L3); - - Sp[d] = saturate_cast(Sp[d] + L0 + L1 + L2 + L3); - } - minLr[0][xm] = (CostType)minL0; - minLr[0][xm+1] = (CostType)minL1; - minLr[0][xm+2] = (CostType)minL2; - minLr[0][xm+3] = (CostType)minL3; - } - } - - if( pass == npasses ) - { - for( x = 0; x < width; x++ ) - { - disp1ptr[x] = disp2ptr[x] = (DispType)INVALID_DISP_SCALED; - disp2cost[x] = MAX_COST; - } - - for( x = width1 - 1; x >= 0; x-- ) - { - CostType* Sp = S + x*D; - int minS = MAX_COST, bestDisp = -1; - - if( npasses == 1 ) - { - int xm = x*NR2, xd = xm*D2; - - int minL0 = MAX_COST; - int delta0 = minLr[0][xm + NR2] + P2; - CostType* Lr_p0 = Lr[0] + xd + NRD2; - Lr_p0[-1] = Lr_p0[D] = MAX_COST; - CostType* Lr_p = Lr[0] + xd; - - const CostType* Cp = C + x*D; - + { + int minL0 = MAX_COST, minL1 = MAX_COST, minL2 = MAX_COST, minL3 = MAX_COST; + + for( d = 0; d < D; d++ ) + { + int Cpd = Cp[d], L0, L1, L2, L3; + + L0 = Cpd + std::min((int)Lr_p0[d], std::min(Lr_p0[d-1] + P1, std::min(Lr_p0[d+1] + P1, delta0))) - delta0; + L1 = Cpd + std::min((int)Lr_p1[d], std::min(Lr_p1[d-1] + P1, std::min(Lr_p1[d+1] + P1, delta1))) - delta1; + L2 = Cpd + std::min((int)Lr_p2[d], std::min(Lr_p2[d-1] + P1, std::min(Lr_p2[d+1] + P1, delta2))) - delta2; + L3 = Cpd + std::min((int)Lr_p3[d], std::min(Lr_p3[d-1] + P1, std::min(Lr_p3[d+1] + P1, delta3))) - delta3; + + Lr_p[d] = (CostType)L0; + minL0 = std::min(minL0, L0); + + Lr_p[d + D2] = (CostType)L1; + minL1 = std::min(minL1, L1); + + Lr_p[d + D2*2] = (CostType)L2; + minL2 = std::min(minL2, L2); + + Lr_p[d + D2*3] = (CostType)L3; + minL3 = std::min(minL3, L3); + + Sp[d] = saturate_cast(Sp[d] + L0 + L1 + L2 + L3); + } + minLr[0][xm] = (CostType)minL0; + minLr[0][xm+1] = (CostType)minL1; + minLr[0][xm+2] = (CostType)minL2; + minLr[0][xm+3] = (CostType)minL3; + } + } + + if( pass == npasses ) + { + for( x = 0; x < width; x++ ) + { + disp1ptr[x] = disp2ptr[x] = (DispType)INVALID_DISP_SCALED; + disp2cost[x] = MAX_COST; + } + + for( x = width1 - 1; x >= 0; x-- ) + { + CostType* Sp = S + x*D; + int minS = MAX_COST, bestDisp = -1; + + if( npasses == 1 ) + { + int xm = x*NR2, xd = xm*D2; + + int minL0 = MAX_COST; + int delta0 = minLr[0][xm + NR2] + P2; + CostType* Lr_p0 = Lr[0] + xd + NRD2; + Lr_p0[-1] = Lr_p0[D] = MAX_COST; + CostType* Lr_p = Lr[0] + xd; + const CostType* Cp = C + x*D; #if CV_SSE2 - if( useSIMD ) - { - __m128i _P1 = _mm_set1_epi16((short)P1); - __m128i _delta0 = _mm_set1_epi16((short)delta0); - - __m128i _minL0 = _mm_set1_epi16((short)minL0); - __m128i _minS = _mm_set1_epi16(MAX_COST), _bestDisp = _mm_set1_epi16(-1); - __m128i _d8 = _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7), _8 = _mm_set1_epi16(8); - - for( d = 0; d < D; d += 8 ) - { - __m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d)), L0; - - L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d)); - L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d - 1)), _P1)); - L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d + 1)), _P1)); - L0 = _mm_min_epi16(L0, _delta0); - L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd); - - _mm_store_si128((__m128i*)(Lr_p + d), L0); - _minL0 = _mm_min_epi16(_minL0, L0); - L0 = _mm_adds_epi16(L0, *(__m128i*)(Sp + d)); - _mm_store_si128((__m128i*)(Sp + d), L0); - - __m128i mask = _mm_cmpgt_epi16(_minS, L0); - _minS = _mm_min_epi16(_minS, L0); - _bestDisp = _mm_xor_si128(_bestDisp, _mm_and_si128(_mm_xor_si128(_bestDisp,_d8), mask)); - _d8 = _mm_adds_epi16(_d8, _8); - } - - short CV_DECL_ALIGNED(16) bestDispBuf[8]; - _mm_store_si128((__m128i*)bestDispBuf, _bestDisp); - - _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8)); - _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 4)); - _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 2)); - - __m128i qS = _mm_min_epi16(_minS, _mm_srli_si128(_minS, 8)); - qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 4)); - qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 2)); - - minLr[0][xm] = (CostType)_mm_cvtsi128_si32(_minL0); - minS = (CostType)_mm_cvtsi128_si32(qS); - - qS = _mm_shuffle_epi32(_mm_unpacklo_epi16(qS, qS), 0); - qS = _mm_cmpeq_epi16(_minS, qS); - int idx = _mm_movemask_epi8(_mm_packs_epi16(qS, qS)) & 255; - - bestDisp = bestDispBuf[LSBTab[idx]]; - } - else + if( useSIMD ) + { + __m128i _P1 = _mm_set1_epi16((short)P1); + __m128i _delta0 = _mm_set1_epi16((short)delta0); + __m128i _minL0 = _mm_set1_epi16((short)minL0); + __m128i _minS = _mm_set1_epi16(MAX_COST), _bestDisp = _mm_set1_epi16(-1); + __m128i _d8 = _mm_setr_epi16(0, 1, 2, 3, 4, 5, 6, 7), _8 = _mm_set1_epi16(8); + for( d = 0; d < D; d += 8 ) + { + __m128i Cpd = _mm_load_si128((const __m128i*)(Cp + d)), L0; + L0 = _mm_load_si128((const __m128i*)(Lr_p0 + d)); + L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d - 1)), _P1)); + L0 = _mm_min_epi16(L0, _mm_adds_epi16(_mm_loadu_si128((const __m128i*)(Lr_p0 + d + 1)), _P1)); + L0 = _mm_min_epi16(L0, _delta0); + L0 = _mm_adds_epi16(_mm_subs_epi16(L0, _delta0), Cpd); + _mm_store_si128((__m128i*)(Lr_p + d), L0); + _minL0 = _mm_min_epi16(_minL0, L0); + L0 = _mm_adds_epi16(L0, *(__m128i*)(Sp + d)); + _mm_store_si128((__m128i*)(Sp + d), L0); + __m128i mask = _mm_cmpgt_epi16(_minS, L0); + _minS = _mm_min_epi16(_minS, L0); + _bestDisp = _mm_xor_si128(_bestDisp, _mm_and_si128(_mm_xor_si128(_bestDisp,_d8), mask)); + _d8 = _mm_adds_epi16(_d8, _8); + } + short CV_DECL_ALIGNED(16) bestDispBuf[8]; + _mm_store_si128((__m128i*)bestDispBuf, _bestDisp); + _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 8)); + _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 4)); + _minL0 = _mm_min_epi16(_minL0, _mm_srli_si128(_minL0, 2)); + __m128i qS = _mm_min_epi16(_minS, _mm_srli_si128(_minS, 8)); + qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 4)); + qS = _mm_min_epi16(qS, _mm_srli_si128(qS, 2)); + minLr[0][xm] = (CostType)_mm_cvtsi128_si32(_minL0); + minS = (CostType)_mm_cvtsi128_si32(qS); + qS = _mm_shuffle_epi32(_mm_unpacklo_epi16(qS, qS), 0); + qS = _mm_cmpeq_epi16(_minS, qS); + int idx = _mm_movemask_epi8(_mm_packs_epi16(qS, qS)) & 255; + bestDisp = bestDispBuf[LSBTab[idx]]; + } + else #endif - { - for( d = 0; d < D; d++ ) - { - int L0 = Cp[d] + std::min((int)Lr_p0[d], std::min(Lr_p0[d-1] + P1, std::min(Lr_p0[d+1] + P1, delta0))) - delta0; - - Lr_p[d] = (CostType)L0; - minL0 = std::min(minL0, L0); - - int Sval = Sp[d] = saturate_cast(Sp[d] + L0); - if( Sval < minS ) - { - minS = Sval; - bestDisp = d; - } - } - minLr[0][xm] = (CostType)minL0; - } - } - else - { - for( d = 0; d < D; d++ ) - { - int Sval = Sp[d]; - if( Sval < minS ) - { - minS = Sval; - bestDisp = d; - } - } - } - - for( d = 0; d < D; d++ ) - { - if( Sp[d]*(100 - uniquenessRatio) < minS*100 && std::abs(bestDisp - d) > 1 ) - break; - } - if( d < D ) - continue; - d = bestDisp; - int _x2 = x + minX1 - d - minD; - if( disp2cost[_x2] > minS ) - { - disp2cost[_x2] = (CostType)minS; - disp2ptr[_x2] = (DispType)(d + minD); - } - - if( 0 < d && d < D-1 ) - { - // do subpixel quadratic interpolation: - // fit parabola into (x1=d-1, y1=Sp[d-1]), (x2=d, y2=Sp[d]), (x3=d+1, y3=Sp[d+1]) - // then find minimum of the parabola. - int denom2 = std::max(Sp[d-1] + Sp[d+1] - 2*Sp[d], 1); - d = d*DISP_SCALE + ((Sp[d-1] - Sp[d+1])*DISP_SCALE + denom2)/(denom2*2); - } - else - d *= DISP_SCALE; - disp1ptr[x + minX1] = (DispType)(d + minD*DISP_SCALE); - } - - for( x = minX1; x < maxX1; x++ ) - { - // we round the computed disparity both towards -inf and +inf and check - // if either of the corresponding disparities in disp2 is consistent. - // This is to give the computed disparity a chance to look valid if it is. - int d1 = disp1ptr[x]; - if( d1 == INVALID_DISP_SCALED ) - continue; - int _d = d1 >> DISP_SHIFT; - int d_ = (d1 + DISP_SCALE-1) >> DISP_SHIFT; - int _x = x - _d, x_ = x - d_; - if( 0 <= _x && _x < width && disp2ptr[_x] >= minD && std::abs(disp2ptr[_x] - _d) > disp12MaxDiff && - 0 <= x_ && x_ < width && disp2ptr[x_] >= minD && std::abs(disp2ptr[x_] - d_) > disp12MaxDiff ) - disp1ptr[x] = (DispType)INVALID_DISP_SCALED; - } - } - - // now shift the cyclic buffers - std::swap( Lr[0], Lr[1] ); - std::swap( minLr[0], minLr[1] ); - } - } - } - - class StereoBinarySGBMImpl : public StereoBinarySGBM - { - public: - StereoBinarySGBMImpl() - { - params = StereoBinarySGBMParams(); - } - - StereoBinarySGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize, - int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, - int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, - int _mode ) - { - params = StereoBinarySGBMParams( _minDisparity, _numDisparities, _SADWindowSize, - _P1, _P2, _disp12MaxDiff, _preFilterCap, - _uniquenessRatio, _speckleWindowSize, _speckleRange, - _mode ); - } - - void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) - { - Mat left = leftarr.getMat(), right = rightarr.getMat(); - CV_Assert( left.size() == right.size() && left.type() == right.type() && - left.depth() == CV_8U ); - - disparr.create( left.size(), CV_16S ); - Mat disp = disparr.getMat(); - - computeDisparityBinarySGBM( left, right, disp, params, buffer ); - medianBlur(disp, disp, 3); - - if( params.speckleWindowSize > 0 ) - filterSpeckles(disp, (params.minDisparity - 1)*StereoMatcher::DISP_SCALE, params.speckleWindowSize, - StereoMatcher::DISP_SCALE*params.speckleRange, buffer); - } - - int getMinDisparity() const { return params.minDisparity; } - void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; } - - int getNumDisparities() const { return params.numDisparities; } - void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; } - - int getBlockSize() const { return params.SADWindowSize; } - void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; } - - int getSpeckleWindowSize() const { return params.speckleWindowSize; } - void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; } - - int getSpeckleRange() const { return params.speckleRange; } - void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; } - - int getDisp12MaxDiff() const { return params.disp12MaxDiff; } - void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; } - - int getPreFilterCap() const { return params.preFilterCap; } - void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; } - - int getUniquenessRatio() const { return params.uniquenessRatio; } - void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; } - - int getP1() const { return params.P1; } - void setP1(int P1) { params.P1 = P1; } - - int getP2() const { return params.P2; } - void setP2(int P2) { params.P2 = P2; } - - int getMode() const { return params.mode; } - void setMode(int mode) { params.mode = mode; } - - void write(FileStorage& fs) const - { - fs << "name" << name_ - << "minDisparity" << params.minDisparity - << "numDisparities" << params.numDisparities - << "blockSize" << params.SADWindowSize - << "speckleWindowSize" << params.speckleWindowSize - << "speckleRange" << params.speckleRange - << "disp12MaxDiff" << params.disp12MaxDiff - << "preFilterCap" << params.preFilterCap - << "uniquenessRatio" << params.uniquenessRatio - << "P1" << params.P1 - << "P2" << params.P2 - << "mode" << params.mode; - } - - void read(const FileNode& fn) - { - FileNode n = fn["name"]; - CV_Assert( n.isString() && String(n) == name_ ); - params.minDisparity = (int)fn["minDisparity"]; - params.numDisparities = (int)fn["numDisparities"]; - params.SADWindowSize = (int)fn["blockSize"]; - params.speckleWindowSize = (int)fn["speckleWindowSize"]; - params.speckleRange = (int)fn["speckleRange"]; - params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; - params.preFilterCap = (int)fn["preFilterCap"]; - params.uniquenessRatio = (int)fn["uniquenessRatio"]; - params.P1 = (int)fn["P1"]; - params.P2 = (int)fn["P2"]; - params.mode = (int)fn["mode"]; - } - - StereoBinarySGBMParams params; - Mat buffer; - static const char* name_; - }; - - const char* StereoBinarySGBMImpl::name_ = "StereoMatcher.SGBM"; - - Ptr StereoBinarySGBM::create(int minDisparity, int numDisparities, int SADWindowSize, - int P1, int P2, int disp12MaxDiff, - int preFilterCap, int uniquenessRatio, - int speckleWindowSize, int speckleRange, - int mode) - { - return Ptr( - new StereoBinarySGBMImpl(minDisparity, numDisparities, SADWindowSize, - P1, P2, disp12MaxDiff, - preFilterCap, uniquenessRatio, - speckleWindowSize, speckleRange, - mode)); - } - - typedef cv::Point_ Point2s; - } + { + for( d = 0; d < D; d++ ) + { + int L0 = Cp[d] + std::min((int)Lr_p0[d], std::min(Lr_p0[d-1] + P1, std::min(Lr_p0[d+1] + P1, delta0))) - delta0; + Lr_p[d] = (CostType)L0; + minL0 = std::min(minL0, L0); + int Sval = Sp[d] = saturate_cast(Sp[d] + L0); + if( Sval < minS ) + { + minS = Sval; + bestDisp = d; + } + } + minLr[0][xm] = (CostType)minL0; + } + } + else + { + for( d = 0; d < D; d++ ) + { + int Sval = Sp[d]; + if( Sval < minS ) + { + minS = Sval; + bestDisp = d; + } + } + } + for( d = 0; d < D; d++ ) + { + if( Sp[d]*(100 - uniquenessRatio) < minS*100 && std::abs(bestDisp - d) > 1 ) + break; + } + if( d < D ) + continue; + d = bestDisp; + int _x2 = x + minX1 - d - minD; + if( disp2cost[_x2] > minS ) + { + disp2cost[_x2] = (CostType)minS; + disp2ptr[_x2] = (DispType)(d + minD); + } + if( 0 < d && d < D-1 ) + { + if(params.subpixelInterpolationMethod == CV_SIMETRICV_INTERPOLATION) + { + double m2m1, m3m1, m3, m2, m1; + m2 = Sp[d - 1]; + m3 = Sp[d + 1]; + m1 = Sp[d]; + m2m1 = m2 - m1; + m3m1 = m3 - m1; + if (!(m2m1 == 0 || m3m1 == 0)) + { + double p; + p = 0; + if (m2 > m3) + { + p = (0.5 - 0.25 * ((m3m1 * m3m1) / (m2m1 * m2m1) + (m3m1 / m2m1))); + } + else + { + p = -1 * (0.5 - 0.25 * ((m2m1 * m2m1) / (m3m1 * m3m1) + (m2m1 / m3m1))); + } + if (p >= -0.5 && p <= 0.5) + d = (int)(d * DISP_SCALE + p * DISP_SCALE ); + } + else + { + d *= DISP_SCALE; + } + } + else if(params.subpixelInterpolationMethod == CV_QUADRATIC_INTERPOLATION) + { + // do subpixel quadratic interpolation: + // fit parabola into (x1=d-1, y1=Sp[d-1]), (x2=d, y2=Sp[d]), (x3=d+1, y3=Sp[d+1]) + // then find minimum of the parabola. + int denom2 = std::max(Sp[d-1] + Sp[d+1] - 2*Sp[d], 1); + d = d*DISP_SCALE + ((Sp[d-1] - Sp[d+1])*DISP_SCALE + denom2)/(denom2*2); + } + } + else + d *= DISP_SCALE; + disp1ptr[x + minX1] = (DispType)(d + minD*DISP_SCALE); + } + for( x = minX1; x < maxX1; x++ ) + { + // we round the computed disparity both towards -inf and +inf and check + // if either of the corresponding disparities in disp2 is consistent. + // This is to give the computed disparity a chance to look valid if it is. + int d1 = disp1ptr[x]; + if( d1 == INVALID_DISP_SCALED ) + continue; + int _d = d1 >> DISP_SHIFT; + int d_ = (d1 + DISP_SCALE-1) >> DISP_SHIFT; + int _x = x - _d, x_ = x - d_; + if( 0 <= _x && _x < width && disp2ptr[_x] >= minD && std::abs(disp2ptr[_x] - _d) > disp12MaxDiff && + 0 <= x_ && x_ < width && disp2ptr[x_] >= minD && std::abs(disp2ptr[x_] - d_) > disp12MaxDiff ) + disp1ptr[x] = (DispType)INVALID_DISP_SCALED; + } + } + // now shift the cyclic buffers + std::swap( Lr[0], Lr[1] ); + std::swap( minLr[0], minLr[1] ); + } + } + } + class StereoBinarySGBMImpl : public StereoBinarySGBM, public Matching + { + public: + StereoBinarySGBMImpl():Matching() + { + params = StereoBinarySGBMParams(); + } + StereoBinarySGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize, + int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap, + int _uniquenessRatio, int _speckleWindowSize, int _speckleRange, + int _mode ):Matching(_numDisparities) + { + params = StereoBinarySGBMParams( _minDisparity, _numDisparities, _SADWindowSize, + _P1, _P2, _disp12MaxDiff, _preFilterCap, + _uniquenessRatio, _speckleWindowSize, _speckleRange, + _mode ); + } + void compute( InputArray leftarr, InputArray rightarr, OutputArray disparr ) + { + Mat left = leftarr.getMat(), right = rightarr.getMat(); + CV_Assert( left.size() == right.size() && left.type() == right.type() && + left.depth() == CV_8U ); + disparr.create( left.size(), CV_16S ); + Mat disp = disparr.getMat(); + censusImageLeft.create(left.rows,left.cols,CV_32SC4); + censusImageRight.create(left.rows,left.cols,CV_32SC4); + + hamDist.create(left.rows, left.cols * (params.numDisparities + 1),CV_16S); + + if(params.kernelType == CV_SPARSE_CENSUS) + { + censusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_SPARSE_CENSUS); + } + else if(params.kernelType == CV_DENSE_CENSUS) + { + censusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_SPARSE_CENSUS); + } + else if(params.kernelType == CV_CS_CENSUS) + { + symetricCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_CS_CENSUS); + } + else if(params.kernelType == CV_MODIFIED_CS_CENSUS) + { + symetricCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MODIFIED_CS_CENSUS); + } + else if(params.kernelType == CV_MODIFIED_CENSUS_TRANSFORM) + { + modifiedCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MODIFIED_CENSUS_TRANSFORM,0); + } + else if(params.kernelType == CV_MEAN_VARIATION) + { + parSumsIntensityImage[0].create(left.rows, left.cols,CV_32SC4); + parSumsIntensityImage[1].create(left.rows, left.cols,CV_32SC4); + Integral[0].create(left.rows,left.cols,CV_32SC4); + Integral[1].create(left.rows,left.cols,CV_32SC4); + integral(left, parSumsIntensityImage[0],CV_32S); + integral(right, parSumsIntensityImage[1],CV_32S); + imageMeanKernelSize(parSumsIntensityImage[0], params.kernelSize,Integral[0]); + imageMeanKernelSize(parSumsIntensityImage[1], params.kernelSize, Integral[1]); + modifiedCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MEAN_VARIATION,0,Integral[0], Integral[1]); + } + else if(params.kernelType == CV_STAR_KERNEL) + { + starCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight); + } + + hammingDistanceBlockMatching(censusImageLeft, censusImageRight, hamDist); + + computeDisparityBinarySGBM( left, right, disp, params, buffer,hamDist); + + if(params.regionRemoval == CV_SPECKLE_REMOVAL_AVG_ALGORITHM) + { + int width = left.cols; + int height = left.rows; + if(previous_size != width * height) + { + previous_size = width * height; + speckleX.create(height,width,CV_32SC4); + speckleY.create(height,width,CV_32SC4); + puss.create(height,width,CV_32SC4); + } + Mat aux; + aux.create(height,width,CV_16S); + Median1x9Filter(disp, aux); + Median9x1Filter(aux,disp); + smallRegionRemoval(disp, params.speckleWindowSize, disp); + } + else if(params.regionRemoval == CV_SPECKLE_REMOVAL_ALGORITHM) + { + int width = left.cols; + int height = left.rows; + Mat aux; + aux.create(height,width,CV_16S); + Median1x9Filter(disp, aux); + Median9x1Filter(aux,disp); + if( params.speckleWindowSize > 0 ) + filterSpeckles(disp, (params.minDisparity - 1) * StereoMatcher::DISP_SCALE, params.speckleWindowSize, + StereoMatcher::DISP_SCALE * params.speckleRange, buffer); + } + } + int getSubPixelInterpolationMethod() const { return params.subpixelInterpolationMethod;} + void setSubPixelInterpolationMethod(int value = CV_QUADRATIC_INTERPOLATION) { CV_Assert(value < 2); params.subpixelInterpolationMethod = value;} + + int getBinaryKernelType() const { return params.kernelType;} + void setBinaryKernelType(int value = CV_MODIFIED_CENSUS_TRANSFORM) { CV_Assert(value < 7); params.kernelType = value; } + + int getSpekleRemovalTechnique() const { return params.regionRemoval;} + void setSpekleRemovalTechnique(int factor = CV_SPECKLE_REMOVAL_AVG_ALGORITHM) { CV_Assert(factor < 2); params.regionRemoval = factor; } + + int getMinDisparity() const { return params.minDisparity; } + void setMinDisparity(int minDisparity) {CV_Assert(minDisparity >= 0); params.minDisparity = minDisparity; } + + int getNumDisparities() const { return params.numDisparities; } + void setNumDisparities(int numDisparities) { CV_Assert(numDisparities > 0); params.numDisparities = numDisparities; } + + int getBlockSize() const { return params.kernelSize; } + void setBlockSize(int blockSize) {CV_Assert(blockSize % 2 != 0); params.kernelSize = blockSize; } + + int getSpeckleWindowSize() const { return params.speckleWindowSize; } + void setSpeckleWindowSize(int speckleWindowSize) {CV_Assert(speckleWindowSize >= 0); params.speckleWindowSize = speckleWindowSize; } + + int getSpeckleRange() const { return params.speckleRange; } + void setSpeckleRange(int speckleRange) { CV_Assert(speckleRange >= 0); params.speckleRange = speckleRange; } + + int getDisp12MaxDiff() const { return params.disp12MaxDiff; } + void setDisp12MaxDiff(int disp12MaxDiff) {CV_Assert(disp12MaxDiff > 0); params.disp12MaxDiff = disp12MaxDiff; } + + int getPreFilterCap() const { return params.preFilterCap; } + void setPreFilterCap(int preFilterCap) { CV_Assert(preFilterCap > 0); params.preFilterCap = preFilterCap; } + + int getUniquenessRatio() const { return params.uniquenessRatio; } + void setUniquenessRatio(int uniquenessRatio) { CV_Assert(uniquenessRatio >= 0); params.uniquenessRatio = uniquenessRatio; } + + int getP1() const { return params.P1; } + void setP1(int P1) { CV_Assert(P1 > 0); params.P1 = P1; } + + int getP2() const { return params.P2; } + void setP2(int P2) {CV_Assert(P2 > 0); CV_Assert(P2 >= 2 * params.P1); params.P2 = P2; } + + int getMode() const { return params.mode; } + void setMode(int mode) { params.mode = mode; } + + void write(FileStorage& fs) const + { + fs << "name" << name_ + << "minDisparity" << params.minDisparity + << "numDisparities" << params.numDisparities + << "blockSize" << params.kernelSize + << "speckleWindowSize" << params.speckleWindowSize + << "speckleRange" << params.speckleRange + << "disp12MaxDiff" << params.disp12MaxDiff + << "preFilterCap" << params.preFilterCap + << "uniquenessRatio" << params.uniquenessRatio + << "P1" << params.P1 + << "P2" << params.P2 + << "mode" << params.mode; + } + + void read(const FileNode& fn) + { + FileNode n = fn["name"]; + CV_Assert( n.isString() && String(n) == name_ ); + params.minDisparity = (int)fn["minDisparity"]; + params.numDisparities = (int)fn["numDisparities"]; + params.kernelSize = (int)fn["blockSize"]; + params.speckleWindowSize = (int)fn["speckleWindowSize"]; + params.speckleRange = (int)fn["speckleRange"]; + params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; + params.preFilterCap = (int)fn["preFilterCap"]; + params.uniquenessRatio = (int)fn["uniquenessRatio"]; + params.P1 = (int)fn["P1"]; + params.P2 = (int)fn["P2"]; + params.mode = (int)fn["mode"]; + } + + StereoBinarySGBMParams params; + Mat buffer; + static const char* name_; + Mat censusImageLeft; + Mat censusImageRight; + Mat partialSumsLR; + Mat agregatedHammingLRCost; + Mat hamDist; + Mat parSumsIntensityImage[2]; + Mat Integral[2]; + }; + + const char* StereoBinarySGBMImpl::name_ = "StereoBinaryMatcher.SGBM"; + + Ptr StereoBinarySGBM::create(int minDisparity, int numDisparities, int kernelSize, + int P1, int P2, int disp12MaxDiff, + int preFilterCap, int uniquenessRatio, + int speckleWindowSize, int speckleRange, + int mode) + { + return Ptr( + new StereoBinarySGBMImpl(minDisparity, numDisparities, kernelSize, + P1, P2, disp12MaxDiff, + preFilterCap, uniquenessRatio, + speckleWindowSize, speckleRange, + mode)); + } + + typedef cv::Point_ Point2s; + } } diff --git a/modules/stereo/test/test_block_matching.cpp b/modules/stereo/test/test_block_matching.cpp new file mode 100644 index 000000000..f5042fb1f --- /dev/null +++ b/modules/stereo/test/test_block_matching.cpp @@ -0,0 +1,241 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of Intel Corporation may not 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 Intel Corporation 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. +// +//M*/ + +#include "test_precomp.hpp" +#include + +using namespace cv; +using namespace cv::stereo; +using namespace std; + +class CV_BlockMatchingTest : public cvtest::BaseTest +{ +public: + CV_BlockMatchingTest(); + ~CV_BlockMatchingTest(); +protected: + void run(int /* idx */); +}; + +CV_BlockMatchingTest::CV_BlockMatchingTest(){} +CV_BlockMatchingTest::~CV_BlockMatchingTest(){} + +static double errorLevel(const Mat &ideal, Mat &actual) +{ + uint8_t *date, *harta; + harta = actual.data; + date = ideal.data; + int stride, h; + stride = (int)ideal.step; + h = ideal.rows; + int error = 0; + for (int i = 0; i < ideal.rows; i++) + { + for (int j = 0; j < ideal.cols; j++) + { + if (date[i * stride + j] != 0) + if (abs(date[i * stride + j] - harta[i * stride + j]) > 2 * 16) + { + error += 1; + } + } + } + return ((double)((error * 100) * 1.0) / (stride * h)); +} +void CV_BlockMatchingTest::run(int ) +{ + Mat image1, image2, gt; + //some test images can be found in the test data folder + //in order for the tests to build succesfully please replace + //ts->get_data_path() + "testdata/imL2l.bmp with the path from your disk + //for example if your images are on D:\\ , please write D:\\testdata\\imL2l.bmp + image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1); + image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1); + gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1); + + if(image1.empty() || image2.empty() || gt.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + + RNG range; + //set the parameters + int binary_descriptor_type = range.uniform(0,8); + int kernel_size, aggregation_window; + if(binary_descriptor_type == 0) + kernel_size = 5; + else if(binary_descriptor_type == 2 || binary_descriptor_type == 3) + kernel_size = 7; + else if(binary_descriptor_type == 1) + kernel_size = 11; + else + kernel_size = 9; + if(binary_descriptor_type == 3) + aggregation_window = 13; + else + aggregation_window = 11; + Mat test = Mat(image1.rows, image1.cols, CV_8UC1); + Ptr sbm = StereoBinaryBM::create(16, kernel_size); + //we set the corresponding parameters + sbm->setPreFilterCap(31); + sbm->setMinDisparity(0); + sbm->setTextureThreshold(10); + sbm->setUniquenessRatio(0); + sbm->setSpeckleWindowSize(400);//speckle size + sbm->setSpeckleRange(200); + sbm->setDisp12MaxDiff(0); + sbm->setScalleFactor(16);//the scaling factor + sbm->setBinaryKernelType(binary_descriptor_type);//binary descriptor kernel + sbm->setAgregationWindowSize(aggregation_window); + //speckle removal algorithm the user can choose between the average speckle removal algorithm + //or the classical version that was implemented in open cv + sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); + sbm->setUsePrefilter(false);//pre-filter or not the images prior to making the transformations + //-- calculate the disparity image + sbm->compute(image1, image2, test); + if(test.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + if(errorLevel(gt,test) > 20) + { + ts->printf( cvtest::TS::LOG, + "Too big error\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); + return; + } +} + +class CV_SGBlockMatchingTest : public cvtest::BaseTest +{ +public: + CV_SGBlockMatchingTest(); + ~CV_SGBlockMatchingTest(); +protected: + void run(int /* idx */); +}; + +CV_SGBlockMatchingTest::CV_SGBlockMatchingTest(){} +CV_SGBlockMatchingTest::~CV_SGBlockMatchingTest(){} + +void CV_SGBlockMatchingTest::run(int ) +{ + Mat image1, image2, gt; + //some test images can be found in the test data folder + image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1); + image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1); + gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1); + + + if(image1.empty() || image2.empty() || gt.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + + RNG range; + //set the parameters + int binary_descriptor_type = range.uniform(0,8); + int kernel_size; + if(binary_descriptor_type == 0) + kernel_size = 5; + else if(binary_descriptor_type == 2 || binary_descriptor_type == 3) + kernel_size = 7; + else if(binary_descriptor_type == 1) + kernel_size = 11; + else + kernel_size = 9; + + Mat test = Mat(image1.rows, image1.cols, CV_8UC1); + Mat imgDisparity16S2 = Mat(image1.rows, image1.cols, CV_16S); + Ptr sgbm = StereoBinarySGBM::create(0, 16, kernel_size); + //setting the penalties for sgbm + sgbm->setP1(10); + sgbm->setP2(100); + sgbm->setMinDisparity(0); + sgbm->setNumDisparities(16);//set disparity number + sgbm->setUniquenessRatio(1); + sgbm->setSpeckleWindowSize(400); + sgbm->setSpeckleRange(200); + sgbm->setDisp12MaxDiff(1); + sgbm->setBinaryKernelType(binary_descriptor_type);//set the binary descriptor + sgbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); //the avg speckle removal algorithm + sgbm->setSubPixelInterpolationMethod(CV_SIMETRICV_INTERPOLATION);// the SIMETRIC V interpolation method + sgbm->compute(image1, image2, imgDisparity16S2); + double minVal; double maxVal; + minMaxLoc(imgDisparity16S2, &minVal, &maxVal); + + imgDisparity16S2.convertTo(test, CV_8UC1, 255 / (maxVal - minVal)); + + if(test.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + double error = errorLevel(gt,test); + if(error > 10) + { + ts->printf( cvtest::TS::LOG, + "Too big error\n"); + ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); + return; + } +} +TEST(block_matching_simple_test, accuracy) { CV_BlockMatchingTest test; test.safe_run(); } +TEST(SG_block_matching_simple_test, accuracy) { CV_SGBlockMatchingTest test; test.safe_run(); } diff --git a/modules/stereo/test/test_descriptors.cpp b/modules/stereo/test/test_descriptors.cpp new file mode 100644 index 000000000..699cdc149 --- /dev/null +++ b/modules/stereo/test/test_descriptors.cpp @@ -0,0 +1,469 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of Intel Corporation may not 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 Intel Corporation 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. +// +//M*/ + +#include "test_precomp.hpp" +#include + +using namespace cv; +using namespace cv::stereo; +using namespace std; + +class CV_DescriptorBaseTest : public cvtest::BaseTest +{ +public: + CV_DescriptorBaseTest(); + ~CV_DescriptorBaseTest(); +protected: + virtual void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) = 0; + virtual void imageTransformation(const Mat &img1, Mat &out1) = 0; + void testROI(const Mat &img); + void testMonotonicity(const Mat &img, Mat &out); + void run(int ); + Mat censusImage[2]; + Mat censusImageSingle[2]; + Mat left; + Mat right; + int kernel_size, descriptor_type; +}; +//we test to see if the descriptor applied on a roi +//has the same value with the descriptor from the original image +//tested at the roi boundaries +void CV_DescriptorBaseTest::testROI(const Mat &img) +{ + int pt, pb,w,h; + //initialize random values for the roi top and bottom + pt = rand() % 100; + pb = rand() % 100; + //calculate the new width and height + w = img.cols; + h = img.rows - pt - pb; + int start = pt + kernel_size / 2 + 1; + int stop = h - kernel_size/2 - 1; + //set the region of interest according to above values + Rect region_of_interest = Rect(0, pt, w, h); + Mat image_roi1 = img(region_of_interest); + Mat p1,p2; + //create 2 images where to put our output + p1.create(image_roi1.rows, image_roi1.cols, CV_32SC4); + p2.create(img.rows, img.cols, CV_32SC4); + imageTransformation(image_roi1,p1); + imageTransformation(img,p2); + int *roi_data = (int *)p1.data; + int *img_data = (int *)p2.data; + //verify result + for(int i = start; i < stop; i++) + { + for(int j = 0; j < w ; j++) + { + if(roi_data[(i - pt) * w + j] != img_data[(i) * w + j]) + { + ts->printf(cvtest::TS::LOG, "Something wrong with ROI \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + return; + } + } + + } +} +CV_DescriptorBaseTest::~CV_DescriptorBaseTest() +{ + left.release(); + right.release(); + censusImage[0].release(); + censusImage[1].release(); + censusImageSingle[0].release(); + censusImageSingle[1].release(); +} +CV_DescriptorBaseTest::CV_DescriptorBaseTest() +{ + //read 2 images from file + //some test images can be found in the test data folder + //in order for the tests to build succesfully please replace + //ts->get_data_path() + "testdata/imL2l.bmp with the path from your disk + //for example if your images are on D:\\ , please write D:\\testdata\\imL2l.bmp + left = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1); + right = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1); + + if(left.empty() || right.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + ts->printf(cvtest::TS::LOG, "Data loaded \n"); +} +//verify if we don't have an image with all pixels the same( except when all input pixels are equal) +void CV_DescriptorBaseTest::testMonotonicity(const Mat &img, Mat &out) +{ + //verify if input data is correct + if(img.rows != out.rows || img.cols != out.cols || img.empty() || out.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + //verify that for an input image with different pxels the values of the + //output pixels are not the same + int same = 0; + uint8_t *data = img.data; + uint8_t val = data[1]; + int stride = (int)img.step; + for(int i = 0 ; i < img.rows && !same; i++) + { + for(int j = 0; j < img.cols; j++) + { + if(val != data[i * stride + j]) + { + same = 1; + break; + } + } + } + int value_descript = out.data[1]; + int accept = 0; + uint8_t *outData = out.data; + for(int i = 0 ; i < img.rows && !accept; i++) + { + for(int j = 0; j < img.cols; j++) + { + //we verify for the output image if the iage pixels are not all the same of an input + //image with different pixels + if(value_descript != outData[i * stride + j] && same) + { + //if we found a value that is different we accept + accept = 1; + break; + } + } + } + if(accept == 1 && same == 0) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ts->printf(cvtest::TS::LOG, "The image has all values the same \n"); + return; + } + if(accept == 0 && same == 1) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ts->printf(cvtest::TS::LOG, "For correct image we get all descriptor values the same \n"); + return; + } + ts->set_failed_test_info(cvtest::TS::OK); +} + +/////////////////////////////////// +//census transform + +class CV_CensusTransformTest: public CV_DescriptorBaseTest +{ +public: + CV_CensusTransformTest(); +protected: + void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2); + void imageTransformation(const Mat &img1, Mat &out1); +}; + +CV_CensusTransformTest::CV_CensusTransformTest() +{ + kernel_size = 11; + descriptor_type = CV_SPARSE_CENSUS; +} +void CV_CensusTransformTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty() + || img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + censusTransform(img1,img2,kernel_size,out1,out2,descriptor_type); + +} +void CV_CensusTransformTest::imageTransformation(const Mat &img1, Mat &out1) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + censusTransform(img1,kernel_size,out1,descriptor_type); +} +////////////////////////////////// +//symetric census + +class CV_SymetricCensusTest: public CV_DescriptorBaseTest +{ +public: + CV_SymetricCensusTest(); +protected: + void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2); + void imageTransformation(const Mat &img1, Mat &out1); +}; +CV_SymetricCensusTest::CV_SymetricCensusTest() +{ + kernel_size = 7; + descriptor_type = CV_CS_CENSUS; +} +void CV_SymetricCensusTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty() + || img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + symetricCensusTransform(img1,img2,kernel_size,out1,out2,descriptor_type); +} +void CV_SymetricCensusTest::imageTransformation(const Mat &img1, Mat &out1) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + symetricCensusTransform(img1,kernel_size,out1,descriptor_type); +} +////////////////////////////////// +//modified census transform +class CV_ModifiedCensusTransformTest: public CV_DescriptorBaseTest +{ +public: + CV_ModifiedCensusTransformTest(); +protected: + void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2); + void imageTransformation(const Mat &img1, Mat &out1); +}; +CV_ModifiedCensusTransformTest::CV_ModifiedCensusTransformTest() +{ + kernel_size = 9; + descriptor_type = CV_MODIFIED_CENSUS_TRANSFORM; +} +void CV_ModifiedCensusTransformTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty() + || img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + modifiedCensusTransform(img1,img2,kernel_size,out1,out2,descriptor_type); +} +void CV_ModifiedCensusTransformTest::imageTransformation(const Mat &img1, Mat &out1) +{ + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + modifiedCensusTransform(img1,kernel_size,out1,descriptor_type); +} +////////////////////////////////// +//star kernel census +class CV_StarKernelCensusTest: public CV_DescriptorBaseTest +{ +public: + CV_StarKernelCensusTest(); +protected: + void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2); + void imageTransformation(const Mat &img1, Mat &out1); +}; +CV_StarKernelCensusTest :: CV_StarKernelCensusTest() +{ + kernel_size = 9; + descriptor_type = CV_STAR_KERNEL; +} +void CV_StarKernelCensusTest :: imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) +{ + //verify if input data is correct + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty() + || img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + starCensusTransform(img1,img2,kernel_size,out1,out2); +} +void CV_StarKernelCensusTest::imageTransformation(const Mat &img1, Mat &out1) +{ + if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()) + { + ts->printf(cvtest::TS::LOG, "Wrong input / output data \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + if(kernel_size % 2 == 0) + { + ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n"); + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + starCensusTransform(img1,kernel_size,out1); +} + +void CV_DescriptorBaseTest::run(int ) +{ + if (left.empty() || right.empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + ts->printf(cvtest::TS::LOG, "No input images detected\n"); + return; + } + testROI(left); + + censusImage[0].create(left.rows, left.cols, CV_32SC4); + censusImage[1].create(left.rows, left.cols, CV_32SC4); + censusImageSingle[0].create(left.rows, left.cols, CV_32SC4); + censusImageSingle[1].create(left.rows, left.cols, CV_32SC4); + censusImage[0].setTo(0); + censusImage[1].setTo(0); + censusImageSingle[0].setTo(0); + censusImageSingle[1].setTo(0); + + imageTransformation(left, right, censusImage[0], censusImage[1]); + imageTransformation(left, censusImageSingle[0]); + imageTransformation(right, censusImageSingle[1]); + testMonotonicity(left,censusImage[0]); + testMonotonicity(right,censusImage[1]); + testMonotonicity(left,censusImageSingle[0]); + testMonotonicity(right,censusImageSingle[1]); + + if (censusImage[0].empty() || censusImage[1].empty() || censusImageSingle[0].empty() || censusImageSingle[1].empty()) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ts->printf(cvtest::TS::LOG, "The descriptor images are empty \n"); + return; + } + int *datl1 = (int *)censusImage[0].data; + int *datr1 = (int *)censusImage[1].data; + int *datl2 = (int *)censusImageSingle[0].data; + int *datr2 = (int *)censusImageSingle[1].data; + for(int i = 0; i < censusImage[0].rows - kernel_size/ 2; i++) + { + for(int j = 0; j < censusImage[0].cols; j++) + { + if(datl1[i * censusImage[0].cols + j] != datl2[i * censusImage[0].cols + j]) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ts->printf(cvtest::TS::LOG, "Mismatch for left images %d \n",descriptor_type); + return; + } + if(datr1[i * censusImage[0].cols + j] != datr2[i * censusImage[0].cols + j]) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); + ts->printf(cvtest::TS::LOG, "Mismatch for right images %d \n",descriptor_type); + return; + } + } + } + int min = numeric_limits::min(); + int max = numeric_limits::max(); + //check if all values are between int min and int max and not NAN + if (0 != cvtest::check(censusImage[0], min, max, 0)) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return; + } + //check if all values are between int min and int max and not NAN + if (0 != cvtest::check(censusImage[1], min, max, 0)) + { + ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); + return ; + } +} + +TEST(census_transform_testing, accuracy) { CV_CensusTransformTest test; test.safe_run(); } +TEST(symetric_census_testing, accuracy) { CV_SymetricCensusTest test; test.safe_run(); } +TEST(modified_census_testing, accuracy) { CV_ModifiedCensusTransformTest test; test.safe_run(); } +TEST(star_kernel_testing, accuracy) { CV_StarKernelCensusTest test; test.safe_run(); } diff --git a/modules/stereo/test/test_precomp.hpp b/modules/stereo/test/test_precomp.hpp index 6b659c327..1735d935a 100644 --- a/modules/stereo/test/test_precomp.hpp +++ b/modules/stereo/test/test_precomp.hpp @@ -12,8 +12,6 @@ #include #include "opencv2/ts.hpp" #include "opencv2/imgcodecs.hpp" - - #include "opencv2/stereo.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/features2d.hpp" @@ -22,10 +20,9 @@ #include "opencv2/core/cvdef.h" #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" +#include "opencv2/calib3d.hpp" #include #include - - #endif diff --git a/modules/stereo/testdata/groundtruth.bmp b/modules/stereo/testdata/groundtruth.bmp new file mode 100644 index 000000000..5615ed088 Binary files /dev/null and b/modules/stereo/testdata/groundtruth.bmp differ diff --git a/modules/stereo/testdata/imL2.bmp b/modules/stereo/testdata/imL2.bmp new file mode 100644 index 000000000..0db173f8c Binary files /dev/null and b/modules/stereo/testdata/imL2.bmp differ diff --git a/modules/stereo/testdata/imL2l.bmp b/modules/stereo/testdata/imL2l.bmp new file mode 100644 index 000000000..9cac9508d Binary files /dev/null and b/modules/stereo/testdata/imL2l.bmp differ diff --git a/modules/stereo/testdata/imgKitty.bmp b/modules/stereo/testdata/imgKitty.bmp new file mode 100644 index 000000000..4f89bf904 Binary files /dev/null and b/modules/stereo/testdata/imgKitty.bmp differ diff --git a/modules/stereo/testdata/imgKittyl.bmp b/modules/stereo/testdata/imgKittyl.bmp new file mode 100644 index 000000000..66afef03d Binary files /dev/null and b/modules/stereo/testdata/imgKittyl.bmp differ diff --git a/modules/stereo/testdata/rezult0.bmp b/modules/stereo/testdata/rezult0.bmp new file mode 100644 index 000000000..4d5d67b72 Binary files /dev/null and b/modules/stereo/testdata/rezult0.bmp differ diff --git a/modules/stereo/testdata/rezult0l.bmp b/modules/stereo/testdata/rezult0l.bmp new file mode 100644 index 000000000..d65538bbf Binary files /dev/null and b/modules/stereo/testdata/rezult0l.bmp differ diff --git a/modules/structured_light/CMakeLists.txt b/modules/structured_light/CMakeLists.txt index 494d58c8b..66bcc2756 100644 --- a/modules/structured_light/CMakeLists.txt +++ b/modules/structured_light/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Structured Light API") -ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_viz opencv_rgbd) \ No newline at end of file +ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd OPTIONAL opencv_viz) diff --git a/modules/structured_light/samples/pointcloud.cpp b/modules/structured_light/samples/pointcloud.cpp index f006dcb0f..97419dcc1 100644 --- a/modules/structured_light/samples/pointcloud.cpp +++ b/modules/structured_light/samples/pointcloud.cpp @@ -45,7 +45,12 @@ #include #include #include +#include + +// (if you did not build the opencv_viz module, you will only see the disparity images) +#ifdef HAVE_OPENCV_VIZ #include +#endif using namespace std; using namespace cv; @@ -73,13 +78,13 @@ static bool readStringList( const string& filename, vector& l ) if( !fs.isOpened() ) { cerr << "failed to open " << filename << endl; - return -1; + return false; } FileNode n = fs.getFirstTopLevelNode(); if( n.type() != FileNode::SEQ ) { cerr << "cam 1 images are not a sequence! FAIL" << endl; - return -1; + return false; } FileNodeIterator it = n.begin(), it_end = n.end(); @@ -92,7 +97,7 @@ static bool readStringList( const string& filename, vector& l ) if( n.type() != FileNode::SEQ ) { cerr << "cam 2 images are not a sequence! FAIL" << endl; - return -1; + return false; } it = n.begin(), it_end = n.end(); @@ -104,7 +109,7 @@ static bool readStringList( const string& filename, vector& l ) if( l.size() % 2 != 0 ) { cout << "Error: the image list contains odd (non-even) number of elements\n"; - return -1; + return false; } return true; } @@ -133,8 +138,8 @@ int main( int argc, char** argv ) if( argc == 7 ) { // If passed, setting the white and black threshold, otherwise using default values - white_thresh = parser.get( 4 ); - black_thresh = parser.get( 5 ); + white_thresh = parser.get( 4 ); + black_thresh = parser.get( 5 ); graycode->setWhiteThreshold( white_thresh ); graycode->setBlackThreshold( black_thresh ); @@ -271,6 +276,7 @@ int main( int argc, char** argv ) resize( thresholded_disp, dst, Size( 640, 480 ) ); imshow( "threshold disp otsu", dst ); +#ifdef HAVE_OPENCV_VIZ // Apply the mask to the point cloud Mat pointcloud_tresh, color_tresh; pointcloud.copyTo( pointcloud_tresh, thresholded_disp ); @@ -283,8 +289,10 @@ int main( int argc, char** argv ) myWindow.showWidget( "pointcloud", viz::WCloud( pointcloud_tresh, color_tresh ) ); myWindow.showWidget( "text2d", viz::WText( "Point cloud", Point(20, 20), 20, viz::Color::green() ) ); myWindow.spin(); +#endif // HAVE_OPENCV_VIZ + } waitKey(); return 0; -} \ No newline at end of file +} diff --git a/modules/structured_light/src/graycodepattern.cpp b/modules/structured_light/src/graycodepattern.cpp index 0418c8980..d3df7aa2a 100644 --- a/modules/structured_light/src/graycodepattern.cpp +++ b/modules/structured_light/src/graycodepattern.cpp @@ -89,11 +89,11 @@ class CV_EXPORTS_W GrayCodePattern_Impl : public GrayCodePattern // Number between 0-255 that represents the minimum brightness difference // between the fully illuminated (white) and the non - illuminated images (black) - int blackThreshold; + size_t blackThreshold; // Number between 0-255 that represents the minimum brightness difference // between the gray-code pattern and its inverse images - int whiteThreshold; + size_t whiteThreshold; // Computes the required number of pattern images, allocating the pattern vector void computeNumberOfPatternImages(); @@ -220,8 +220,8 @@ bool GrayCodePattern_Impl::decode( InputArrayOfArrays patternImages, OutputArray std::vector shadowMasks; computeShadowMasks( blackImages, whitheImages, shadowMasks ); - size_t cam_width = acquired_pattern[0][0].cols; - size_t cam_height = acquired_pattern[0][0].rows; + int cam_width = acquired_pattern[0][0].cols; + int cam_height = acquired_pattern[0][0].rows; Point projPixel; @@ -233,9 +233,9 @@ bool GrayCodePattern_Impl::decode( InputArrayOfArrays patternImages, OutputArray for( size_t k = 0; k < acquired_pattern.size(); k++ ) { camsPixels[k].resize( params.height * params.width ); - for( size_t i = 0; i < cam_width; i++ ) + for( int i = 0; i < cam_width; i++ ) { - for( size_t j = 0; j < cam_height; j++ ) + for( int j = 0; j < cam_height; j++ ) { //if the pixel is not shadowed, reconstruct if( shadowMasks[k].at( j, i ) ) @@ -345,10 +345,10 @@ void GrayCodePattern_Impl::computeShadowMasks( InputArrayOfArrays blackImages, I { for( int j = 0; j < cam_height; j++ ) { - uchar white = whiteImages_[k].at( Point( i, j ) ); - uchar black = blackImages_[k].at( Point( i, j ) ); + double white = whiteImages_[k].at( Point( i, j ) ); + double black = blackImages_[k].at( Point( i, j ) ); - if( white - black > blackThreshold ) + if( abs(white - black) > blackThreshold ) { shadowMasks_[k].at( Point( i, j ) ) = ( uchar ) 1; } @@ -472,4 +472,4 @@ Ptr GrayCodePattern::create( const GrayCodePattern::Params& par } } -} \ No newline at end of file +} diff --git a/modules/structured_light/test/test_getProjPixel.cpp b/modules/structured_light/test/test_getProjPixel.cpp index d90955fbc..91c6db5d9 100644 --- a/modules/structured_light/test/test_getProjPixel.cpp +++ b/modules/structured_light/test/test_getProjPixel.cpp @@ -73,12 +73,12 @@ void CV_GetProjPixelTest::run( int ) Point projPixel; - size_t image_width = pattern[0].cols; - size_t image_height = pattern[0].rows; + int image_width = pattern[0].cols; + int image_height = pattern[0].rows; - for( size_t i = 0; i < image_width; i++ ) + for( int i = 0; i < image_width; i++ ) { - for( size_t j = 0; j < image_height; j++ ) + for( int j = 0; j < image_height; j++ ) { //for a (x,y) pixel of the camera returns the corresponding projector pixel bool error = graycode->getProjPixel( pattern, i, j, projPixel ); @@ -97,4 +97,4 @@ TEST( GrayCodePattern, getProjPixel ) { CV_GetProjPixelTest test; test.safe_run(); -} \ No newline at end of file +} diff --git a/modules/structured_light/test/test_plane.cpp b/modules/structured_light/test/test_plane.cpp index 658f24a07..36f5b840c 100644 --- a/modules/structured_light/test/test_plane.cpp +++ b/modules/structured_light/test/test_plane.cpp @@ -45,7 +45,6 @@ #include #include #include -#include using namespace std; using namespace cv; @@ -360,4 +359,4 @@ TEST( GrayCodePattern, plane_reconstruction ) { CV_PlaneTest test; test.safe_run(); -} \ No newline at end of file +} diff --git a/modules/surface_matching/src/icp.cpp b/modules/surface_matching/src/icp.cpp index a5dd5708a..615f93d23 100644 --- a/modules/surface_matching/src/icp.cpp +++ b/modules/surface_matching/src/icp.cpp @@ -425,14 +425,14 @@ int ICP::registerModelToScene(const Mat& srcPC, const Mat& dstPC, double& residu if (node) { // select the first node - long idx = reinterpret_cast(node->data)-1, dn=0; + size_t idx = reinterpret_cast(node->data)-1, dn=0; int dup = (int)node->key-1; - long minIdxD = idx; + size_t minIdxD = idx; float minDist = distances[idx]; while ( node ) { - idx = reinterpret_cast(node->data)-1; + idx = reinterpret_cast(node->data)-1; if (distances[idx] < minDist) { diff --git a/modules/text/samples/webcam_demo.cpp b/modules/text/samples/webcam_demo.cpp index 125ff0e56..6f8d95ea7 100644 --- a/modules/text/samples/webcam_demo.cpp +++ b/modules/text/samples/webcam_demo.cpp @@ -234,7 +234,8 @@ int main(int argc, char* argv[]) frame.copyTo(out_img); - float scale_img = (float)(600.f/frame.rows); + int scale = downsize ? 2 : 1; + float scale_img = (float)((600.f/frame.rows)/scale); float scale_font = (float)(2-scale_img)/1.4f; vector words_detection; float min_confidence1 = 0.f, min_confidence2 = 0.f; @@ -318,13 +319,13 @@ int main(int argc, char* argv[]) t_all = ((double)getTickCount() - t_all)*1000/getTickFrequency(); char buff[100]; - sprintf(buff, "%2.1f Fps. @ 640x480", (float)(1000/t_all)); + sprintf(buff, "%2.1f Fps. @ %dx%d", (float)(1000/t_all), out_img.cols, out_img.rows); string fps_info = buff; - rectangle(out_img, Point(out_img.rows-160,out_img.rows-70), Point(out_img.cols,out_img.rows), Scalar(255,255,255),-1); - putText(out_img, fps_info, Point(10,out_img.rows-10), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); - putText(out_img, region_types_str[REGION_TYPE], Point(out_img.rows-150,out_img.rows-50), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); - putText(out_img, grouping_algorithms_str[GROUPING_ALGORITHM], Point(out_img.rows-150,out_img.rows-30), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); - putText(out_img, recognitions_str[RECOGNITION], Point(out_img.rows-150,out_img.rows-10), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); + rectangle(out_img, Point( out_img.rows-(160/scale),out_img.rows-(70/scale) ), Point(out_img.cols,out_img.rows), Scalar(255,255,255),-1); + putText(out_img, fps_info, Point( 10,out_img.rows-(10/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); + putText(out_img, region_types_str[REGION_TYPE], Point( out_img.rows-(150/scale),out_img.rows-(50/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); + putText(out_img, grouping_algorithms_str[GROUPING_ALGORITHM], Point( out_img.rows-(150/scale),out_img.rows-(30/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); + putText(out_img, recognitions_str[RECOGNITION], Point( out_img.rows-(150/scale),out_img.rows-(10/scale) ), FONT_HERSHEY_DUPLEX, scale_font, Scalar(255,0,0)); imshow("recognition", out_img); diff --git a/modules/tracking/CMakeLists.txt b/modules/tracking/CMakeLists.txt index b74370ea5..69a3c9a0d 100644 --- a/modules/tracking/CMakeLists.txt +++ b/modules/tracking/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Tracking API") -ocv_define_module(tracking opencv_imgproc opencv_core opencv_video opencv_highgui) +ocv_define_module(tracking opencv_imgproc opencv_core opencv_video opencv_highgui opencv_datasets) diff --git a/modules/tracking/include/opencv2/tracking/tldDataset.hpp b/modules/tracking/include/opencv2/tracking/tldDataset.hpp index 6d21a7d48..d31919ab5 100644 --- a/modules/tracking/include/opencv2/tracking/tldDataset.hpp +++ b/modules/tracking/include/opencv2/tracking/tldDataset.hpp @@ -48,7 +48,7 @@ namespace cv { namespace tld { - CV_EXPORTS cv::Rect2d tld_InitDataset(int datasetInd, const char* rootPath = "TLD_dataset"); + CV_EXPORTS cv::Rect2d tld_InitDataset(int videoInd, const char* rootPath = "TLD_dataset", int datasetInd = 0); CV_EXPORTS cv::Mat tld_getNextDatasetFrame(); } } diff --git a/modules/tracking/include/opencv2/tracking/tracker.hpp b/modules/tracking/include/opencv2/tracking/tracker.hpp index 3c7e480b5..3aef75261 100644 --- a/modules/tracking/include/opencv2/tracking/tracker.hpp +++ b/modules/tracking/include/opencv2/tracking/tracker.hpp @@ -49,6 +49,7 @@ #include "onlineBoosting.hpp" #include + #define BOILERPLATE_CODE(name,classname) \ static Ptr createTracker(const classname::Params ¶meters=classname::Params());\ virtual ~classname(){}; @@ -564,6 +565,11 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm virtual void read( const FileNode& fn )=0; virtual void write( FileStorage& fs ) const=0; + Ptr getModel() + { + return model; + } + protected: virtual bool initImpl( const Mat& image, const Rect2d& boundingBox ) = 0; @@ -576,6 +582,7 @@ class CV_EXPORTS_W Tracker : public virtual Algorithm Ptr model; }; + /************************************ Specific TrackerStateEstimator Classes ************************************/ /** @brief TrackerStateEstimator based on Boosting @@ -1197,173 +1204,253 @@ class CV_EXPORTS_W TrackerTLD : public Tracker */ class CV_EXPORTS_W TrackerKCF : public Tracker { - public: - /** - * \brief Feature type to be used in the tracking grayscale, colornames, compressed color-names - * The modes available now: - - "GRAY" -- Use grayscale values as the feature - - "CN" -- Color-names feature - */ - enum MODE { - GRAY = (1u << 0), - CN = (1u << 1), - CUSTOM = (1u<<2) - }; - - struct CV_EXPORTS Params - { - /** - * \brief Constructor - */ - Params(); - - /** - * \brief Read parameters from file, currently unused - */ - void read( const FileNode& /*fn*/ ); - - /** - * \brief Read parameters from file, currently unused - */ - void write( FileStorage& /*fs*/ ) const; - - double sigma; //!< gaussian kernel bandwidth - double lambda; //!< regularization - double interp_factor; //!< linear interpolation factor for adaptation - double output_sigma_factor; //!< spatial bandwidth (proportional to target) - double pca_learning_rate; //!< compression learning rate - bool resize; //!< activate the resize feature to improve the processing speed - bool split_coeff; //!< split the training coefficients into two matrices - bool wrap_kernel; //!< wrap around the kernel values - bool compress_feature; //!< activate the pca method to compress the features - int max_patch_size; //!< threshold for the ROI size - int compressed_size; //!< feature size after compression - unsigned int desc_pca; //!< compressed descriptors of TrackerKCF::MODE - unsigned int desc_npca; //!< non-compressed descriptors of TrackerKCF::MODE - }; - - virtual void setFeatureExtractor(void (*)(const Mat, const Rect, Mat&), bool pca_func = false); - - /** @brief Constructor - @param parameters KCF parameters TrackerKCF::Params - */ - BOILERPLATE_CODE("KCF",TrackerKCF); +public: + /** + * \brief Feature type to be used in the tracking grayscale, colornames, compressed color-names + * The modes available now: + - "GRAY" -- Use grayscale values as the feature + - "CN" -- Color-names feature + */ + enum MODE { + GRAY = (1u << 0), + CN = (1u << 1), + CUSTOM = (1u << 2) + }; + + struct CV_EXPORTS Params + { + /** + * \brief Constructor + */ + Params(); + + /** + * \brief Read parameters from file, currently unused + */ + void read(const FileNode& /*fn*/); + + /** + * \brief Read parameters from file, currently unused + */ + void write(FileStorage& /*fs*/) const; + + double sigma; //!< gaussian kernel bandwidth + double lambda; //!< regularization + double interp_factor; //!< linear interpolation factor for adaptation + double output_sigma_factor; //!< spatial bandwidth (proportional to target) + double pca_learning_rate; //!< compression learning rate + bool resize; //!< activate the resize feature to improve the processing speed + bool split_coeff; //!< split the training coefficients into two matrices + bool wrap_kernel; //!< wrap around the kernel values + bool compress_feature; //!< activate the pca method to compress the features + int max_patch_size; //!< threshold for the ROI size + int compressed_size; //!< feature size after compression + unsigned int desc_pca; //!< compressed descriptors of TrackerKCF::MODE + unsigned int desc_npca; //!< non-compressed descriptors of TrackerKCF::MODE + }; + + virtual void setFeatureExtractor(void(*)(const Mat, const Rect, Mat&), bool pca_func = false); + + /** @brief Constructor + @param parameters KCF parameters TrackerKCF::Params + */ + BOILERPLATE_CODE("KCF", TrackerKCF); }; -/************************************ MultiTracker Class ************************************/ +/************************************ MultiTracker Class ---By Laksono Kurnianggoro---) ************************************/ /** @brief This class is used to track multiple objects using the specified tracker algorithm. - * The MultiTracker is naive implementation of multiple object tracking. - * It process the tracked objects independently without any optimization accross the tracked objects. - */ +* The MultiTracker is naive implementation of multiple object tracking. +* It process the tracked objects independently without any optimization accross the tracked objects. +*/ class CV_EXPORTS_W MultiTracker { - public: - - /** - * \brief Constructor. - * In the case of trackerType is given, it will be set as the default algorithm for all trackers. - * @param trackerType the name of the tracker algorithm to be used - */ - MultiTracker(const String& trackerType = "" ); +public: - /** - * \brief Destructor - */ - ~MultiTracker(); + /** + * \brief Constructor. + * In the case of trackerType is given, it will be set as the default algorithm for all trackers. + * @param trackerType the name of the tracker algorithm to be used + */ + MultiTracker(const String& trackerType = ""); + + /** + * \brief Destructor + */ + ~MultiTracker(); + + /** + * \brief Add a new object to be tracked. + * The defaultAlgorithm will be used the newly added tracker. + * @param image input image + * @param boundingBox a rectangle represents ROI of the tracked object + */ + bool add(const Mat& image, const Rect2d& boundingBox); + + /** + * \brief Add a new object to be tracked. + * @param trackerType the name of the tracker algorithm to be used + * @param image input image + * @param boundingBox a rectangle represents ROI of the tracked object + */ + bool add(const String& trackerType, const Mat& image, const Rect2d& boundingBox); + + /** + * \brief Add a set of objects to be tracked. + * @param trackerType the name of the tracker algorithm to be used + * @param image input image + * @param boundingBox list of the tracked objects + */ + bool add(const String& trackerType, const Mat& image, std::vector boundingBox); + + /** + * \brief Add a set of objects to be tracked using the defaultAlgorithm tracker. + * @param image input image + * @param boundingBox list of the tracked objects + */ + bool add(const Mat& image, std::vector boundingBox); + + /** + * \brief Update the current tracking status. + * The result will be saved in the internal storage. + * @param image input image + */ + bool update(const Mat& image); + + //!< storage for the tracked objects, each object corresponds to one tracker algorithm. + std::vector objects; + + /** + * \brief Update the current tracking status. + * @param image input image + * @param boundingBox the tracking result, represent a list of ROIs of the tracked objects. + */ + bool update(const Mat& image, std::vector & boundingBox); - /** - * \brief Add a new object to be tracked. - * The defaultAlgorithm will be used the newly added tracker. - * @param image input image - * @param boundingBox a rectangle represents ROI of the tracked object - */ - bool add( const Mat& image, const Rect2d& boundingBox ); +protected: + //!< storage for the tracker algorithms. + std::vector< Ptr > trackerList; - /** - * \brief Add a new object to be tracked. - * @param trackerType the name of the tracker algorithm to be used - * @param image input image - * @param boundingBox a rectangle represents ROI of the tracked object - */ - bool add( const String& trackerType, const Mat& image, const Rect2d& boundingBox ); + //!< default algorithm for the tracking method. + String defaultAlgorithm; +}; - /** - * \brief Add a set of objects to be tracked. - * @param trackerType the name of the tracker algorithm to be used - * @param image input image - * @param boundingBox list of the tracked objects - */ - bool add(const String& trackerType, const Mat& image, std::vector boundingBox); +class ROISelector { +public: + Rect2d select(Mat img, bool fromCenter = true); + Rect2d select(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); + void select(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); - /** - * \brief Add a set of objects to be tracked using the defaultAlgorithm tracker. - * @param image input image - * @param boundingBox list of the tracked objects - */ - bool add(const Mat& image, std::vector boundingBox); + struct handlerT{ + // basic parameters + bool isDrawing; + Rect2d box; + Mat image; - /** - * \brief Update the current tracking status. - * The result will be saved in the internal storage. - * @param image input image - */ - bool update( const Mat& image); + // parameters for drawing from the center + bool drawFromCenter; + Point2f center; - //!< storage for the tracked objects, each object corresponds to one tracker algorithm. - std::vector objects; + // initializer list + handlerT() : isDrawing(false), drawFromCenter(true) {}; + }selectorParams; - /** - * \brief Update the current tracking status. - * @param image input image - * @param boundingBox the tracking result, represent a list of ROIs of the tracked objects. - */ - bool update( const Mat& image, std::vector & boundingBox ); + // to store the tracked objects + std::vector objects; - protected: - //!< storage for the tracker algorithms. - std::vector< Ptr > trackerList; +private: + static void mouseHandler(int event, int x, int y, int flags, void *param); + void opencv_mouse_callback(int event, int x, int y, int, void *param); - //!< default algorithm for the tracking method. - String defaultAlgorithm; + // save the keypressed characted + int key; }; -class ROISelector { +Rect2d CV_EXPORTS_W selectROI(Mat img, bool fromCenter = true); +Rect2d CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); +void CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); + + +/************************************ Multi-Tracker Classes ---By Tyan Vladimir---************************************/ + +/** @brief Base abstract class for the long-term Multi Object Trackers: + +@sa Tracker, MultiTrackerTLD +*/ +class CV_EXPORTS_W MultiTracker_Alt +{ public: - Rect2d select(Mat img, bool fromCenter = true); - Rect2d select(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); - void select(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); + /** @brief Constructor for Multitracker + */ + MultiTracker_Alt() + { + targetNum = 0; + } + + /** @brief Add a new target to a tracking-list and initialize the tracker with a know bounding box that surrounding the target + @param image The initial frame + @param boundingBox The initial boundig box of target + @param tracker_algorithm_name Multi-tracker algorithm name + + @return True if new target initialization went succesfully, false otherwise + */ + bool addTarget(const Mat& image, const Rect2d& boundingBox, String tracker_algorithm_name); + + /** @brief Update all trackers from the tracking-list, find a new most likely bounding boxes for the targets + @param image The current frame + + @return True means that all targets were located and false means that tracker couldn't locate one of the targets in + current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed + missing from the frame (say, out of sight) + */ + bool update(const Mat& image); + + /** @brief Current number of targets in tracking-list + */ + int targetNum; + + /** @brief Trackers list for Multi-Object-Tracker + */ + std::vector > trackers; + + /** @brief Bounding Boxes list for Multi-Object-Tracker + */ + std::vector boundingBoxes; + /** @brief List of randomly generated colors for bounding boxes display + */ + std::vector colors; +}; - struct handlerT{ - // basic parameters - bool isDrawing; - Rect2d box; - Mat image; +/** @brief Multi Object Tracker for TLD. TLD is a novel tracking framework that explicitly decomposes +the long-term tracking task into tracking, learning and detection. - // parameters for drawing from the center - bool drawFromCenter; - Point2f center; +The tracker follows the object from frame to frame. The detector localizes all appearances that +have been observed so far and corrects the tracker if necessary. The learning estimates detector’s +errors and updates it to avoid these errors in the future. The implementation is based on @cite TLD . - // initializer list - handlerT(): isDrawing(false), drawFromCenter(true) {}; - }selectorParams; +The Median Flow algorithm (see cv::TrackerMedianFlow) was chosen as a tracking component in this +implementation, following authors. Tracker is supposed to be able to handle rapid motions, partial +occlusions, object absence etc. - // to store the tracked objects - std::vector objects; +@sa Tracker, MultiTracker, TrackerTLD +*/ +class CV_EXPORTS_W MultiTrackerTLD : public MultiTracker_Alt +{ +public: + /** @brief Update all trackers from the tracking-list, find a new most likely bounding boxes for the targets by + optimized update method using some techniques to speedup calculations specifically for MO TLD. The only limitation + is that all target bounding boxes should have approximately same aspect ratios. Speed boost is around 20% -private: - static void mouseHandler(int event, int x, int y, int flags, void *param); - void opencv_mouse_callback( int event, int x, int y, int , void *param ); + @param image The current frame. - // save the keypressed characted - int key; + @return True means that all targets were located and false means that tracker couldn't locate one of the targets in + current frame. Note, that latter *does not* imply that tracker has failed, maybe target is indeed + missing from the frame (say, out of sight) + */ + bool update_opt(const Mat& image); }; -Rect2d CV_EXPORTS_W selectROI(Mat img, bool fromCenter = true); -Rect2d CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); -void CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); +//! @} } /* namespace cv */ -//! @} - #endif diff --git a/modules/tracking/samples/multiTracker_dataset.cpp b/modules/tracking/samples/multiTracker_dataset.cpp new file mode 100644 index 000000000..ce4c70551 --- /dev/null +++ b/modules/tracking/samples/multiTracker_dataset.cpp @@ -0,0 +1,230 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "opencv2/datasets/track_vot.hpp" +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; +using namespace cv::datasets; + +#define NUM_TEST_FRAMES 1000 + +static Mat image; +static bool paused; +static bool selectObjects = false; +static bool startSelection = false; +vector boundingBoxes; +int targetsCnt = 0; +int targetsNum = 0; +Rect2d boundingBox; + +static const char* keys = +{ "{@tracker_algorithm | | Tracker algorithm }" +"{@target_num |1| Number of targets }" +"{@dataset_path |true| Dataset path }" +"{@dataset_id |1| Dataset ID }" +}; + +static void onMouse(int event, int x, int y, int, void*) +{ + if (!selectObjects) + { + switch (event) + { + case EVENT_LBUTTONDOWN: + //set origin of the bounding box + startSelection = true; + boundingBox.x = x; + boundingBox.y = y; + boundingBox.width = boundingBox.height = 0; + break; + case EVENT_LBUTTONUP: + //sei with and height of the bounding box + boundingBox.width = std::abs(x - boundingBox.x); + boundingBox.height = std::abs(y - boundingBox.y); + boundingBoxes.push_back(boundingBox); + targetsCnt++; + if (targetsCnt == targetsNum) + { + paused = false; + selectObjects = true; + } + startSelection = false; + break; + case EVENT_MOUSEMOVE: + + if (startSelection && !selectObjects) + { + //draw the bounding box + Mat currentFrame; + image.copyTo(currentFrame); + for (int i = 0; i < (int)boundingBoxes.size(); i++) + rectangle(currentFrame, boundingBoxes[i], Scalar(255, 0, 0), 2, 1); + rectangle(currentFrame, Point((int)boundingBox.x, (int)boundingBox.y), Point(x, y), Scalar(255, 0, 0), 2, 1); + imshow("Tracking API", currentFrame); + } + break; + } + } +} + +static void help() +{ + cout << "\nThis example shows the functionality of \"Long-term optical tracking API\"" + "TLD dataset ID: 1~10, VOT2015 dataset ID: 1~60\n" + "-- pause video [p] and draw a bounding boxes around the targets to start the tracker\n" + "Example:\n" + "./example_tracking_multiTracker_dataset \n" + << endl; + + cout << "\n\nHot keys: \n" + "\tq - quit the program\n" + "\tp - pause video\n"; +} + +int main(int argc, char *argv[]) +{ + CommandLineParser parser(argc, argv, keys); + string tracker_algorithm = parser.get(0); + targetsNum = parser.get(1); + string datasetRootPath = parser.get(2); + int datasetID = parser.get(3); + if (tracker_algorithm.empty() || datasetRootPath.empty() || targetsNum < 1) + { + help(); + return -1; + } + + Mat frame; + paused = false; + namedWindow("Tracking API", 0); + setMouseCallback("Tracking API", onMouse, 0); + + MultiTrackerTLD mt; + //Init Dataset + Ptr dataset = TRACK_vot::create(); + dataset->load(datasetRootPath); + dataset->initDataset(datasetID); + + //Read first frame + dataset->getNextFrame(frame); + frame.copyTo(image); + for (int i = 0; i < (int)boundingBoxes.size(); i++) + rectangle(image, boundingBoxes[i], Scalar(255, 0, 0), 2, 1); + imshow("Tracking API", image); + + bool initialized = false; + paused = true; + int frameCounter = 0; + + //Time measurment + int64 e3 = getTickCount(); + + for (;;) + { + if (!paused) + { + //Time measurment + int64 e1 = getTickCount(); + if (initialized){ + if (!dataset->getNextFrame(frame)) + break; + frame.copyTo(image); + } + + if (!initialized && selectObjects) + { + //Initialize the tracker and add targets + for (int i = 0; i < (int)boundingBoxes.size(); i++) + { + if (!mt.addTarget(frame, boundingBoxes[i], tracker_algorithm)) + { + cout << "Trackers Init Error!!!"; + return 0; + } + rectangle(frame, boundingBoxes[i], mt.colors[0], 2, 1); + } + initialized = true; + } + else if (initialized) + { + //Update all targets + if (mt.update(frame)) + { + for (int i = 0; i < mt.targetNum; i++) + { + rectangle(frame, mt.boundingBoxes[i], mt.colors[i], 2, 1); + } + } + } + imshow("Tracking API", frame); + frameCounter++; + //Time measurment + int64 e2 = getTickCount(); + double t1 = (e2 - e1) / getTickFrequency(); + cout << frameCounter << "\tframe : " << t1 * 1000.0 << "ms" << endl; + } + + char c = (char)waitKey(2); + if (c == 'q') + break; + if (c == 'p') + paused = !paused; + + //waitKey(0); + } + + //Time measurment + int64 e4 = getTickCount(); + double t2 = (e4 - e3) / getTickFrequency(); + cout << "Average Time for Frame: " << t2 * 1000.0 / frameCounter << "ms" << endl; + cout << "Average FPS: " << 1.0 / t2*frameCounter << endl; + + + waitKey(0); + + return 0; +} \ No newline at end of file diff --git a/modules/tracking/samples/tracker.cpp b/modules/tracking/samples/tracker.cpp index 57187a96b..3a1295959 100644 --- a/modules/tracking/samples/tracker.cpp +++ b/modules/tracking/samples/tracker.cpp @@ -61,6 +61,7 @@ static void help() "Example of is in opencv_extra/testdata/cv/tracking/\n" "Call:\n" "./tracker []\n" + "tracker_algorithm can be: MIL, BOOSTING, MEDIANFLOW, TLD\n" << endl; cout << "\n\nHot keys: \n" diff --git a/modules/tracking/samples/tld_test.cpp b/modules/tracking/samples/tracker_dataset.cpp similarity index 70% rename from modules/tracking/samples/tld_test.cpp rename to modules/tracking/samples/tracker_dataset.cpp index 6db5e7a08..489469fea 100644 --- a/modules/tracking/samples/tld_test.cpp +++ b/modules/tracking/samples/tracker_dataset.cpp @@ -39,17 +39,21 @@ // //M*/ +#include "opencv2/datasets/track_vot.hpp" #include #include #include #include +#include + #include using namespace std; using namespace cv; +using namespace cv::datasets; -#define NUM_TEST_FRAMES 100 -#define TEST_VIDEO_INDEX 7 //TLD Dataset Video Index from 1-10 +#define NUM_TEST_FRAMES 300 +#define TEST_VIDEO_INDEX 1 //TLD Dataset Video Index from 1-10 //#define RECORD_VIDEO_FLG static Mat image; @@ -58,6 +62,12 @@ static bool paused; static bool selectObject = false; static bool startSelection = false; +static const char* keys = +{ "{@tracker_algorithm | | Tracker algorithm }" +"{@dataset_path |true| Dataset path }" +"{@dataset_id |1| Dataset ID }" +}; + static void onMouse(int event, int x, int y, int, void*) { if (!selectObject) @@ -93,19 +103,39 @@ static void onMouse(int event, int x, int y, int, void*) } } -int main() +static void help() +{ + cout << "\nThis example shows the functionality of \"Long-term optical tracking API\"" + "TLD dataset ID: 1~10, VOT2015 dataset ID: 1~60\n" + "-- pause video [p] and draw a bounding box around the target to start the tracker\n" + "Example:\n" + "./example_tracking_tracker_dataset \n" + << endl; + + cout << "\n\nHot keys: \n" + "\tq - quit the program\n" + "\tp - pause video\n"; +} + +int main(int argc, char *argv[]) { - // - // "MIL", "BOOSTING", "MEDIANFLOW", "TLD" - // - string tracker_algorithm_name = "TLD"; + CommandLineParser parser(argc, argv, keys); + string tracker_algorithm = parser.get(0); + string datasetRootPath = parser.get(1); + int datasetID = parser.get(2); + if (tracker_algorithm.empty() || datasetRootPath.empty()) + { + help(); + return -1; + } Mat frame; paused = false; namedWindow("Tracking API", 0); setMouseCallback("Tracking API", onMouse, 0); - Ptr tracker = Tracker::create(tracker_algorithm_name); + //Create Tracker + Ptr tracker = Tracker::create(tracker_algorithm); if (tracker == NULL) { cout << "***Error in the instantiation of the tracker...***\n"; @@ -113,107 +143,72 @@ int main() return 0; } - //Get the first frame - ////Open the capture - // VideoCapture cap(0); - // if( !cap.isOpened() ) - // { - // cout << "Video stream error"; - // return; - // } - //cap >> frame; - - //From TLD dataset - selectObject = true; - boundingBox = tld::tld_InitDataset(TEST_VIDEO_INDEX, "D:/opencv/TLD_dataset"); - - frame = tld::tld_getNextDatasetFrame(); - frame.copyTo(image); + //Init Dataset + Ptr dataset = TRACK_vot::create(); + dataset->load(datasetRootPath); + dataset->initDataset(datasetID); - // Setup output video -#ifdef RECORD_VIDEO_FLG - String outputFilename = "test.avi"; - VideoWriter outputVideo; - outputVideo.open(outputFilename, -1, 30, Size(image.cols, image.rows)); - - if (!outputVideo.isOpened()) - { - std::cout << "!!! Output video could not be opened" << std::endl; - getchar(); - return; - } -#endif + //Read first frame + dataset->getNextFrame(frame); + frame.copyTo(image); rectangle(image, boundingBox, Scalar(255, 0, 0), 2, 1); imshow("Tracking API", image); bool initialized = false; + paused = true; int frameCounter = 0; //Time measurment int64 e3 = getTickCount(); - for (;;) { - //Time measurment - int64 e1 = getTickCount(); - //Frame num - frameCounter++; - if (frameCounter == NUM_TEST_FRAMES) break; - - char c = (char)waitKey(2); - if (c == 'q' || c == 27) - break; - if (c == 'p') - paused = !paused; - if (!paused) { - //cap >> frame; - frame = tld::tld_getNextDatasetFrame(); - if (frame.empty()) - { - break; + //Time measurment + int64 e1 = getTickCount(); + if (initialized){ + if (!dataset->getNextFrame(frame)) + break; + frame.copyTo(image); } - frame.copyTo(image); - if (selectObject) + if (!initialized && selectObject) { - if (!initialized) + //initializes the tracker + if (!tracker->init(frame, boundingBox)) { - //initializes the tracker - if (!tracker->init(frame, boundingBox)) - { - cout << "***Could not initialize tracker...***\n"; - return 0; - } - initialized = true; - rectangle(image, boundingBox, Scalar(255, 0, 0), 2, 1); + cout << "***Could not initialize tracker...***\n"; + return -1; } - else + initialized = true; + } + else if (initialized) + { + //updates the tracker + if (tracker->update(frame, boundingBox)) { - //updates the tracker - if (tracker->update(frame, boundingBox)) - { - rectangle(image, boundingBox, Scalar(255, 0, 0), 2, 1); - } + rectangle(image, boundingBox, Scalar(255, 0, 0), 2, 1); } } imshow("Tracking API", image); - -#ifdef RECORD_VIDEO_FLG - outputVideo << image; -#endif - - + frameCounter++; //Time measurment int64 e2 = getTickCount(); double t1 = (e2 - e1) / getTickFrequency(); cout << frameCounter << "\tframe : " << t1 * 1000.0 << "ms" << endl; - - //waitKey(0); } + + char c = (char)waitKey(2); + if (c == 'q') + break; + if (c == 'p') + paused = !paused; + + + + //waitKey(0); } //Time measurment diff --git a/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp b/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp new file mode 100644 index 000000000..3131be397 --- /dev/null +++ b/modules/tracking/samples/tutorial_customizing_cn_tracker.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +// prototype of the functino for feature extractor +void sobelExtractor(const Mat img, const Rect roi, Mat& feat); + +int main( int argc, char** argv ){ + // show help + if(argc<2){ + cout<< + " Usage: tracker \n" + " examples:\n" + " example_tracking_kcf Bolt/img/%04d.jpg\n" + " example_tracking_kcf faceocc2.webm\n" + << endl; + return 0; + } + + // declares all required variables + Rect2d roi; + Mat frame; + + //! [param] + TrackerKCF::Params param; + param.desc_pca = TrackerKCF::GRAY | TrackerKCF::CN; + param.desc_npca = 0; + param.compress_feature = true; + param.compressed_size = 2; + //! [param] + + // create a tracker object + //! [create] + Ptr tracker = TrackerKCF::createTracker(param); + //! [create] + + //! [setextractor] + tracker->setFeatureExtractor(sobelExtractor); + //! [setextractor] + + // set input video + std::string video = argv[1]; + VideoCapture cap(video); + + // get bounding box + cap >> frame; + roi=selectROI("tracker",frame); + + //quit if ROI was not selected + if(roi.width==0 || roi.height==0) + return 0; + + // initialize the tracker + tracker->init(frame,roi); + + // perform the tracking process + printf("Start the tracking process, press ESC to quit.\n"); + for ( ;; ){ + // get frame from the video + cap >> frame; + + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + // update the tracking result + tracker->update(frame,roi); + + // draw the tracked object + rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 ); + + // show image with the tracked object + imshow("tracker",frame); + + //quit on ESC button + if(waitKey(1)==27)break; + } + + return 0; +} + +void sobelExtractor(const Mat img, const Rect roi, Mat& feat){ + Mat sobel[2]; + Mat patch; + Rect region=roi; + + //! [insideimage] + // extract patch inside the image + if(roi.x<0){region.x=0;region.width+=roi.x;} + if(roi.y<0){region.y=0;region.height+=roi.y;} + if(roi.x+roi.width>img.cols)region.width=img.cols-roi.x; + if(roi.y+roi.height>img.rows)region.height=img.rows-roi.y; + if(region.width>img.cols)region.width=img.cols; + if(region.height>img.rows)region.height=img.rows; + //! [insideimage] + + patch=img(region).clone(); + cvtColor(patch,patch, CV_BGR2GRAY); + + //! [padding] + // add some padding to compensate when the patch is outside image border + int addTop,addBottom, addLeft, addRight; + addTop=region.y-roi.y; + addBottom=(roi.height+roi.y>img.rows?roi.height+roi.y-img.rows:0); + addLeft=region.x-roi.x; + addRight=(roi.width+roi.x>img.cols?roi.width+roi.x-img.cols:0); + + copyMakeBorder(patch,patch,addTop,addBottom,addLeft,addRight,BORDER_REPLICATE); + //! [padding] + + //! [sobel] + Sobel(patch, sobel[0], CV_32F,1,0,1); + Sobel(patch, sobel[1], CV_32F,0,1,1); + + merge(sobel,2,feat); + //! [sobel] + + //! [postprocess] + feat.convertTo(feat,CV_64F); + feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5 + //! [postprocess] +} diff --git a/modules/tracking/samples/tutorial_introduction_to_tracker.cpp b/modules/tracking/samples/tutorial_introduction_to_tracker.cpp new file mode 100644 index 000000000..d9907fac3 --- /dev/null +++ b/modules/tracking/samples/tutorial_introduction_to_tracker.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ){ + // show help + //! [help] + if(argc<2){ + cout<< + " Usage: tracker \n" + " examples:\n" + " example_tracking_kcf Bolt/img/%04d.jpg\n" + " example_tracking_kcf faceocc2.webm\n" + << endl; + return 0; + } + //! [help] + + // declares all required variables + //! [vars] + Rect2d roi; + Mat frame; + //! [vars] + + // create a tracker object + //! [create] + Ptr tracker = Tracker::create( "KCF" ); + //! [create] + + // set input video + //! [setvideo] + std::string video = argv[1]; + VideoCapture cap(video); + //! [setvideo] + + // get bounding box + //! [getframe] + cap >> frame; + //! [getframe] + //! [selectroi] + roi=selectROI("tracker",frame); + //! [selectroi] + + //quit if ROI was not selected + if(roi.width==0 || roi.height==0) + return 0; + + // initialize the tracker + //! [init] + tracker->init(frame,roi); + //! [init] + + // perform the tracking process + printf("Start the tracking process, press ESC to quit.\n"); + for ( ;; ){ + // get frame from the video + cap >> frame; + + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + // update the tracking result + //! [update] + tracker->update(frame,roi); + //! [update] + + //! [visualization] + // draw the tracked object + rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 ); + + // show image with the tracked object + imshow("tracker",frame); + //! [visualization] + + //quit on ESC button + if(waitKey(1)==27)break; + } + + return 0; +} diff --git a/modules/tracking/samples/tutorial_multitracker.cpp b/modules/tracking/samples/tutorial_multitracker.cpp new file mode 100644 index 000000000..0d14c2087 --- /dev/null +++ b/modules/tracking/samples/tutorial_multitracker.cpp @@ -0,0 +1,99 @@ +/*---------------------------------------------- + * Usage: + * example_tracking_multitracker [algorithm] + * + * example: + * example_tracking_multitracker Bolt/img/%04d.jpg + * example_tracking_multitracker faceocc2.webm KCF + *--------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace cv; + +int main( int argc, char** argv ){ + // show help + if(argc<2){ + cout<< + " Usage: example_tracking_multitracker [algorithm]\n" + " examples:\n" + " example_tracking_multitracker Bolt/img/%04d.jpg\n" + " example_tracking_multitracker faceocc2.webm MEDIANFLOW\n" + << endl; + return 0; + } + + // set the default tracking algorithm + std::string trackingAlg = "KCF"; + + // set the tracking algorithm from parameter + if(argc>2) + trackingAlg = argv[2]; + + // create the tracker + //! [create] + MultiTracker trackers(trackingAlg); + //! [create] + + // container of the tracked objects + //! [roi] + vector objects; + //! [roi] + + // set input video + std::string video = argv[1]; + VideoCapture cap(video); + + Mat frame; + + // get bounding box + cap >> frame; + //! [selectmulti] + selectROI("tracker",frame,objects); + //! [selectmulti] + + //quit when the tracked object(s) is not provided + if(objects.size()<1) + return 0; + + // initialize the tracker + //! [init] + trackers.add(frame,objects); + //! [init] + + // do the tracking + printf("Start the tracking process, press ESC to quit.\n"); + for ( ;; ){ + // get frame from the video + cap >> frame; + + // stop the program if no more images + if(frame.rows==0 || frame.cols==0) + break; + + //update the tracking result + //! [update] + trackers.update(frame); + //! [update] + + //! [result] + // draw the tracked object + for(unsigned i=0;i newTracker = Tracker::create( trackerType ); - - // add the created tracker algorithm to the trackers list - trackerList.push_back(newTracker); - - // add the ROI to the bounding box list - objects.push_back(boundingBox); - - // initialize the created tracker - return trackerList.back()->init(image, boundingBox); - }; - - // add a set of objects to be tracked - bool MultiTracker::add(const String& trackerType, const Mat& image, std::vector boundingBox){ - // status of the tracker addition - bool stat=false; - - // add tracker for all input objects - for(unsigned i =0;i boundingBox){ - // quit if defaultAlgorithm has not been configured - if(defaultAlgorithm==""){ - printf("Default algorithm was not defined!\n"); - return false; - } - - return add(defaultAlgorithm.c_str(), image, boundingBox); - }; - - // update position of the tracked objects, the result is stored in internal storage - bool MultiTracker::update( const Mat& image){ - for(unsigned i=0;i< trackerList.size(); i++){ - trackerList[i]->update(image, objects[i]); - } - return true; - }; - - // update position of the tracked objects, the result is copied to external variable - bool MultiTracker::update( const Mat& image, std::vector & boundingBox ){ - update(image); - boundingBox=objects; - return true; - }; - -} /* namespace cv */ +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#include "multiTracker.hpp" + +namespace cv +{ + //Multitracker + bool MultiTracker_Alt::addTarget(const Mat& image, const Rect2d& boundingBox, String tracker_algorithm_name) + { + Ptr tracker = Tracker::create(tracker_algorithm_name); + if (tracker == NULL) + return false; + + if (!tracker->init(image, boundingBox)) + return false; + + //Add BB of target + boundingBoxes.push_back(boundingBox); + + //Add Tracker to stack + trackers.push_back(tracker); + + //Assign a random color to target + if (targetNum == 1) + colors.push_back(Scalar(0, 0, 255)); + else + colors.push_back(Scalar(rand() % 256, rand() % 256, rand() % 256)); + + + + //Target counter + targetNum++; + + return true; + } + + bool MultiTracker_Alt::update(const Mat& image) + { + for (int i = 0; i < (int)trackers.size(); i++) + if (!trackers[i]->update(image, boundingBoxes[i])) + return false; + + return true; + } + + //Multitracker TLD + /*Optimized update method for TLD Multitracker */ + bool MultiTrackerTLD::update_opt(const Mat& image) + { + //Get parameters from first object + //TLD Tracker data extraction + Tracker* trackerPtr = trackers[0]; + tld::TrackerTLDImpl* tracker = static_cast(trackerPtr); + //TLD Model Extraction + tld::TrackerTLDModel* tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + Ptr data = tracker->data; + double scale = data->getScale(); + + Mat image_gray, image_blurred, imageForDetector; + cvtColor(image, image_gray, COLOR_BGR2GRAY); + + if (scale > 1.0) + resize(image_gray, imageForDetector, Size(cvRound(image.cols*scale), cvRound(image.rows*scale)), 0, 0, tld::DOWNSCALE_MODE); + else + imageForDetector = image_gray; + GaussianBlur(imageForDetector, image_blurred, tld::GaussBlurKernelSize, 0.0); + + //best overlap around 92% + Mat_ standardPatch(tld::STANDARD_PATCH_SIZE, tld::STANDARD_PATCH_SIZE); + + std::vector > detectorResults(targetNum); + std::vector > candidates(targetNum); + std::vector > candidatesRes(targetNum); + std::vector tmpCandidates(targetNum); + std::vector detect_flgs(targetNum); + std::vector trackerNeedsReInit(targetNum); + + bool DETECT_FLG = false; + + //Detect all + for (int k = 0; k < targetNum; k++) + tmpCandidates[k] = boundingBoxes[k]; +#ifdef HAVE_OPENCL + if (ocl::haveOpenCL()) + ocl_detect_all(imageForDetector, image_blurred, tmpCandidates, detectorResults, detect_flgs, trackers); + else +#endif + detect_all(imageForDetector, image_blurred, tmpCandidates, detectorResults, detect_flgs, trackers); + + for (int k = 0; k < targetNum; k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + data = tracker->data; + + data->frameNum++; + + for (int i = 0; i < 2; i++) + { + Rect2d tmpCandid = boundingBoxes[k]; + + //if (i == 1) + { + DETECT_FLG = detect_flgs[k]; + tmpCandid = tmpCandidates[k]; + } + + if (((i == 0) && !data->failedLastTime && tracker->trackerProxy->update(image, tmpCandid)) || (DETECT_FLG)) + { + candidates[k].push_back(tmpCandid); + if (i == 0) + tld::resample(image_gray, tmpCandid, standardPatch); + else + tld::resample(imageForDetector, tmpCandid, standardPatch); + candidatesRes[k].push_back(tldModel->detector->Sc(standardPatch)); + } + else + { + if (i == 0) + trackerNeedsReInit[k] = true; + else + trackerNeedsReInit[k] = false; + } + } + + std::vector::iterator it = std::max_element(candidatesRes[k].begin(), candidatesRes[k].end()); + + + if (it == candidatesRes[k].end()) + { + + data->confident = false; + data->failedLastTime = true; + return false; + } + else + { + boundingBoxes[k] = candidates[k][it - candidatesRes[k].begin()]; + data->failedLastTime = false; + if (trackerNeedsReInit[k] || it != candidatesRes[k].begin()) + tracker->trackerProxy->init(image, boundingBoxes[k]); + } + +#if 1 + if (it != candidatesRes[k].end()) + tld::resample(imageForDetector, candidates[k][it - candidatesRes[k].begin()], standardPatch); +#endif + + if (*it > tld::CORE_THRESHOLD) + data->confident = true; + + if (data->confident) + { + tld::TrackerTLDImpl::Pexpert pExpert(imageForDetector, image_blurred, boundingBoxes[k], tldModel->detector, tracker->params, data->getMinSize()); + tld::TrackerTLDImpl::Nexpert nExpert(imageForDetector, boundingBoxes[k], tldModel->detector, tracker->params); + std::vector > examplesForModel, examplesForEnsemble; + examplesForModel.reserve(100); examplesForEnsemble.reserve(100); + int negRelabeled = 0; + for (int i = 0; i < (int)detectorResults[k].size(); i++) + { + bool expertResult; + if (detectorResults[k][i].isObject) + { + expertResult = nExpert(detectorResults[k][i].rect); + if (expertResult != detectorResults[k][i].isObject) + negRelabeled++; + } + else + { + expertResult = pExpert(detectorResults[k][i].rect); + } + + detectorResults[k][i].shouldBeIntegrated = detectorResults[k][i].shouldBeIntegrated || (detectorResults[k][i].isObject != expertResult); + detectorResults[k][i].isObject = expertResult; + } + tldModel->integrateRelabeled(imageForDetector, image_blurred, detectorResults[k]); + pExpert.additionalExamples(examplesForModel, examplesForEnsemble); +#ifdef HAVE_OPENCL + if (ocl::haveOpenCL()) + tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, true); + else +#endif + tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, true); + examplesForModel.clear(); examplesForEnsemble.clear(); + nExpert.additionalExamples(examplesForModel, examplesForEnsemble); + +#ifdef HAVE_OPENCL + if (ocl::haveOpenCL()) + tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, false); + else +#endif + tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, false); + } + else + { +#ifdef CLOSED_LOOP + tldModel->integrateRelabeled(imageForDetector, image_blurred, detectorResults); +#endif + } + + + } + + return true; + } + + void detect_all(const Mat& img, const Mat& imgBlurred, std::vector& res, std::vector < std::vector < tld::TLDDetector::LabeledPatch > > &patches, std::vector &detect_flgs, + std::vector > &trackers) + { + //TLD Tracker data extraction + Tracker* trackerPtr = trackers[0]; + cv::tld::TrackerTLDImpl* tracker = static_cast(trackerPtr); + //TLD Model Extraction + tld::TrackerTLDModel* tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + Size initSize = tldModel->getMinSize(); + + for (int k = 0; k < (int)trackers.size(); k++) + patches[k].clear(); + + Mat_ standardPatch(tld::STANDARD_PATCH_SIZE, tld::STANDARD_PATCH_SIZE); + Mat tmp; + int dx = initSize.width / 10, dy = initSize.height / 10; + Size2d size = img.size(); + double scale = 1.0; + int npos = 0, nneg = 0; + double maxSc = -5.0; + Rect2d maxScRect; + int scaleID; + std::vector resized_imgs, blurred_imgs; + + std::vector > varBuffer(trackers.size()), ensBuffer(trackers.size()); + std::vector > varScaleIDs(trackers.size()), ensScaleIDs(trackers.size()); + + std::vector tmpP; + std::vector tmpI; + + //Detection part + //Generate windows and filter by variance + scaleID = 0; + resized_imgs.push_back(img); + blurred_imgs.push_back(imgBlurred); + do + { + Mat_ intImgP, intImgP2; + tld::TLDDetector::computeIntegralImages(resized_imgs[scaleID], intImgP, intImgP2); + for (int i = 0, imax = cvFloor((0.0 + resized_imgs[scaleID].cols - initSize.width) / dx); i < imax; i++) + { + for (int j = 0, jmax = cvFloor((0.0 + resized_imgs[scaleID].rows - initSize.height) / dy); j < jmax; j++) + { + //Optimized variance calculation + int x = dx * i, + y = dy * j, + width = initSize.width, + height = initSize.height; + double p = 0, p2 = 0; + double A, B, C, D; + + A = intImgP(y, x); + B = intImgP(y, x + width); + C = intImgP(y + height, x); + D = intImgP(y + height, x + width); + p = (A + D - B - C) / (width * height); + + A = intImgP2(y, x); + B = intImgP2(y, x + width); + C = intImgP2(y + height, x); + D = intImgP2(y + height, x + width); + p2 = (A + D - B - C) / (width * height); + double windowVar = p2 - p * p; + + //Loop for on all objects + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + + //Optimized variance calculation + bool varPass = (windowVar > tld::VARIANCE_THRESHOLD * *tldModel->detector->originalVariancePtr); + + if (!varPass) + continue; + varBuffer[k].push_back(Point(dx * i, dy * j)); + varScaleIDs[k].push_back(scaleID); + } + } + } + scaleID++; + size.width /= tld::SCALE_STEP; + size.height /= tld::SCALE_STEP; + scale *= tld::SCALE_STEP; + resize(img, tmp, size, 0, 0, tld::DOWNSCALE_MODE); + resized_imgs.push_back(tmp); + GaussianBlur(resized_imgs[scaleID], tmp, tld::GaussBlurKernelSize, 0.0f); + blurred_imgs.push_back(tmp); + } while (size.width >= initSize.width && size.height >= initSize.height); + + //Encsemble classification + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + + + for (int i = 0; i < (int)varBuffer[k].size(); i++) + { + tldModel->detector->prepareClassifiers(static_cast (blurred_imgs[varScaleIDs[k][i]].step[0])); + + double ensRes = 0; + uchar* data = &blurred_imgs[varScaleIDs[k][i]].at(varBuffer[k][i].y, varBuffer[k][i].x); + for (int x = 0; x < (int)tldModel->detector->classifiers.size(); x++) + { + int position = 0; + for (int n = 0; n < (int)tldModel->detector->classifiers[x].measurements.size(); n++) + { + position = position << 1; + if (data[tldModel->detector->classifiers[x].offset[n].x] < data[tldModel->detector->classifiers[x].offset[n].y]) + position++; + } + double posNum = (double)tldModel->detector->classifiers[x].posAndNeg[position].x; + double negNum = (double)tldModel->detector->classifiers[x].posAndNeg[position].y; + if (posNum == 0.0 && negNum == 0.0) + continue; + else + ensRes += posNum / (posNum + negNum); + } + ensRes /= tldModel->detector->classifiers.size(); + ensRes = tldModel->detector->ensembleClassifierNum(&blurred_imgs[varScaleIDs[k][i]].at(varBuffer[k][i].y, varBuffer[k][i].x)); + + if ( ensRes <= tld::ENSEMBLE_THRESHOLD) + continue; + ensBuffer[k].push_back(varBuffer[k][i]); + ensScaleIDs[k].push_back(varScaleIDs[k][i]); + } + } + + //NN classification + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + + npos = 0; + nneg = 0; + maxSc = -5.0; + + for (int i = 0; i < (int)ensBuffer[k].size(); i++) + { + tld::TLDDetector::LabeledPatch labPatch; + double curScale = pow(tld::SCALE_STEP, ensScaleIDs[k][i]); + labPatch.rect = Rect2d(ensBuffer[k][i].x*curScale, ensBuffer[k][i].y*curScale, initSize.width * curScale, initSize.height * curScale); + tld::resample(resized_imgs[ensScaleIDs[k][i]], Rect2d(ensBuffer[k][i], initSize), standardPatch); + + double srValue, scValue; + srValue = tldModel->detector->Sr(standardPatch); + + ////To fix: Check the paper, probably this cause wrong learning + // + labPatch.isObject = srValue > tld::THETA_NN; + labPatch.shouldBeIntegrated = abs(srValue - tld::THETA_NN) < 0.1; + patches[k].push_back(labPatch); + // + + if (!labPatch.isObject) + { + nneg++; + continue; + } + else + { + npos++; + } + scValue = tldModel->detector->Sc(standardPatch); + if (scValue > maxSc) + { + maxSc = scValue; + maxScRect = labPatch.rect; + } + } + + + + if (maxSc < 0) + detect_flgs[k] = false; + else + { + res[k] = maxScRect; + detect_flgs[k] = true; + } + } + } + +#ifdef HAVE_OPENCL + void ocl_detect_all(const Mat& img, const Mat& imgBlurred, std::vector& res, std::vector < std::vector < tld::TLDDetector::LabeledPatch > > &patches, std::vector &detect_flgs, + std::vector > &trackers) + { + //TLD Tracker data extraction + Tracker* trackerPtr = trackers[0]; + cv::tld::TrackerTLDImpl* tracker = static_cast(trackerPtr); + //TLD Model Extraction + tld::TrackerTLDModel* tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + Size initSize = tldModel->getMinSize(); + + for (int k = 0; k < (int)trackers.size(); k++) + patches[k].clear(); + + Mat_ standardPatch(tld::STANDARD_PATCH_SIZE, tld::STANDARD_PATCH_SIZE); + Mat tmp; + int dx = initSize.width / 10, dy = initSize.height / 10; + Size2d size = img.size(); + double scale = 1.0; + int npos = 0, nneg = 0; + double maxSc = -5.0; + Rect2d maxScRect; + int scaleID; + std::vector resized_imgs, blurred_imgs; + + std::vector > varBuffer(trackers.size()), ensBuffer(trackers.size()); + std::vector > varScaleIDs(trackers.size()), ensScaleIDs(trackers.size()); + + std::vector tmpP; + std::vector tmpI; + + //Detection part + //Generate windows and filter by variance + scaleID = 0; + resized_imgs.push_back(img); + blurred_imgs.push_back(imgBlurred); + do + { + Mat_ intImgP, intImgP2; + tld::TLDDetector::computeIntegralImages(resized_imgs[scaleID], intImgP, intImgP2); + for (int i = 0, imax = cvFloor((0.0 + resized_imgs[scaleID].cols - initSize.width) / dx); i < imax; i++) + { + for (int j = 0, jmax = cvFloor((0.0 + resized_imgs[scaleID].rows - initSize.height) / dy); j < jmax; j++) + { + //Optimized variance calculation + int x = dx * i, + y = dy * j, + width = initSize.width, + height = initSize.height; + double p = 0, p2 = 0; + double A, B, C, D; + + A = intImgP(y, x); + B = intImgP(y, x + width); + C = intImgP(y + height, x); + D = intImgP(y + height, x + width); + p = (A + D - B - C) / (width * height); + + A = intImgP2(y, x); + B = intImgP2(y, x + width); + C = intImgP2(y + height, x); + D = intImgP2(y + height, x + width); + p2 = (A + D - B - C) / (width * height); + double windowVar = p2 - p * p; + + //Loop for on all objects + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + + //Optimized variance calculation + bool varPass = (windowVar > tld::VARIANCE_THRESHOLD * *tldModel->detector->originalVariancePtr); + + if (!varPass) + continue; + varBuffer[k].push_back(Point(dx * i, dy * j)); + varScaleIDs[k].push_back(scaleID); + } + } + } + scaleID++; + size.width /= tld::SCALE_STEP; + size.height /= tld::SCALE_STEP; + scale *= tld::SCALE_STEP; + resize(img, tmp, size, 0, 0, tld::DOWNSCALE_MODE); + resized_imgs.push_back(tmp); + GaussianBlur(resized_imgs[scaleID], tmp, tld::GaussBlurKernelSize, 0.0f); + blurred_imgs.push_back(tmp); + } while (size.width >= initSize.width && size.height >= initSize.height); + + //Encsemble classification + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + + + for (int i = 0; i < (int)varBuffer[k].size(); i++) + { + tldModel->detector->prepareClassifiers(static_cast (blurred_imgs[varScaleIDs[k][i]].step[0])); + + double ensRes = 0; + uchar* data = &blurred_imgs[varScaleIDs[k][i]].at(varBuffer[k][i].y, varBuffer[k][i].x); + for (int x = 0; x < (int)tldModel->detector->classifiers.size(); x++) + { + int position = 0; + for (int n = 0; n < (int)tldModel->detector->classifiers[x].measurements.size(); n++) + { + position = position << 1; + if (data[tldModel->detector->classifiers[x].offset[n].x] < data[tldModel->detector->classifiers[x].offset[n].y]) + position++; + } + double posNum = (double)tldModel->detector->classifiers[x].posAndNeg[position].x; + double negNum = (double)tldModel->detector->classifiers[x].posAndNeg[position].y; + if (posNum == 0.0 && negNum == 0.0) + continue; + else + ensRes += posNum / (posNum + negNum); + } + ensRes /= tldModel->detector->classifiers.size(); + ensRes = tldModel->detector->ensembleClassifierNum(&blurred_imgs[varScaleIDs[k][i]].at(varBuffer[k][i].y, varBuffer[k][i].x)); + + if (ensRes <= tld::ENSEMBLE_THRESHOLD) + continue; + ensBuffer[k].push_back(varBuffer[k][i]); + ensScaleIDs[k].push_back(varScaleIDs[k][i]); + } + } + + //NN classification + for (int k = 0; k < (int)trackers.size(); k++) + { + //TLD Tracker data extraction + trackerPtr = trackers[k]; + tracker = static_cast(trackerPtr); + //TLD Model Extraction + tldModel = ((tld::TrackerTLDModel*)static_cast(tracker->getModel())); + npos = 0; + nneg = 0; + maxSc = -5.0; + + //Prepare batch of patches + int numOfPatches = (int)ensBuffer[k].size(); + Mat_ stdPatches(numOfPatches, 225); + double *resultSr = new double[numOfPatches]; + double *resultSc = new double[numOfPatches]; + + uchar *patchesData = stdPatches.data; + for (int i = 0; i < (int)ensBuffer.size(); i++) + { + tld::resample(resized_imgs[ensScaleIDs[k][i]], Rect2d(ensBuffer[k][i], initSize), standardPatch); + uchar *stdPatchData = standardPatch.data; + for (int j = 0; j < 225; j++) + patchesData[225 * i + j] = stdPatchData[j]; + } + //Calculate Sr and Sc batches + tldModel->detector->ocl_batchSrSc(stdPatches, resultSr, resultSc, numOfPatches); + + for (int i = 0; i < (int)ensBuffer[k].size(); i++) + { + tld::TLDDetector::LabeledPatch labPatch; + standardPatch.data = &stdPatches.data[225 * i]; + double curScale = pow(tld::SCALE_STEP, ensScaleIDs[k][i]); + labPatch.rect = Rect2d(ensBuffer[k][i].x*curScale, ensBuffer[k][i].y*curScale, initSize.width * curScale, initSize.height * curScale); + tld::resample(resized_imgs[ensScaleIDs[k][i]], Rect2d(ensBuffer[k][i], initSize), standardPatch); + + double srValue, scValue; + srValue = resultSr[i]; + + ////To fix: Check the paper, probably this cause wrong learning + // + labPatch.isObject = srValue > tld::THETA_NN; + labPatch.shouldBeIntegrated = abs(srValue - tld::THETA_NN) < 0.1; + patches[k].push_back(labPatch); + // + + if (!labPatch.isObject) + { + nneg++; + continue; + } + else + { + npos++; + } + scValue = resultSc[i]; + if (scValue > maxSc) + { + maxSc = scValue; + maxScRect = labPatch.rect; + } + } + + + + if (maxSc < 0) + detect_flgs[k] = false; + else + { + res[k] = maxScRect; + detect_flgs[k] = true; + } + } + } +#endif + +} \ No newline at end of file diff --git a/modules/tracking/src/multiTracker.hpp b/modules/tracking/src/multiTracker.hpp new file mode 100644 index 000000000..4ab654e9b --- /dev/null +++ b/modules/tracking/src/multiTracker.hpp @@ -0,0 +1,59 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2013, OpenCV Foundation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's 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. +// +// * The name of the copyright holders may not 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 Intel Corporation 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. +// +//M*/ + +#ifndef OPENCV_MULTITRACKER +#define OPENCV_MULTITRACKER + +#include "precomp.hpp" +#include "tldTracker.hpp" +#include "tldUtils.hpp" +#include + +namespace cv +{ + void detect_all(const Mat& img, const Mat& imgBlurred, std::vector& res, std::vector < std::vector < tld::TLDDetector::LabeledPatch > > &patches, + std::vector& detect_flgs, std::vector >& trackers); +#ifdef HAVE_OPENCL + void ocl_detect_all(const Mat& img, const Mat& imgBlurred, std::vector& res, std::vector < std::vector < tld::TLDDetector::LabeledPatch > > &patches, + std::vector& detect_flgs, std::vector >& trackers); +#endif +} +#endif \ No newline at end of file diff --git a/modules/tracking/src/multiTracker_alt.cpp b/modules/tracking/src/multiTracker_alt.cpp new file mode 100644 index 000000000..99722a7c7 --- /dev/null +++ b/modules/tracking/src/multiTracker_alt.cpp @@ -0,0 +1,120 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2013, OpenCV Foundation, all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's 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. + // + // * The name of the copyright holders may not 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 Intel Corporation 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. + // + //M*/ + +#include "precomp.hpp" + +namespace cv { + + // constructor + MultiTracker::MultiTracker(const String& trackerType):defaultAlgorithm(trackerType){}; + + // destructor + MultiTracker::~MultiTracker(){}; + + // add an object to be tracked, defaultAlgorithm is used + bool MultiTracker::add(const Mat& image, const Rect2d& boundingBox){ + // quit if defaultAlgorithm has not been configured + if(defaultAlgorithm==""){ + printf("Default algorithm was not defined!\n"); + return false; + } + + // add a new tracked object + return add(defaultAlgorithm.c_str(), image, boundingBox); + }; + + // add a new tracked object + bool MultiTracker::add( const String& trackerType, const Mat& image, const Rect2d& boundingBox ){ + // declare a new tracker + Ptr newTracker = Tracker::create( trackerType ); + + // add the created tracker algorithm to the trackers list + trackerList.push_back(newTracker); + + // add the ROI to the bounding box list + objects.push_back(boundingBox); + + // initialize the created tracker + return trackerList.back()->init(image, boundingBox); + }; + + // add a set of objects to be tracked + bool MultiTracker::add(const String& trackerType, const Mat& image, std::vector boundingBox){ + // status of the tracker addition + bool stat=false; + + // add tracker for all input objects + for(unsigned i =0;i boundingBox){ + // quit if defaultAlgorithm has not been configured + if(defaultAlgorithm==""){ + printf("Default algorithm was not defined!\n"); + return false; + } + + return add(defaultAlgorithm.c_str(), image, boundingBox); + }; + + // update position of the tracked objects, the result is stored in internal storage + bool MultiTracker::update( const Mat& image){ + for(unsigned i=0;i< trackerList.size(); i++){ + trackerList[i]->update(image, objects[i]); + } + return true; + }; + + // update position of the tracked objects, the result is copied to external variable + bool MultiTracker::update( const Mat& image, std::vector & boundingBox ){ + update(image); + boundingBox=objects; + return true; + }; + +} /* namespace cv */ \ No newline at end of file diff --git a/modules/tracking/src/tldDataset.cpp b/modules/tracking/src/tldDataset.cpp index b93de2576..9ddbeed25 100644 --- a/modules/tracking/src/tldDataset.cpp +++ b/modules/tracking/src/tldDataset.cpp @@ -48,70 +48,108 @@ namespace cv char tldRootPath[100]; int frameNum = 0; bool flagPNG = false; + bool flagVOT = false; - cv::Rect2d tld_InitDataset(int datasetInd,const char* rootPath) + //TLD Dataset Parameters + const char* tldFolderName[10] = { + "01_david", + "02_jumping", + "03_pedestrian1", + "04_pedestrian2", + "05_pedestrian3", + "06_car", + "07_motocross", + "08_volkswagen", + "09_carchase", + "10_panda" + }; + const char* votFolderName[60] = { + "bag", "ball1", "ball2", "basketball", "birds1", "birds2", "blanket", "bmx", "bolt1", "bolt2", + "book", "butterfly", "car1", "car2", "crossing", "dinosaur", "fernando", "fish1", "fish2", "fish3", + "fish4", "girl", "glove", "godfather", "graduate", "gymnastics1", "gymnastics2 ", "gymnastics3", "gymnastics4", "hand", + "handball1", "handball2", "helicopter", "iceskater1", "iceskater2", "leaves", "marching", "matrix", "motocross1", "motocross2", + "nature", "octopus", "pedestrian1", "pedestrian2", "rabbit", "racing", "road", "shaking", "sheep", "singer1", + "singer2", "singer3", "soccer1", "soccer2", "soldier", "sphere", "tiger", "traffic", "tunnel", "wiper" + }; + + const Rect2d tldInitBB[10] = { + Rect2d(165, 93, 51, 54), Rect2d(147, 110, 33, 32), Rect2d(47, 51, 21, 36), Rect2d(130, 134, 21, 53), Rect2d(154, 102, 24, 52), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(337, 219, 54, 37), Rect2d(58, 100, 27, 22) + }; + const Rect2d votInitBB[60] = { + Rect2d(142, 125, 90, 39), Rect2d(490, 400, 40, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + Rect2d(450, 380, 60, 60), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(225, 175, 50, 50), Rect2d(58, 100, 27, 22), + + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(560, 460, 50, 120), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + Rect2d(142, 125, 90, 39), Rect2d(290, 43, 23, 40), Rect2d(273, 77, 27, 25), Rect2d(145, 84, 54, 37), Rect2d(58, 100, 27, 22), + }; + + int tldFrameOffset[10] = { 100, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + int votFrameOffset[60] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + bool tldFlagPNG[10] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }; + bool votFlagPNG[60] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + cv::Rect2d tld_InitDataset(int videoInd, const char* rootPath, int datasetInd) { char* folderName = (char *)""; - int x = 0; - int y = 0; - int w = 0; - int h = 0; - flagPNG = false; - - frameNum = 1; - - if (datasetInd == 1) { - folderName = (char *)"01_david"; - x = 165, y = 83; - w = 51; h = 54; - frameNum = 100; - } - if (datasetInd == 2) { - folderName = (char *)"02_jumping"; - x = 147, y = 110; - w = 33; h = 32; - } - if (datasetInd == 3) { - folderName = (char *)"03_pedestrian1"; - x = 47, y = 51; - w = 21; h = 36; - } - if (datasetInd == 4) { - folderName = (char *)"04_pedestrian2"; - x = 130, y = 134; - w = 21; h = 53; - } - if (datasetInd == 5) { - folderName = (char *)"05_pedestrian3"; - x = 154, y = 102; - w = 24; h = 52; - } - if (datasetInd == 6) { - folderName = (char *)"06_car"; - x = 142, y = 125; - w = 90; h = 39; - } - if (datasetInd == 7) { - folderName = (char *)"07_motocross"; - x = 290, y = 43; - w = 23; h = 40; - flagPNG = true; - } - if (datasetInd == 8) { - folderName = (char *)"08_volkswagen"; - x = 273, y = 77; - w = 27; h = 25; - } - if (datasetInd == 9) { - folderName = (char *)"09_carchase"; - x = 145, y = 84; - w = 54; h = 37; - } - if (datasetInd == 10){ - folderName = (char *)"10_panda"; - x = 58, y = 100; - w = 27; h = 22; + double x = 0, + y = 0, + w = 0, + h = 0; + + //Index range + // 1-10 TLD Dataset + // 1-60 VOT 2015 Dataset + int id = videoInd - 1; + + if (datasetInd == 0) + { + folderName = (char*)tldFolderName[id]; + x = tldInitBB[id].x; + y = tldInitBB[id].y; + w = tldInitBB[id].width; + h = tldInitBB[id].height; + frameNum = tldFrameOffset[id]; + flagPNG = tldFlagPNG[id]; + flagVOT = false; } + if (datasetInd == 1) + { + folderName = (char*)votFolderName[id]; + x = votInitBB[id].x; + y = votInitBB[id].y; + w = votInitBB[id].width; + h = votInitBB[id].height; + frameNum = votFrameOffset[id]; + flagPNG = votFlagPNG[id]; + flagVOT = true; + } strcpy(tldRootPath, rootPath); strcat(tldRootPath, "\\"); @@ -127,6 +165,8 @@ namespace cv char numStr[10]; strcpy(fullPath, tldRootPath); strcat(fullPath, "\\"); + if (flagVOT) + strcat(fullPath, "000"); if (frameNum < 10) strcat(fullPath, "0000"); else if (frameNum < 100) strcat(fullPath, "000"); else if (frameNum < 1000) strcat(fullPath, "00"); diff --git a/modules/tracking/src/tldDetector.cpp b/modules/tracking/src/tldDetector.cpp index cbb783ece..7136e70fa 100644 --- a/modules/tracking/src/tldDetector.cpp +++ b/modules/tracking/src/tldDetector.cpp @@ -65,25 +65,6 @@ namespace cv // Calculate Relative similarity of the patch (NN-Model) double TLDDetector::Sr(const Mat_& patch) { - /* - int64 e1, e2; - float t; - e1 = getTickCount(); - double splus = 0.0, sminus = 0.0; - for (int i = 0; i < (int)(*positiveExamples).size(); i++) - splus = std::max(splus, 0.5 * (NCC((*positiveExamples)[i], patch) + 1.0)); - for (int i = 0; i < (int)(*negativeExamples).size(); i++) - sminus = std::max(sminus, 0.5 * (NCC((*negativeExamples)[i], patch) + 1.0)); - e2 = getTickCount(); - t = (e2 - e1) / getTickFrequency()*1000.0; - printf("Sr: %f\n", t); - if (splus + sminus == 0.0) - return 0.0; - return splus / (sminus + splus); - */ - //int64 e1, e2; - //float t; - //e1 = getTickCount(); double splus = 0.0, sminus = 0.0; Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); for (int i = 0; i < *posNum; i++) @@ -96,20 +77,15 @@ namespace cv modelSample.data = &(negExp->data[i * 225]); sminus = std::max(sminus, 0.5 * (NCC(modelSample, patch) + 1.0)); } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Sr CPU: %f\n", t); + if (splus + sminus == 0.0) return 0.0; return splus / (sminus + splus); } +#ifdef HAVE_OPENCL double TLDDetector::ocl_Sr(const Mat_& patch) { - //int64 e1, e2, e3, e4; - //double t; - //e1 = getTickCount(); - //e3 = getTickCount(); double splus = 0.0, sminus = 0.0; @@ -122,7 +98,7 @@ namespace cv ocl::Kernel k; ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; String error; - ocl::Program prog(src, NULL, error); + ocl::Program prog(src, String(), error); k.create("NCC", prog); if (k.empty()) printf("Kernel create failed!!!\n"); @@ -131,41 +107,15 @@ namespace cv ocl::KernelArg::PtrReadOnly(devPositiveSamples), ocl::KernelArg::PtrReadOnly(devNegativeSamples), ocl::KernelArg::PtrWriteOnly(devNCC), - posNum, - negNum); - - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Mem Cpy GPU: %f\n", t); + *posNum, + *negNum); size_t globSize = 1000; - //e3 = getTickCount(); + if (!k.run(1, &globSize, NULL, false)) printf("Kernel Run Error!!!"); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Kernel Run GPU: %f\n", t); - //e3 = getTickCount(); Mat resNCC = devNCC.getMat(ACCESS_READ); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Read Mem GPU: %f\n", t); - - ////Compare - //Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); - //for (int i = 0; i < 200; i+=17) - //{ - // modelSample.data = &(posExp->data[i * 225]); - // printf("%f\t%f\n\n", resNCC.at(i), NCC(modelSample, patch)); - //} - - //for (int i = 0; i < 200; i+=23) - //{ - // modelSample.data = &(negExp->data[i * 225]); - // printf("%f\t%f\n", resNCC.at(500+i), NCC(modelSample, patch)); - //} - for (int i = 0; i < *posNum; i++) splus = std::max(splus, 0.5 * (resNCC.at(i) + 1.0)); @@ -173,10 +123,6 @@ namespace cv for (int i = 0; i < *negNum; i++) sminus = std::max(sminus, 0.5 * (resNCC.at(i+500) +1.0)); - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Sr GPU: %f\n\n", t); - if (splus + sminus == 0.0) return 0.0; return splus / (sminus + splus); @@ -184,11 +130,6 @@ namespace cv void TLDDetector::ocl_batchSrSc(const Mat_& patches, double *resultSr, double *resultSc, int numOfPatches) { - //int64 e1, e2, e3, e4; - //double t; - //e1 = getTickCount(); - //e3 = getTickCount(); - UMat devPatches = patches.getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); UMat devPositiveSamples = posExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); UMat devNegativeSamples = negExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); @@ -198,7 +139,7 @@ namespace cv ocl::Kernel k; ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; String error; - ocl::Program prog(src, NULL, error); + ocl::Program prog(src, String(), error); k.create("batchNCC", prog); if (k.empty()) printf("Kernel create failed!!!\n"); @@ -208,29 +149,17 @@ namespace cv ocl::KernelArg::PtrReadOnly(devNegativeSamples), ocl::KernelArg::PtrWriteOnly(devPosNCC), ocl::KernelArg::PtrWriteOnly(devNegNCC), - posNum, - negNum, + *posNum, + *negNum, numOfPatches); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Mem Cpy GPU: %f\n", t); - - // 2 -> Pos&Neg size_t globSize = 2 * numOfPatches*MAX_EXAMPLES_IN_MODEL; - //e3 = getTickCount(); - if (!k.run(1, &globSize, NULL, false)) + + if (!k.run(1, &globSize, NULL, true)) printf("Kernel Run Error!!!"); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Kernel Run GPU: %f\n", t); - //e3 = getTickCount(); Mat posNCC = devPosNCC.getMat(ACCESS_READ); Mat negNCC = devNegNCC.getMat(ACCESS_READ); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Read Mem GPU: %f\n", t); //Calculate Srs for (int id = 0; id < numOfPatches; id++) @@ -256,62 +185,12 @@ namespace cv else resultSc[id] = spc / (smc + spc); } - - ////Compare positive NCCs - /*Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); - Mat_ patch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); - for (int j = 0; j < numOfPatches; j++) - { - for (int i = 0; i < 1; i++) - { - modelSample.data = &(posExp->data[i * 225]); - patch.data = &(patches.data[j * 225]); - printf("%f\t%f\n", resultSr[j], Sr(patch)); - printf("%f\t%f\n", resultSc[j], Sc(patch)); - } - }*/ - - //for (int i = 0; i < 200; i+=23) - //{ - // modelSample.data = &(negExp->data[i * 225]); - // printf("%f\t%f\n", resNCC.at(500+i), NCC(modelSample, patch)); - //} - - - - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Sr GPU: %f\n\n", t); } +#endif // Calculate Conservative similarity of the patch (NN-Model) double TLDDetector::Sc(const Mat_& patch) { - /* - int64 e1, e2; - float t; - e1 = getTickCount(); - double splus = 0.0, sminus = 0.0; - int med = getMedian((*timeStampsPositive)); - for (int i = 0; i < (int)(*positiveExamples).size(); i++) - { - if ((int)(*timeStampsPositive)[i] <= med) - splus = std::max(splus, 0.5 * (NCC((*positiveExamples)[i], patch) + 1.0)); - } - for (int i = 0; i < (int)(*negativeExamples).size(); i++) - sminus = std::max(sminus, 0.5 * (NCC((*negativeExamples)[i], patch) + 1.0)); - e2 = getTickCount(); - t = (e2 - e1) / getTickFrequency()*1000.0; - printf("Sc: %f\n", t); - if (splus + sminus == 0.0) - return 0.0; - - return splus / (sminus + splus); - */ - - //int64 e1, e2; - //double t; - //e1 = getTickCount(); double splus = 0.0, sminus = 0.0; Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); int med = getMedian((*timeStampsPositive)); @@ -328,24 +207,18 @@ namespace cv modelSample.data = &(negExp->data[i * 225]); sminus = std::max(sminus, 0.5 * (NCC(modelSample, patch) + 1.0)); } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Sc: %f\n", t); + if (splus + sminus == 0.0) return 0.0; return splus / (sminus + splus); } +#ifdef HAVE_OPENCL double TLDDetector::ocl_Sc(const Mat_& patch) { - //int64 e1, e2, e3, e4; - //float t; - //e1 = getTickCount(); double splus = 0.0, sminus = 0.0; - //e3 = getTickCount(); - UMat devPatch = patch.getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); UMat devPositiveSamples = posExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); UMat devNegativeSamples = negExp->getUMat(ACCESS_READ, USAGE_ALLOCATE_DEVICE_MEMORY); @@ -355,7 +228,7 @@ namespace cv ocl::Kernel k; ocl::ProgramSource src = ocl::tracking::tldDetector_oclsrc; String error; - ocl::Program prog(src, NULL, error); + ocl::Program prog(src, String(), error); k.create("NCC", prog); if (k.empty()) printf("Kernel create failed!!!\n"); @@ -364,40 +237,15 @@ namespace cv ocl::KernelArg::PtrReadOnly(devPositiveSamples), ocl::KernelArg::PtrReadOnly(devNegativeSamples), ocl::KernelArg::PtrWriteOnly(devNCC), - posNum, - negNum); - - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Mem Cpy GPU: %f\n", t); + *posNum, + *negNum); size_t globSize = 1000; - //e3 = getTickCount(); + if (!k.run(1, &globSize, NULL, false)) printf("Kernel Run Error!!!"); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Kernel Run GPU: %f\n", t); - //e3 = getTickCount(); Mat resNCC = devNCC.getMat(ACCESS_READ); - //e4 = getTickCount(); - //t = (e4 - e3) / getTickFrequency()*1000.0; - //printf("Read Mem GPU: %f\n", t); - - ////Compare - //Mat_ modelSample(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); - //for (int i = 0; i < 200; i+=17) - //{ - // modelSample.data = &(posExp->data[i * 225]); - // printf("%f\t%f\n\n", resNCC.at(i), NCC(modelSample, patch)); - //} - - //for (int i = 0; i < 200; i+=23) - //{ - // modelSample.data = &(negExp->data[i * 225]); - // printf("%f\t%f\n", resNCC.at(500+i), NCC(modelSample, patch)); - //} int med = getMedian((*timeStampsPositive)); for (int i = 0; i < *posNum; i++) @@ -407,14 +255,11 @@ namespace cv for (int i = 0; i < *negNum; i++) sminus = std::max(sminus, 0.5 * (resNCC.at(i + 500) + 1.0)); - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Sc GPU: %f\n\n", t); - if (splus + sminus == 0.0) return 0.0; return splus / (sminus + splus); } +#endif // HAVE_OPENCL // Generate Search Windows for detector from aspect ratio of initial BBs void TLDDetector::generateScanGrid(int rows, int cols, Size initBox, std::vector& res, bool withScaling) @@ -449,7 +294,6 @@ namespace cv break; } } - //dprintf(("%d rects in res\n", (int)res.size())); } //Detection - returns most probable new target location (Max Sc) @@ -469,10 +313,6 @@ namespace cv std::vector resized_imgs, blurred_imgs; std::vector varBuffer, ensBuffer; std::vector varScaleIDs, ensScaleIDs; - //int64 e1, e2; - //double t; - - //e1 = getTickCount(); //Detection part //Generate windows and filter by variance @@ -502,12 +342,8 @@ namespace cv GaussianBlur(resized_imgs[scaleID], tmp, GaussBlurKernelSize, 0.0f); blurred_imgs.push_back(tmp); } while (size.width >= initSize.width && size.height >= initSize.height); - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Variance: %d\t%f\n", varBuffer.size(), t); //Encsemble classification - //e1 = getTickCount(); for (int i = 0; i < (int)varBuffer.size(); i++) { prepareClassifiers(static_cast (blurred_imgs[varScaleIDs[i]].step[0])); @@ -516,12 +352,8 @@ namespace cv ensBuffer.push_back(varBuffer[i]); ensScaleIDs.push_back(varScaleIDs[i]); } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Ensemble: %d\t%f\n", ensBuffer.size(), t); //NN classification - //e1 = getTickCount(); for (int i = 0; i < (int)ensBuffer.size(); i++) { LabeledPatch labPatch; @@ -555,16 +387,17 @@ namespace cv maxScRect = labPatch.rect; } } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("NN: %d\t%f\n", patches.size(), t); if (maxSc < 0) return false; - res = maxScRect; - return true; + else + { + res = maxScRect; + return true; + } } +#ifdef HAVE_OPENCL bool TLDDetector::ocl_detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector& patches, Size initSize) { patches.clear(); @@ -580,10 +413,7 @@ namespace cv std::vector resized_imgs, blurred_imgs; std::vector varBuffer, ensBuffer; std::vector varScaleIDs, ensScaleIDs; - //int64 e1, e2; - //double t; - //e1 = getTickCount(); //Detection part //Generate windows and filter by variance scaleID = 0; @@ -612,12 +442,8 @@ namespace cv GaussianBlur(resized_imgs[scaleID], tmp, GaussBlurKernelSize, 0.0f); blurred_imgs.push_back(tmp); } while (size.width >= initSize.width && size.height >= initSize.height); - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Variance: %d\t%f\n", varBuffer.size(), t); //Encsemble classification - //e1 = getTickCount(); for (int i = 0; i < (int)varBuffer.size(); i++) { prepareClassifiers((int)blurred_imgs[varScaleIDs[i]].step[0]); @@ -626,12 +452,8 @@ namespace cv ensBuffer.push_back(varBuffer[i]); ensScaleIDs.push_back(varScaleIDs[i]); } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("Ensemble: %d\t%f\n", ensBuffer.size(), t); //NN classification - //e1 = getTickCount(); //Prepare batch of patches int numOfPatches = (int)ensBuffer.size(); Mat_ stdPatches(numOfPatches, 225); @@ -661,9 +483,6 @@ namespace cv srValue = resultSr[i]; - //srValue = Sr(standardPatch); - //printf("%f\t%f\t\n", srValue, resultSr[i]); - ////To fix: Check the paper, probably this cause wrong learning // labPatch.isObject = srValue > THETA_NN; @@ -687,15 +506,13 @@ namespace cv maxScRect = labPatch.rect; } } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency()*1000.0; - //printf("NN: %d\t%f\n", patches.size(), t); if (maxSc < 0) return false; res = maxScRect; return true; } +#endif // HAVE_OPENCL // Computes the variance of subimage given by box, with the help of two integral // images intImgP and intImgP2 (sum of squares), which should be also provided. diff --git a/modules/tracking/src/tldDetector.hpp b/modules/tracking/src/tldDetector.hpp index 3e1189592..742125696 100644 --- a/modules/tracking/src/tldDetector.hpp +++ b/modules/tracking/src/tldDetector.hpp @@ -66,18 +66,22 @@ namespace cv static const cv::Size GaussBlurKernelSize(3, 3); + + class TLDDetector { public: TLDDetector(){} ~TLDDetector(){} - inline double ensembleClassifierNum(const uchar* data); - inline void prepareClassifiers(int rowstep); + double ensembleClassifierNum(const uchar* data); + void prepareClassifiers(int rowstep); double Sr(const Mat_& patch); - double ocl_Sr(const Mat_& patch); double Sc(const Mat_& patch); +#ifdef HAVE_OPENCL + double ocl_Sr(const Mat_& patch); double ocl_Sc(const Mat_& patch); void ocl_batchSrSc(const Mat_& patches, double *resultSr, double *resultSc, int numOfPatches); +#endif std::vector classifiers; Mat *posExp, *negExp; @@ -93,15 +97,14 @@ namespace cv bool isObject, shouldBeIntegrated; }; bool detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector& patches, Size initSize); - bool ocl_detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector& patches, Size initSize); - protected: - - + bool ocl_detect(const Mat& img, const Mat& imgBlurred, Rect2d& res, std::vector& patches, Size initSize); friend class MyMouseCallbackDEBUG; - void computeIntegralImages(const Mat& img, Mat_& intImgP, Mat_& intImgP2){ integral(img, intImgP, intImgP2, CV_64F); } - inline bool patchVariance(Mat_& intImgP, Mat_& intImgP2, double *originalVariance, Point pt, Size size); + static void computeIntegralImages(const Mat& img, Mat_& intImgP, Mat_& intImgP2){ integral(img, intImgP, intImgP2, CV_64F); } + static inline bool patchVariance(Mat_& intImgP, Mat_& intImgP2, double *originalVariance, Point pt, Size size); }; + + } } diff --git a/modules/tracking/src/tldEnsembleClassifier.hpp b/modules/tracking/src/tldEnsembleClassifier.hpp index 97221372d..f0ec175ba 100644 --- a/modules/tracking/src/tldEnsembleClassifier.hpp +++ b/modules/tracking/src/tldEnsembleClassifier.hpp @@ -54,7 +54,7 @@ namespace cv double posteriorProbability(const uchar* data, int rowstep) const; double posteriorProbabilityFast(const uchar* data) const; void prepareClassifier(int rowstep); - private: + TLDEnsembleClassifier(const std::vector& meas, int beg, int end); static void stepPrefSuff(std::vector & arr, int pos, int len, int gridSize); int code(const uchar* data, int rowstep) const; diff --git a/modules/tracking/src/tldModel.cpp b/modules/tracking/src/tldModel.cpp index 085402265..03d922e50 100644 --- a/modules/tracking/src/tldModel.cpp +++ b/modules/tracking/src/tldModel.cpp @@ -140,7 +140,6 @@ namespace cv detector->classifiers[k].integrate(blurredPatch, false); } } - //dprintf(("positive patches: %d\nnegative patches: %d\n", (int)positiveExamples.size(), (int)negativeExamples.size())); } @@ -180,16 +179,6 @@ namespace cv detector->classifiers[i].integrate(blurredPatch, patches[k].isObject); } } - /* - if( negativeIntoModel > 0 ) - dfprintf((stdout, "negativeIntoModel = %d ", negativeIntoModel)); - if( positiveIntoModel > 0) - dfprintf((stdout, "positiveIntoModel = %d ", positiveIntoModel)); - if( negativeIntoEnsemble > 0 ) - dfprintf((stdout, "negativeIntoEnsemble = %d ", negativeIntoEnsemble)); - if( positiveIntoEnsemble > 0 ) - dfprintf((stdout, "positiveIntoEnsemble = %d ", positiveIntoEnsemble)); - dfprintf((stdout, "\n"));*/ } @@ -198,9 +187,6 @@ namespace cv int positiveIntoModel = 0, negativeIntoModel = 0, positiveIntoEnsemble = 0, negativeIntoEnsemble = 0; if ((int)eForModel.size() == 0) return; - //int64 e1, e2; - //double t; - //e1 = getTickCount(); for (int k = 0; k < (int)eForModel.size(); k++) { double sr = detector->Sr(eForModel[k]); @@ -231,30 +217,14 @@ namespace cv detector->classifiers[i].integrate(eForEnsemble[k], isPositive); } } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency() * 1000; - //printf("Integrate Additional: %fms\n", t); - /* - if( negativeIntoModel > 0 ) - dfprintf((stdout, "negativeIntoModel = %d ", negativeIntoModel)); - if( positiveIntoModel > 0 ) - dfprintf((stdout, "positiveIntoModel = %d ", positiveIntoModel)); - if( negativeIntoEnsemble > 0 ) - dfprintf((stdout, "negativeIntoEnsemble = %d ", negativeIntoEnsemble)); - if( positiveIntoEnsemble > 0 ) - dfprintf((stdout, "positiveIntoEnsemble = %d ", positiveIntoEnsemble)); - dfprintf((stdout, "\n"));*/ } +#ifdef HAVE_OPENCL void TrackerTLDModel::ocl_integrateAdditional(const std::vector >& eForModel, const std::vector >& eForEnsemble, bool isPositive) { int positiveIntoModel = 0, negativeIntoModel = 0, positiveIntoEnsemble = 0, negativeIntoEnsemble = 0; if ((int)eForModel.size() == 0) return; - //int64 e1, e2; - //double t; - //e1 = getTickCount(); - //Prepare batch of patches int numOfPatches = (int)eForModel.size(); Mat_ stdPatches(numOfPatches, 225); @@ -301,20 +271,8 @@ namespace cv detector->classifiers[i].integrate(eForEnsemble[k], isPositive); } } - //e2 = getTickCount(); - //t = (e2 - e1) / getTickFrequency() * 1000; - //printf("Integrate Additional OCL: %fms\n", t); - /* - if( negativeIntoModel > 0 ) - dfprintf((stdout, "negativeIntoModel = %d ", negativeIntoModel)); - if( positiveIntoModel > 0 ) - dfprintf((stdout, "positiveIntoModel = %d ", positiveIntoModel)); - if( negativeIntoEnsemble > 0 ) - dfprintf((stdout, "negativeIntoEnsemble = %d ", negativeIntoEnsemble)); - if( positiveIntoEnsemble > 0 ) - dfprintf((stdout, "positiveIntoEnsemble = %d ", positiveIntoEnsemble)); - dfprintf((stdout, "\n"));*/ } +#endif // HAVE_OPENCL //Push the patch to the model void TrackerTLDModel::pushIntoModel(const Mat_& example, bool positive) diff --git a/modules/tracking/src/tldModel.hpp b/modules/tracking/src/tldModel.hpp index be9141a54..ba7c9269f 100644 --- a/modules/tracking/src/tldModel.hpp +++ b/modules/tracking/src/tldModel.hpp @@ -58,7 +58,9 @@ namespace cv void setBoudingBox(Rect2d boundingBox){ boundingBox_ = boundingBox; } void integrateRelabeled(Mat& img, Mat& imgBlurred, const std::vector& patches); void integrateAdditional(const std::vector >& eForModel, const std::vector >& eForEnsemble, bool isPositive); +#ifdef HAVE_OPENCL void ocl_integrateAdditional(const std::vector >& eForModel, const std::vector >& eForEnsemble, bool isPositive); +#endif Size getMinSize(){ return minSize_; } void printme(FILE* port = stdout); Ptr detector; diff --git a/modules/tracking/src/tldTracker.cpp b/modules/tracking/src/tldTracker.cpp index 0f1e2f78e..51d994efc 100644 --- a/modules/tracking/src/tldTracker.cpp +++ b/modules/tracking/src/tldTracker.cpp @@ -45,6 +45,13 @@ namespace cv { + TrackerTLD::Params::Params(){} + + void TrackerTLD::Params::read(const cv::FileNode& /*fn*/){} + + void TrackerTLD::Params::write(cv::FileStorage& /*fs*/) const {} + + Ptr TrackerTLD::createTracker(const TrackerTLD::Params ¶meters) { return Ptr(new tld::TrackerTLDImpl(parameters)); @@ -112,7 +119,6 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox) Mat_ standardPatch(STANDARD_PATCH_SIZE, STANDARD_PATCH_SIZE); std::vector detectorResults; //best overlap around 92% - std::vector candidates; std::vector candidatesRes; bool trackerNeedsReInit = false; @@ -123,12 +129,13 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox) if (i == 1) { +#ifdef HAVE_OPENCL if (ocl::haveOpenCL()) DETECT_FLG = tldModel->detector->ocl_detect(imageForDetector, image_blurred, tmpCandid, detectorResults, tldModel->getMinSize()); else +#endif DETECT_FLG = tldModel->detector->detect(imageForDetector, image_blurred, tmpCandid, detectorResults, tldModel->getMinSize()); } - if( ( (i == 0) && !data->failedLastTime && trackerProxy->update(image, tmpCandid) ) || ( DETECT_FLG)) { candidates.push_back(tmpCandid); @@ -144,15 +151,8 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox) trackerNeedsReInit = true; } } - std::vector::iterator it = std::max_element(candidatesRes.begin(), candidatesRes.end()); - //dfprintf((stdout, "scale = %f\n", log(1.0 * boundingBox.width / (data->getMinSize()).width) / log(SCALE_STEP))); - //for( int i = 0; i < (int)candidatesRes.size(); i++ ) - //dprintf(("\tcandidatesRes[%d] = %f\n", i, candidatesRes[i])); - //data->printme(); - //tldModel->printme(stdout); - if( it == candidatesRes.end() ) { data->confident = false; @@ -169,16 +169,7 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox) #if 1 if( it != candidatesRes.end() ) - { resample(imageForDetector, candidates[it - candidatesRes.begin()], standardPatch); - //dfprintf((stderr, "%d %f %f\n", data->frameNum, tldModel->Sc(standardPatch), tldModel->Sr(standardPatch))); - //if( candidatesRes.size() == 2 && it == (candidatesRes.begin() + 1) ) - //dfprintf((stderr, "detector WON\n")); - } - else - { - //dfprintf((stderr, "%d x x\n", data->frameNum)); - } #endif if( *it > CORE_THRESHOLD ) @@ -209,19 +200,22 @@ bool TrackerTLDImpl::updateImpl(const Mat& image, Rect2d& boundingBox) detectorResults[i].isObject = expertResult; } tldModel->integrateRelabeled(imageForDetector, image_blurred, detectorResults); - //dprintf(("%d relabeled by nExpert\n", negRelabeled)); pExpert.additionalExamples(examplesForModel, examplesForEnsemble); - if (ocl::haveOpenCL()) - tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, true); - else - tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, true); +#ifdef HAVE_OPENCL + if (ocl::haveOpenCL()) + tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, true); + else +#endif + tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, true); examplesForModel.clear(); examplesForEnsemble.clear(); nExpert.additionalExamples(examplesForModel, examplesForEnsemble); - if (ocl::haveOpenCL()) - tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, false); - else - tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, false); +#ifdef HAVE_OPENCL + if (ocl::haveOpenCL()) + tldModel->ocl_integrateAdditional(examplesForModel, examplesForEnsemble, false); + else +#endif + tldModel->integrateAdditional(examplesForModel, examplesForEnsemble, false); } else { @@ -296,7 +290,6 @@ Data::Data(Rect2d initBox) minSize.width = (int)(initBox.width * 20.0 / minDim); minSize.height = (int)(initBox.height * 20.0 / minDim); frameNum = 0; - //dprintf(("minSize = %dx%d\n", minSize.width, minSize.height)); } void Data::printme(FILE* port) diff --git a/modules/tracking/src/tldTracker.hpp b/modules/tracking/src/tldTracker.hpp index e04926d5d..4a5610de3 100644 --- a/modules/tracking/src/tldTracker.hpp +++ b/modules/tracking/src/tldTracker.hpp @@ -52,12 +52,6 @@ namespace cv { -TrackerTLD::Params::Params(){} - -void TrackerTLD::Params::read(const cv::FileNode& /*fn*/){} - -void TrackerTLD::Params::write(cv::FileStorage& /*fs*/) const {} - namespace tld { class TrackerProxy @@ -128,7 +122,6 @@ public: void read(const FileNode& fn); void write(FileStorage& fs) const; -protected: class Pexpert { public: diff --git a/modules/tracking/tutorials/tutorial_customizing_cn_tracker.markdown b/modules/tracking/tutorials/tutorial_customizing_cn_tracker.markdown new file mode 100644 index 000000000..4d52e2d73 --- /dev/null +++ b/modules/tracking/tutorials/tutorial_customizing_cn_tracker.markdown @@ -0,0 +1,73 @@ +Customizing the CN Tracker {#tutorial_customizing_cn_tracker} +====================== + +Goal +---- + +In this tutorial you will learn how to + +- Set custom parameters for CN tracker. +- Use your own feature-extractor function for the CN tracker. + +This document contains tutorial for the @ref cv::TrackerKCF. + +Source Code +----------- + +@includelineno tracking/samples/tutorial_customizing_cn_tracker.cpp + +Explanation +----------- + +This part explains how to set custom parameters and use your own feature-extractor function for the CN tracker. +If you need a more detailed information to use @ref cv::Tracker, please refer to @ref tutorial_introduction_to_tracker. + +-# **Set Custom Parameters** + + @snippet tracking/samples/tutorial_customizing_cn_tracker.cpp param + + To set custom paramters, an object should be created. Each tracker algorithm has their own parameter format. + So, in this case we should use parameter from @ref cv::TrackerKCF since we are interested in modifying the parameter of this tracker algorithm. + + There are several parameters that can be configured as explained in @ref cv::TrackerKCF::Params. + For this tutorial, we focussed on the feature extractor functions. + + Several feature types can be used in @ref cv::TrackerKCF. + In this case, the grayscale value (1 dimension) and color-names features (10 dimension), + will be merged as 11 dimension feature and then compressed into 2 dimension as specified in the code. + + If you want to use another type of pre-defined feature-extractor function, you can check in @ref cv::TrackerKCF::MODE. + We will leave the non-compressed feature as 0 since we want to use a customized function. + +-# **Using a custom function** + + You can define your own feature-extractor function for the CN tracker. + However, you need to take care about several things: + - The extracted feature should have the same size as the size of the given bounding box (width and height). + For the number of channels you can check the limitation in @ref cv::Mat. + - You can only use features that can be compared using Euclidean distance. + Features like local binary pattern (LBP) may not be suitable since it should be compared using Hamming distance. + + Since the size of the extracted feature should be in the same size with the given bounding box, + we need to take care whenever the given bounding box is partially out of range. + In this case, we can copy part of image contained in the bounding box as shown in the snippet below. + + @snippet tracking/samples/tutorial_customizing_cn_tracker.cpp insideimage + + Whenever the copied image is smaller than the given bounding box, + padding should be given to the sides where the bounding box is partially out of frame. + + @snippet tracking/samples/tutorial_customizing_cn_tracker.cpp padding + +-# **Defining the feature** + + In this tutorial, the extracted feature is reponse of the Sobel filter in x and y direction. + Those Sobel filter responses are concatenated, resulting a feature with 2 channels. + + @snippet tracking/samples/tutorial_customizing_cn_tracker.cpp sobel + +-# **Post processing** + + Make sure to convert the feature into @ref cv::CV_64F data format and normalize its value with range -0.5 to 0.5 + + @snippet tracking/samples/tutorial_customizing_cn_tracker.cpp postprocess diff --git a/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown b/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown new file mode 100644 index 000000000..500df0c1c --- /dev/null +++ b/modules/tracking/tutorials/tutorial_introduction_to_tracker.markdown @@ -0,0 +1,75 @@ +Introduction to OpenCV Tracker {#tutorial_introduction_to_tracker} +============================== + +Goal +---- + +In this tutorial you will learn how to + +- Create a tracker object. +- Use the roiSelector function to select a ROI from a given image. +- Track a specific region in a given image. + +Source Code +----------- + +@include tracking/samples/tutorial_introduction_to_tracker.cpp + +Explanation +----------- + +-# **Set up the input video** + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp help + + In this tutorial, you can choose between video or list of images for the program input. + As written in the help, you should specify the input video as parameter of the program. + If you want to use image list as input, the image list should have formatted numbering + as shown in help. In the help, it means that the image files are numbered with 4 digits + (e.g. the file naming will be 0001.jpg, 0002.jpg, and so on). + + You can find video samples in Itseez/opencv_extra/testdata/cv/tracking + + +-# **Declares the required variables** + + You need roi to record the bounding box of the tracked object. The value stored in this + variable will be updated using the tracker object. + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp vars + + The frame variable is used to hold the image data from each frame of the input video or images list. + +-# **Creating a tracker object** + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp create + + There are at least 5 types of tracker algorithms that can be used: + + MIL + + BOOSTING + + MEDIANFLOW + + TLD + + KCF + + Each tracker algorithm has their own advantages and disadvantages, please refer the documentation of @ref cv::Tracker for more detailed information. + +-# **Select the tracked object** + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp selectroi + + Using this function, you can select the bounding box of the tracked object using a GUI. + With default parameters, the selection is started from the center of the box and a middle cross will be shown. + See @ref cv::selectROI for more detailed information. + +-# **Initializing the tracker object** + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp init + + Tracker algorithm should be initialized with the provided image data as well as the bounding box of the tracked object. + Make sure that the bounding box is not valid (size more than zero) to avoid the initialization process failed. + +-# **Update** + + @snippet tracking/samples/tutorial_introduction_to_tracker.cpp update + + This update function will perform the tracking process and pass the result to the roi variable. diff --git a/modules/tracking/tutorials/tutorial_multitracker.markdown b/modules/tracking/tutorials/tutorial_multitracker.markdown new file mode 100644 index 000000000..4bc3e3c5c --- /dev/null +++ b/modules/tracking/tutorials/tutorial_multitracker.markdown @@ -0,0 +1,49 @@ +Using MultiTracker {#tutorial_multitracker} +================== + +Goal +---- + +In this tutorial you will learn how to + +- Create a MultiTracker object. +- Track several objects at once using the MultiTracker object. + +Source Code +----------- + +@includelineno tracking/samples/tutorial_multitracker.cpp + +Explanation +----------- + +-# **Create the MultiTracker object** + + @snippet tracking/samples/tutorial_multitracker.cpp create + + You can create the MultiTracker object and use the same tracking algorithm for all tracked object as shown in the snippet. + If you want to use different type of tracking algorithm for each tracked object, you should define the tracking algorithm whenever a new object is added to the MultiTracker object. + +-# **Selection of multiple objects** + + @snippet tracking/samples/tutorial_multitracker.cpp selectmulti + + You can use @ref cv::selectROI to select multiple objects with + the result stored in a vector of @ref cv::Rect2d as shown in the code. + You can also use another kind of selection scheme, please refer to @ref cv::selectROI for detailed information. + +-# **Adding the tracked object to MultiTracker** + + @snippet tracking/samples/tutorial_multitracker.cpp init + + You can add all tracked objects at once to the MultiTracker as shown in the code. + In this case, all objects will be tracked using same tracking algorithm as specified in decaration of MultiTracker object. + If you want to use different tracker algorithms for each tracked object, + You should add the tracked objects one by one and specify their tracking algorithm using the variant of @ref cv::MultiTracker::add. + @sa cv::MultiTracker::add( const String& trackerType, const Mat& image, const Rect2d& boundingBox ) + +-# **Obtaining the result** + + @snippet tracking/samples/tutorial_multitracker.cpp result + + You can access the result from the public variable @ref cv::MultiTracker::objects provided by the MultiTracker class as shown in the code. diff --git a/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp b/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp index 6c9e2158c..a194c9662 100644 --- a/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp +++ b/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp @@ -125,7 +125,7 @@ public: class CV_EXPORTS_W BriefDescriptorExtractor : public Feature2D { public: - static Ptr create( int bytes = 32, bool use_orientation = false ); + CV_WRAP static Ptr create( int bytes = 32, bool use_orientation = false ); }; /** @brief Class implementing the locally uniform comparison image descriptor, described in @cite LUCID diff --git a/modules/xfeatures2d/src/freak.cpp b/modules/xfeatures2d/src/freak.cpp index dbb30d195..555c871a8 100644 --- a/modules/xfeatures2d/src/freak.cpp +++ b/modules/xfeatures2d/src/freak.cpp @@ -802,7 +802,8 @@ void FREAKImpl::drawPattern() FREAK_Impl::FREAK_Impl( bool _orientationNormalized, bool _scaleNormalized , float _patternScale, int _nOctaves, const std::vector& _selectedPairs ) : orientationNormalized(_orientationNormalized), scaleNormalized(_scaleNormalized), - patternScale(_patternScale), nOctaves(_nOctaves), extAll(false), nOctaves0(0), selectedPairs0(_selectedPairs) + patternScale(_patternScale), nOctaves(_nOctaves), extAll(false), + patternScale0(0.0), nOctaves0(0), selectedPairs0(_selectedPairs) { } diff --git a/modules/xfeatures2d/src/surf.cpp b/modules/xfeatures2d/src/surf.cpp index 673817e73..af5ceaf60 100644 --- a/modules/xfeatures2d/src/surf.cpp +++ b/modules/xfeatures2d/src/surf.cpp @@ -892,6 +892,7 @@ void SURF_Impl::detectAndCompute(InputArray _img, InputArray _mask, CV_Assert(!_img.empty() && CV_MAT_DEPTH(imgtype) == CV_8U && (imgcn == 1 || imgcn == 3 || imgcn == 4)); CV_Assert(_descriptors.needed() || !useProvidedKeypoints); +#ifdef HAVE_OPENCL if( ocl::useOpenCL() ) { SURF_OCL ocl_surf; @@ -918,6 +919,7 @@ void SURF_Impl::detectAndCompute(InputArray _img, InputArray _mask, return; } } +#endif // HAVE_OPENCL Mat img = _img.getMat(), mask = _mask.getMat(), mask1, sum, msum; diff --git a/modules/xfeatures2d/src/surf.hpp b/modules/xfeatures2d/src/surf.hpp index 2c4e271f2..cf3fda16b 100644 --- a/modules/xfeatures2d/src/surf.hpp +++ b/modules/xfeatures2d/src/surf.hpp @@ -64,6 +64,7 @@ public: bool upright; }; +#ifdef HAVE_OPENCL class SURF_OCL { public: @@ -145,6 +146,7 @@ protected: int status; }; +#endif // HAVE_OPENCL /* template void copyVectorToUMat(const std::vector<_Tp>& v, UMat& um) diff --git a/modules/xfeatures2d/src/surf.ocl.cpp b/modules/xfeatures2d/src/surf.ocl.cpp index b12ebd319..bf1c97c29 100644 --- a/modules/xfeatures2d/src/surf.ocl.cpp +++ b/modules/xfeatures2d/src/surf.ocl.cpp @@ -43,6 +43,9 @@ // //M*/ #include "precomp.hpp" + +#ifdef HAVE_OPENCL + #include "surf.hpp" #include @@ -204,7 +207,7 @@ bool SURF_OCL::setUpRight(UMat &keypoints) if( nFeatures == 0 ) return true; - size_t globalThreads[3] = {nFeatures, 1}; + size_t globalThreads[3] = {(size_t)nFeatures, 1}; ocl::Kernel kerUpRight("SURF_setUpRight", ocl::xfeatures2d::surf_oclsrc, kerOpts); return kerUpRight.args(ocl::KernelArg::ReadWrite(keypoints)).run(2, globalThreads, 0, true); } @@ -260,7 +263,7 @@ bool SURF_OCL::computeDescriptors(const UMat &keypoints, OutputArray _descriptor if(!kerCalcDesc.run(2, globalThreads, localThreads, true)) return false; - size_t localThreads_n[] = {dsize, 1}; + size_t localThreads_n[] = {(size_t)dsize, 1}; size_t globalThreads_n[] = {nFeatures*localThreads_n[0], localThreads_n[1]}; globalThreads[0] = nFeatures * localThreads[0]; @@ -461,3 +464,4 @@ bool SURF_OCL::calcOrientation(UMat &keypoints) } } +#endif // HAVE_OPENCL diff --git a/modules/ximgproc/doc/ximgproc.bib b/modules/ximgproc/doc/ximgproc.bib index a9b43c59b..8523622e6 100644 --- a/modules/ximgproc/doc/ximgproc.bib +++ b/modules/ximgproc/doc/ximgproc.bib @@ -78,6 +78,7 @@ organization={ACM} } + @inproceedings{xu2011image, title={Image smoothing via L 0 gradient minimization}, author={Xu, Li and Lu, Cewu and Xu, Yi and Jia, Jiaya}, @@ -88,3 +89,11 @@ year={2011}, organization={ACM} } + +@inproceedings{Revaud2015, + title={EpicFlow: Edge-Preserving Interpolation of Correspondences for Optical Flow}, + author={Revaud, Jerome and Weinzaepfel, Philippe and Harchaoui, Zaid and Schmid, Cordelia}, + booktitle={Computer Vision and Pattern Recognition (CVPR), IEEE Conference on}, + pages={1164--1172}, + year={2015} +} diff --git a/modules/ximgproc/include/opencv2/ximgproc.hpp b/modules/ximgproc/include/opencv2/ximgproc.hpp index 41b726096..cb55da078 100644 --- a/modules/ximgproc/include/opencv2/ximgproc.hpp +++ b/modules/ximgproc/include/opencv2/ximgproc.hpp @@ -39,6 +39,7 @@ #include "ximgproc/edge_filter.hpp" #include "ximgproc/disparity_filter.hpp" +#include "ximgproc/sparse_match_interpolator.hpp" #include "ximgproc/structured_edge_detection.hpp" #include "ximgproc/seeds.hpp" #include "ximgproc/fast_hough_transform.hpp" diff --git a/modules/ximgproc/include/opencv2/ximgproc/sparse_match_interpolator.hpp b/modules/ximgproc/include/opencv2/ximgproc/sparse_match_interpolator.hpp new file mode 100644 index 000000000..4821aba25 --- /dev/null +++ b/modules/ximgproc/include/opencv2/ximgproc/sparse_match_interpolator.hpp @@ -0,0 +1,132 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * 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 names of the copyright holders nor the names of the 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 copyright holders 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 __OPENCV_SPARSEMATCHINTERPOLATOR_HPP__ +#define __OPENCV_SPARSEMATCHINTERPOLATOR_HPP__ +#ifdef __cplusplus + +#include + +namespace cv { +namespace ximgproc { + +//! @addtogroup ximgproc_filters +//! @{ + +/** @brief Main interface for all filters, that take sparse matches as an +input and produce a dense per-pixel matching (optical flow) as an output. + */ +class CV_EXPORTS_W SparseMatchInterpolator : public Algorithm +{ +public: + /** @brief Interpolate input sparse matches. + + @param from_image first of the two matched images, 8-bit single-channel or three-channel. + + @param from_points points of the from_image for which there are correspondences in the + to_image (Point2f vector, size shouldn't exceed 32767) + + @param to_image second of the two matched images, 8-bit single-channel or three-channel. + + @param to_points points in the to_image corresponding to from_points + (Point2f vector, size shouldn't exceed 32767) + + @param dense_flow output dense matching (two-channel CV_32F image) + */ + CV_WRAP virtual void interpolate(InputArray from_image, InputArray from_points, + InputArray to_image , InputArray to_points, + OutputArray dense_flow) = 0; +}; + +/** @brief Sparse match interpolation algorithm based on modified locally-weighted affine +estimator from @cite Revaud2015 and Fast Global Smoother as post-processing filter. + */ +class CV_EXPORTS_W EdgeAwareInterpolator : public SparseMatchInterpolator +{ +public: + /** @brief K is a number of nearest-neighbor matches considered, when fitting a locally affine + model. Usually it should be around 128. However, lower values would make the interpolation + noticeably faster. + */ + CV_WRAP virtual void setK(int _k) = 0; + /** @see setK */ + CV_WRAP virtual int getK() = 0; + + /** @brief Sigma is a parameter defining how fast the weights decrease in the locally-weighted affine + fitting. Higher values can help preserve fine details, lower values can help to get rid of noise in the + output flow. + */ + CV_WRAP virtual void setSigma(float _sigma) = 0; + /** @see setSigma */ + CV_WRAP virtual float getSigma() = 0; + + /** @brief Lambda is a parameter defining the weight of the edge-aware term in geodesic distance, + should be in the range of 0 to 1000. + */ + CV_WRAP virtual void setLambda(float _lambda) = 0; + /** @see setLambda */ + CV_WRAP virtual float getLambda() = 0; + + /** @brief Sets whether the fastGlobalSmootherFilter() post-processing is employed. It is turned on by + default. + */ + CV_WRAP virtual void setUsePostProcessing(bool _use_post_proc) = 0; + /** @see setUsePostProcessing */ + CV_WRAP virtual bool getUsePostProcessing() = 0; + + /** @brief Sets the respective fastGlobalSmootherFilter() parameter. + */ + CV_WRAP virtual void setFGSLambda(float _lambda) = 0; + /** @see setFGSLambda */ + CV_WRAP virtual float getFGSLambda() = 0; + + /** @see setFGSLambda */ + CV_WRAP virtual void setFGSSigma(float _sigma) = 0; + /** @see setFGSLambda */ + CV_WRAP virtual float getFGSSigma() = 0; +}; + +/** @brief Factory method that creates an instance of the +EdgeAwareInterpolator. +*/ +CV_EXPORTS_W +Ptr createEdgeAwareInterpolator(); + +//! @} +} +} +#endif +#endif diff --git a/modules/ximgproc/samples/live_demo.cpp b/modules/ximgproc/samples/live_demo.cpp index dd5dc1bfb..8e16de3a3 100644 --- a/modules/ximgproc/samples/live_demo.cpp +++ b/modules/ximgproc/samples/live_demo.cpp @@ -189,7 +189,7 @@ int main() //Thread trackbar cv::setNumThreads(g_numberOfCPUs); //speedup filtering - createTrackbar("Threads", NULL, &g_numberOfCPUs, cv::getNumberOfCPUs(), changeNumberOfCpuCallback); + createTrackbar("Threads", String(), &g_numberOfCPUs, cv::getNumberOfCPUs(), changeNumberOfCpuCallback); //Buttons to choose different modes createButton("Mode Details Enhancement", changeModeCallback, (void*)filterDetailEnhancement, QT_RADIOBOX, true); @@ -199,15 +199,15 @@ int main() //sliders for Details Enhancement mode g_filterOp = filterDetailEnhancement; //set Details Enhancement as default filter - createTrackbar("Detail contrast", NULL, &g_contrastBase, 200); - createTrackbar("Detail level" , NULL, &g_detailsLevel, 200); + createTrackbar("Detail contrast", String(), &g_contrastBase, 200); + createTrackbar("Detail level" , String(), &g_detailsLevel, 200); //sliders for Stylizing mode - createTrackbar("Style gamma", NULL, &g_edgesGamma, 300); + createTrackbar("Style gamma", String(), &g_edgesGamma, 300); //sliders for every mode - createTrackbar("Sigma Spatial", NULL, &g_sigmaSpatial, 200); - createTrackbar("Sigma Color" , NULL, &g_sigmaColor, 200); + createTrackbar("Sigma Spatial", String(), &g_sigmaSpatial, 200); + createTrackbar("Sigma Color" , String(), &g_sigmaColor, 200); Mat rawFrame, outputFrame; Mat srcFrame, processedFrame; diff --git a/modules/ximgproc/src/sparse_match_interpolators.cpp b/modules/ximgproc/src/sparse_match_interpolators.cpp new file mode 100644 index 000000000..d5d8d1f1d --- /dev/null +++ b/modules/ximgproc/src/sparse_match_interpolators.cpp @@ -0,0 +1,881 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * 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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" +#include "opencv2/ximgproc/sparse_match_interpolator.hpp" +#include +#include + +using namespace std; + +#define INF 1E+20F + +namespace cv { +namespace ximgproc { + +struct SparseMatch +{ + Point2f reference_image_pos; + Point2f target_image_pos; + SparseMatch(){} + SparseMatch(Point2f ref_point, Point2f target_point): reference_image_pos(ref_point), target_image_pos(target_point) {} +}; + +bool operator<(const SparseMatch& lhs,const SparseMatch& rhs); + +void weightedLeastSquaresAffineFit(short* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst); +void generateHypothesis(short* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst); +void verifyHypothesis(short* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers); + +struct node +{ + float dist; + short label; + node() {} + node(short l,float d): dist(d), label(l) {} +}; + +class EdgeAwareInterpolatorImpl : public EdgeAwareInterpolator +{ +public: + static Ptr create(); + void interpolate(InputArray from_image, InputArray from_points, InputArray to_image, InputArray to_points, OutputArray dense_flow); + +protected: + int w,h; + int match_num; + + //internal buffers: + vector* g; + Mat labels; + Mat NNlabels; + Mat NNdistances; + + //tunable parameters: + float lambda; + int k; + float sigma; + bool use_post_proc; + float fgs_lambda; + float fgs_sigma; + + // static parameters: + static const int distance_transform_num_iter = 1; + static const int ransac_interpolation_num_iter = 1; + float regularization_coef; + static const int ransac_num_stripes = 4; + RNG rngs[ransac_num_stripes]; + + void init(); + void preprocessData(Mat& src, vector& matches); + void computeGradientMagnitude(Mat& src, Mat& dst); + void geodesicDistanceTransform(Mat& distances, Mat& cost_map); + void buildGraph(Mat& distances, Mat& cost_map); + void ransacInterpolation(vector& matches, Mat& dst_dense_flow); + +protected: + struct GetKNNMatches_ParBody : public ParallelLoopBody + { + EdgeAwareInterpolatorImpl* inst; + int num_stripes; + int stripe_sz; + + GetKNNMatches_ParBody(EdgeAwareInterpolatorImpl& _inst, int _num_stripes); + void operator () (const Range& range) const; + }; + + struct RansacInterpolation_ParBody : public ParallelLoopBody + { + EdgeAwareInterpolatorImpl* inst; + Mat* transforms; + float* weighted_inlier_nums; + float* eps; + SparseMatch* matches; + int num_stripes; + int stripe_sz; + int inc; + + RansacInterpolation_ParBody(EdgeAwareInterpolatorImpl& _inst, Mat* _transforms, float* _weighted_inlier_nums, float* _eps, SparseMatch* _matches, int _num_stripes, int _inc); + void operator () (const Range& range) const; + }; + +public: + void setK(int _k) {k=_k;} + int getK() {return k;} + void setSigma(float _sigma) {sigma=_sigma;} + float getSigma() {return sigma;} + void setLambda(float _lambda) {lambda=_lambda;} + float getLambda() {return lambda;} + void setUsePostProcessing(bool _use_post_proc) {use_post_proc=_use_post_proc;} + bool getUsePostProcessing() {return use_post_proc;} + void setFGSLambda(float _lambda) {fgs_lambda=_lambda;} + float getFGSLambda() {return fgs_lambda;} + void setFGSSigma(float _sigma) {fgs_sigma = _sigma;} + float getFGSSigma() {return fgs_sigma;} +}; + +void EdgeAwareInterpolatorImpl::init() +{ + lambda = 999.0f; + k = 128; + sigma = 0.05f; + use_post_proc = true; + fgs_lambda = 500.0f; + fgs_sigma = 1.5f; + regularization_coef = 0.01f; +} + +Ptr EdgeAwareInterpolatorImpl::create() +{ + EdgeAwareInterpolatorImpl *eai = new EdgeAwareInterpolatorImpl(); + eai->init(); + return Ptr(eai); +} + +void EdgeAwareInterpolatorImpl::interpolate(InputArray from_image, InputArray from_points, InputArray, InputArray to_points, OutputArray dense_flow) +{ + CV_Assert( !from_image.empty() && (from_image.depth() == CV_8U) && (from_image.channels() == 3 || from_image.channels() == 1) ); + CV_Assert( !from_points.empty() && from_points.isVector() && + !to_points .empty() && to_points .isVector() && + from_points.sameSize(to_points) ); + + w = from_image.cols(); + h = from_image.rows(); + + vector from_vector = *(const vector*)from_points.getObj(); + vector to_vector = *(const vector*)to_points .getObj(); + vector matches_vector(from_vector.size()); + for(unsigned int i=0;i[match_num]; + + preprocessData(src,matches_vector); + + dense_flow.create(from_image.size(),CV_32FC2); + Mat dst = dense_flow.getMat(); + ransacInterpolation(matches_vector,dst); + if(use_post_proc) + fastGlobalSmootherFilter(src,dst,dst,fgs_lambda,fgs_sigma); + + delete[] g; +} + +void EdgeAwareInterpolatorImpl::preprocessData(Mat& src, vector& matches) +{ + Mat distances(h,w,CV_32F); + Mat cost_map (h,w,CV_32F); + distances = Scalar(INF); + + int x,y; + for(unsigned int i=0;i(y,x) = 0.0f; + labels.at(y,x) = (short)i; + } + + computeGradientMagnitude(src,cost_map); + cost_map = (1000.0f-lambda) + lambda*cost_map; + + geodesicDistanceTransform(distances,cost_map); + buildGraph(distances,cost_map); + parallel_for_(Range(0,getNumThreads()),GetKNNMatches_ParBody(*this,getNumThreads())); +} + +void EdgeAwareInterpolatorImpl::computeGradientMagnitude(Mat& src, Mat& dst) +{ + Mat dx,dy; + Sobel(src, dx, CV_16S, 1, 0); + Sobel(src, dy, CV_16S, 0, 1); + float norm_coef = src.channels()*4.0f*255.0f; + + if(src.channels()==1) + { + for(int i=0;i(i); + short* dy_row = dy.ptr(i); + float* dst_row = dst.ptr(i); + + for(int j=0;j(i); + Vec3s* dy_row = dy.ptr(i); + float* dst_row = dst.ptr(i); + + for(int j=0;jd){\ + cur_dist=d;\ + cur_label = prev_label;}\ +} + + for(int it=0;it(0); + label_row = labels.ptr(0); + cost_row = cost_map.ptr(0); + for(j=1;j(i); + dist_row_prev = distances.ptr(i-1); + + label_row = labels.ptr(i); + label_row_prev = labels.ptr(i-1); + + cost_row = cost_map.ptr(i); + cost_row_prev = cost_map.ptr(i-1); + + j=0; + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j] ,label_row_prev[j] ,cost_row_prev[j] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j+1],label_row_prev[j+1],cost_row_prev[j+1],c2); + j++; + for(;j(h-1); + label_row = labels.ptr(h-1); + cost_row = cost_map.ptr(h-1); + for(j=w-2;j>=0;j--) + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j+1],label_row[j+1],cost_row[j+1],c1); + + for(i=h-2;i>=0;i--) + { + dist_row = distances.ptr(i); + dist_row_prev = distances.ptr(i+1); + + label_row = labels.ptr(i); + label_row_prev = labels.ptr(i+1); + + cost_row = cost_map.ptr(i); + cost_row_prev = cost_map.ptr(i+1); + + j=w-1; + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j] ,label_row_prev[j] ,cost_row_prev[j] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j-1],label_row_prev[j-1],cost_row_prev[j-1],c2); + j--; + for(;j>0;j--) + { + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j+1] ,label_row[j+1] ,cost_row[j+1] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j+1],label_row_prev[j+1],cost_row_prev[j+1],c2); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j] ,label_row_prev[j] ,cost_row_prev[j] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j-1],label_row_prev[j-1],cost_row_prev[j-1],c2); + } + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row[j+1] ,label_row[j+1] ,cost_row[j+1] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j+1],label_row_prev[j+1],cost_row_prev[j+1],c2); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j] ,label_row_prev[j] ,cost_row_prev[j] ,c1); + } + } +#undef CHECK +} + +void EdgeAwareInterpolatorImpl::buildGraph(Mat& distances, Mat& cost_map) +{ + float *dist_row, *cost_row; + float *dist_row_prev, *cost_row_prev; + short *label_row; + short *label_row_prev; + int i,j; + const float c1 = 1.0f/2.0f; + const float c2 = sqrt(2.0f)/2.0f; + float d; + bool found; + +#define CHECK(cur_dist,cur_label,cur_cost,prev_dist,prev_label,prev_cost,coef)\ + if(cur_label!=prev_label)\ + {\ + d = prev_dist + cur_dist + coef*(cur_cost+prev_cost);\ + found = false;\ + for(unsigned int n=0;n(0); + label_row = labels.ptr(0); + cost_row = cost_map.ptr(0); + for(j=1;j(i); + dist_row_prev = distances.ptr(i-1); + + label_row = labels.ptr(i); + label_row_prev = labels.ptr(i-1); + + cost_row = cost_map.ptr(i); + cost_row_prev = cost_map.ptr(i-1); + + j=0; + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j] ,label_row_prev[j] ,cost_row_prev[j] ,c1); + CHECK(dist_row[j],label_row[j],cost_row[j],dist_row_prev[j+1],label_row_prev[j+1],cost_row_prev[j+1],c2); + j++; + for(;j>1 + node* heap; + short* heap_pos; + node tmp_node; + short size; + short num_labels; + + nodeHeap(short _num_labels) + { + num_labels = _num_labels; + heap = new node[num_labels+1]; + heap[0] = node(-1,-1.0f); + heap_pos = new short[num_labels]; + memset(heap_pos,0,sizeof(short)*num_labels); + size=0; + } + + ~nodeHeap() + { + delete[] heap; + delete[] heap_pos; + } + + void clear() + { + size=0; + memset(heap_pos,0,sizeof(short)*num_labels); + } + + inline bool empty() + { + return (size==0); + } + + inline void nodeSwap(short idx1, short idx2) + { + heap_pos[heap[idx1].label] = idx2; + heap_pos[heap[idx2].label] = idx1; + + tmp_node = heap[idx1]; + heap[idx1] = heap[idx2]; + heap[idx2] = tmp_node; + } + + void add(node n) + { + size++; + heap[size] = n; + heap_pos[n.label] = size; + short i = size; + short parent_i = i>>1; + while(heap[i].dist>1; + } + } + + node getMin() + { + node res = heap[1]; + heap_pos[res.label] = 0; + + short i=1; + short left,right; + while( (left=i<<1) < size ) + { + right = left+1; + if(heap[left].dist>1; + while(heap[i].dist>1; + } + + size--; + return res; + } + + //checks if node is already in the heap + //if not - add it + //if it is - update it with the min dist of the two + void updateNode(node n) + { + if(heap_pos[n.label]) + { + short i = heap_pos[n.label]; + heap[i].dist = min(heap[i].dist,n.dist); + short parent_i = i>>1; + while(heap[i].dist>1; + } + } + else + add(n); + } +}; + +EdgeAwareInterpolatorImpl::GetKNNMatches_ParBody::GetKNNMatches_ParBody(EdgeAwareInterpolatorImpl& _inst, int _num_stripes): +inst(&_inst),num_stripes(_num_stripes) +{ + stripe_sz = (int)ceil(inst->match_num/(double)num_stripes); +} + +void EdgeAwareInterpolatorImpl::GetKNNMatches_ParBody::operator() (const Range& range) const +{ + int start = std::min(range.start * stripe_sz, inst->match_num); + int end = std::min(range.end * stripe_sz, inst->match_num); + nodeHeap q((short)inst->match_num); + int num_expanded_vertices; + unsigned char* expanded_flag = new unsigned char[inst->match_num]; + node* neighbors; + + for(int i=start;ig[i].empty()) + continue; + + num_expanded_vertices = 0; + memset(expanded_flag,0,inst->match_num); + q.clear(); + q.add(node((short)i,0.0f)); + short* NNlabels_row = inst->NNlabels.ptr(i); + float* NNdistances_row = inst->NNdistances.ptr(i); + while(num_expanded_verticesk && !q.empty()) + { + node vert_for_expansion = q.getMin(); + expanded_flag[vert_for_expansion.label] = 1; + + //write the expanded vertex to the dst: + NNlabels_row[num_expanded_vertices] = vert_for_expansion.label; + NNdistances_row[num_expanded_vertices] = vert_for_expansion.dist; + num_expanded_vertices++; + + //update the heap: + neighbors = &inst->g[vert_for_expansion.label].front(); + for(int j=0;j<(int)inst->g[vert_for_expansion.label].size();j++) + { + if(!expanded_flag[neighbors[j].label]) + q.updateNode(node(neighbors[j].label,vert_for_expansion.dist+neighbors[j].dist)); + } + } + } + delete[] expanded_flag; +} + +void weightedLeastSquaresAffineFit(short* labels, float* weights, int count, float lambda, SparseMatch* matches, Mat& dst) +{ + double sa[6][6]={{0.}}, sb[6]={0.}; + Mat A (6, 6, CV_64F, &sa[0][0]), + B (6, 1, CV_64F, sb), + MM(1, 6, CV_64F); + Point2f a,b; + float w; + + for( int i = 0; i < count; i++ ) + { + a = matches[labels[i]].reference_image_pos; + b = matches[labels[i]].target_image_pos; + w = weights[i]; + + sa[0][0] += w*a.x*a.x; + sa[0][1] += w*a.y*a.x; + sa[0][2] += w*a.x; + sa[1][1] += w*a.y*a.y; + sa[1][2] += w*a.y; + sa[2][2] += w; + + sb[0] += w*a.x*b.x; + sb[1] += w*a.y*b.x; + sb[2] += w*b.x; + sb[3] += w*a.x*b.y; + sb[4] += w*a.y*b.y; + sb[5] += w*b.y; + } + sa[0][0] += lambda; + sa[1][1] += lambda; + + sa[3][4] = sa[4][3] = sa[1][0] = sa[0][1]; + sa[3][5] = sa[5][3] = sa[2][0] = sa[0][2]; + sa[4][5] = sa[5][4] = sa[2][1] = sa[1][2]; + + sa[3][3] = sa[0][0]; + sa[4][4] = sa[1][1]; + sa[5][5] = sa[2][2]; + + sb[0] += lambda; + sb[4] += lambda; + + solve(A, B, MM, DECOMP_EIG); + MM.reshape(2,3).convertTo(dst,CV_32F); +} + +void generateHypothesis(short* labels, int count, RNG& rng, unsigned char* is_used, SparseMatch* matches, Mat& dst) +{ + int idx; + Point2f src_points[3]; + Point2f dst_points[3]; + memset(is_used,0,count); + + // randomly get 3 distinct matches + idx = rng.uniform(0,count-2); + is_used[idx] = true; + src_points[0] = matches[labels[idx]].reference_image_pos; + dst_points[0] = matches[labels[idx]].target_image_pos; + + idx = rng.uniform(0,count-1); + if (is_used[idx]) + idx = count-2; + is_used[idx] = true; + src_points[1] = matches[labels[idx]].reference_image_pos; + dst_points[1] = matches[labels[idx]].target_image_pos; + + idx = rng.uniform(0,count); + if (is_used[idx]) + idx = count-1; + is_used[idx] = true; + src_points[2] = matches[labels[idx]].reference_image_pos; + dst_points[2] = matches[labels[idx]].target_image_pos; + + // compute an affine transform: + getAffineTransform(src_points,dst_points).convertTo(dst,CV_32F); +} + +void verifyHypothesis(short* labels, float* weights, int count, SparseMatch* matches, float eps, float lambda, Mat& hypothesis_transform, Mat& old_transform, float& old_weighted_num_inliers) +{ + float* tr = hypothesis_transform.ptr(0); + Point2f a,b; + float weighted_num_inliers = -lambda*((tr[0]-1)*(tr[0]-1)+tr[1]*tr[1]+tr[3]*tr[3]+(tr[4]-1)*(tr[4]-1)); + + for(int i=0;i=old_weighted_num_inliers) + { + old_weighted_num_inliers = weighted_num_inliers; + hypothesis_transform.copyTo(old_transform); + } +} + +EdgeAwareInterpolatorImpl::RansacInterpolation_ParBody::RansacInterpolation_ParBody(EdgeAwareInterpolatorImpl& _inst, Mat* _transforms, float* _weighted_inlier_nums, float* _eps, SparseMatch* _matches, int _num_stripes, int _inc): +inst(&_inst), transforms(_transforms), weighted_inlier_nums(_weighted_inlier_nums), eps(_eps), matches(_matches), num_stripes(_num_stripes), inc(_inc) +{ + stripe_sz = (int)ceil(inst->match_num/(double)num_stripes); +} + +void EdgeAwareInterpolatorImpl::RansacInterpolation_ParBody::operator() (const Range& range) const +{ + if(range.end>range.start+1) + { + for(int n=range.start;nmatch_num); + int end = std::min(range.end * stripe_sz, inst->match_num); + if(inc<0) + { + int tmp = end; + end = start-1; + start = tmp-1; + } + + short* KNNlabels; + float* KNNdistances; + unsigned char* is_used = new unsigned char[inst->k]; + Mat hypothesis_transform; + + short* inlier_labels = new short[inst->k]; + float* inlier_distances = new float[inst->k]; + float* tr; + int num_inliers; + Point2f a,b; + + for(int i=start;i!=end;i+=inc) + { + if(inst->g[i].empty()) + continue; + + KNNlabels = inst->NNlabels.ptr(i); + KNNdistances = inst->NNdistances.ptr(i); + if(inc>0) //forward pass + { + hal::exp(KNNdistances,KNNdistances,inst->k); + + Point2f average = Point2f(0.0f,0.0f); + for(int j=0;jk;j++) + average += matches[KNNlabels[j]].target_image_pos - matches[KNNlabels[j]].reference_image_pos; + average/=inst->k; + float average_dist = 0.0; + Point2f vec; + for(int j=0;jk;j++) + { + vec = (matches[KNNlabels[j]].target_image_pos - matches[KNNlabels[j]].reference_image_pos); + average_dist += abs(vec.x-average.x) + abs(vec.y-average.y); + } + eps[i] = min(0.5f*(average_dist/inst->k),2.0f); + } + + for(int it=0;itransac_interpolation_num_iter;it++) + { + generateHypothesis(KNNlabels,inst->k,inst->rngs[range.start],is_used,matches,hypothesis_transform); + verifyHypothesis(KNNlabels,KNNdistances,inst->k,matches,eps[i],inst->regularization_coef,hypothesis_transform,transforms[i],weighted_inlier_nums[i]); + } + + //propagate hypotheses from neighbors: + node* neighbors = &inst->g[i].front(); + for(int j=0;j<(int)inst->g[i].size();j++) + { + if((inc*neighbors[j].label)<(inc*i) && (inc*neighbors[j].label)>=(inc*start)) //already processed this neighbor + verifyHypothesis(KNNlabels,KNNdistances,inst->k,matches,eps[i],inst->regularization_coef,transforms[neighbors[j].label],transforms[i],weighted_inlier_nums[i]); + } + + if(inc<0) //backward pass + { + // determine inliers and compute a least squares fit: + tr = transforms[i].ptr(0); + num_inliers = 0; + + for(int j=0;jk;j++) + { + a = matches[KNNlabels[j]].reference_image_pos; + b = matches[KNNlabels[j]].target_image_pos; + if(abs(tr[0]*a.x + tr[1]*a.y + tr[2] - b.x) + + abs(tr[3]*a.x + tr[4]*a.y + tr[5] - b.y) < eps[i]) + { + inlier_labels[num_inliers] = KNNlabels[j]; + inlier_distances[num_inliers] = KNNdistances[j]; + num_inliers++; + } + } + + weightedLeastSquaresAffineFit(inlier_labels,inlier_distances,num_inliers,inst->regularization_coef,matches,transforms[i]); + } + } + + delete[] inlier_labels; + delete[] inlier_distances; + delete[] is_used; +} + +void EdgeAwareInterpolatorImpl::ransacInterpolation(vector& matches, Mat& dst_dense_flow) +{ + NNdistances *= (-sigma*sigma); + + Mat* transforms = new Mat[match_num]; + float* weighted_inlier_nums = new float[match_num]; + float* eps = new float[match_num]; + for(int i=0;i(i); + Point2f* dst_row = dst_dense_flow.ptr(i); + for(int j=0;j(0); + dst_row[j] = Point2f(tr[0]*j+tr[1]*i+tr[2],tr[3]*j+tr[4]*i+tr[5]) - Point2f((float)j,(float)i); + } + } + + delete[] transforms; + delete[] weighted_inlier_nums; + delete[] eps; +} + +CV_EXPORTS_W +Ptr createEdgeAwareInterpolator() +{ + return Ptr(EdgeAwareInterpolatorImpl::create()); +} + +bool operator<(const SparseMatch& lhs,const SparseMatch& rhs) +{ + if((int)(lhs.reference_image_pos.y+0.5f)!=(int)(rhs.reference_image_pos.y+0.5f)) + return (lhs.reference_image_pos.y(i*stride/shrink); @@ -599,6 +601,9 @@ protected: dstM.setTo(0); float step = 2.0f * CV_SQR(stride) / CV_SQR(ipSize) / nTreesEval; + #ifdef _OPENMP + #pragma omp parallel for + #endif for (int i = 0; i < height; ++i) { int *pIndex = indexes.ptr(i); diff --git a/modules/ximgproc/test/test_sparse_match_interpolator.cpp b/modules/ximgproc/test/test_sparse_match_interpolator.cpp new file mode 100644 index 000000000..bb9eb6174 --- /dev/null +++ b/modules/ximgproc/test/test_sparse_match_interpolator.cpp @@ -0,0 +1,195 @@ +/* + * By downloading, copying, installing or using the software you agree to this license. + * If you do not agree to this license, do not download, install, + * copy or use the software. + * + * + * License Agreement + * For Open Source Computer Vision Library + * (3 - clause BSD License) + * + * 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 names of the copyright holders nor the names of the 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 copyright holders 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 "test_precomp.hpp" +#include "opencv2/ximgproc/sparse_match_interpolator.hpp" +#include + +namespace cvtest +{ + +using namespace std; +using namespace std::tr1; +using namespace testing; +using namespace perf; +using namespace cv; +using namespace cv::ximgproc; + +static string getDataDir() +{ + return cvtest::TS::ptr()->get_data_path(); +} + +const float FLOW_TAG_FLOAT = 202021.25f; +Mat readOpticalFlow( const String& path ) +{ +// CV_Assert(sizeof(float) == 4); + //FIXME: ensure right sizes of int and float - here and in writeOpticalFlow() + + Mat_ flow; + ifstream file(path.c_str(), std::ios_base::binary); + if ( !file.good() ) + return flow; // no file - return empty matrix + + float tag; + file.read((char*) &tag, sizeof(float)); + if ( tag != FLOW_TAG_FLOAT ) + return flow; + + int width, height; + + file.read((char*) &width, 4); + file.read((char*) &height, 4); + + flow.create(height, width); + + for ( int i = 0; i < flow.rows; ++i ) + { + for ( int j = 0; j < flow.cols; ++j ) + { + Point2f u; + file.read((char*) &u.x, sizeof(float)); + file.read((char*) &u.y, sizeof(float)); + if ( !file.good() ) + { + flow.release(); + return flow; + } + + flow(i, j) = u; + } + } + file.close(); + return flow; +} + +CV_ENUM(GuideTypes, CV_8UC1, CV_8UC3) +typedef tuple InterpolatorParams; +typedef TestWithParam InterpolatorTest; + +TEST(InterpolatorTest, ReferenceAccuracy) +{ + double MAX_DIF = 1.0; + double MAX_MEAN_DIF = 1.0 / 256.0; + string dir = getDataDir() + "cv/sparse_match_interpolator"; + + Mat src = imread(getDataDir() + "cv/optflow/RubberWhale1.png",IMREAD_COLOR); + ASSERT_FALSE(src.empty()); + + Mat ref_flow = readOpticalFlow(dir + "/RubberWhale_reference_result.flo"); + ASSERT_FALSE(ref_flow.empty()); + + ifstream file((dir + "/RubberWhale_sparse_matches.txt").c_str()); + float from_x,from_y,to_x,to_y; + vector from_points; + vector to_points; + + while(file >> from_x >> from_y >> to_x >> to_y) + { + from_points.push_back(Point2f(from_x,from_y)); + to_points.push_back(Point2f(to_x,to_y)); + } + + cv::setNumThreads(cv::getNumberOfCPUs()); + Mat res_flow; + + Ptr interpolator = createEdgeAwareInterpolator(); + interpolator->setK(128); + interpolator->setSigma(0.05f); + interpolator->setUsePostProcessing(true); + interpolator->setFGSLambda(500.0f); + interpolator->setFGSSigma(1.5f); + interpolator->interpolate(src,from_points,Mat(),to_points,res_flow); + + EXPECT_LE(cv::norm(res_flow, ref_flow, NORM_INF), MAX_DIF); + EXPECT_LE(cv::norm(res_flow, ref_flow, NORM_L1) , MAX_MEAN_DIF*res_flow.total()); +} + +TEST_P(InterpolatorTest, MultiThreadReproducibility) +{ + if (cv::getNumberOfCPUs() == 1) + return; + + double MAX_DIF = 1.0; + double MAX_MEAN_DIF = 1.0 / 256.0; + int loopsCount = 2; + RNG rng(0); + + InterpolatorParams params = GetParam(); + Size size = get<0>(params); + int guideType = get<1>(params); + + Mat from(size, guideType); + randu(from, 0, 255); + + int num_matches = rng.uniform(5,SHRT_MAX-1); + vector from_points; + vector to_points; + + for(int i=0;i interpolator = createEdgeAwareInterpolator(); + interpolator->setK(K); + interpolator->setSigma(sigma); + interpolator->setUsePostProcessing(true); + interpolator->setFGSLambda(FGSlambda); + interpolator->setFGSSigma(FGSsigma); + + cv::setNumThreads(cv::getNumberOfCPUs()); + Mat resMultiThread; + interpolator->interpolate(from,from_points,Mat(),to_points,resMultiThread); + + cv::setNumThreads(1); + Mat resSingleThread; + interpolator->interpolate(from,from_points,Mat(),to_points,resSingleThread); + + EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF); + EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1) , MAX_MEAN_DIF*resMultiThread.total()); + } +} +INSTANTIATE_TEST_CASE_P(FullSet,InterpolatorTest, Combine(Values(szODD,szVGA), GuideTypes::all())); +} \ No newline at end of file diff --git a/modules/xobjdetect/CMakeLists.txt b/modules/xobjdetect/CMakeLists.txt index 8d78c8a9f..5a1bbfab6 100644 --- a/modules/xobjdetect/CMakeLists.txt +++ b/modules/xobjdetect/CMakeLists.txt @@ -1,2 +1,3 @@ set(the_description "Object detection algorithms") -ocv_define_module(xobjdetect opencv_core opencv_imgproc opencv_highgui WRAP python) +ocv_define_module(xobjdetect opencv_core opencv_imgproc opencv_highgui opencv_objdetect WRAP python) +add_subdirectory(tools) diff --git a/modules/xobjdetect/include/opencv2/xobjdetect.hpp b/modules/xobjdetect/include/opencv2/xobjdetect.hpp index 0c3e34541..45038ab24 100644 --- a/modules/xobjdetect/include/opencv2/xobjdetect.hpp +++ b/modules/xobjdetect/include/opencv2/xobjdetect.hpp @@ -49,201 +49,53 @@ the use of this software, even if advised of the possibility of such damage. /** @defgroup xobjdetect Extended object detection */ - namespace cv { namespace xobjdetect { - //! @addtogroup xobjdetect //! @{ -/** @brief Compute channels for integral channel features evaluation - -@param image image for which channels should be computed -@param channels output array for computed channels - */ -CV_EXPORTS void computeChannels(InputArray image, std::vector& channels); - -/** @brief Feature evaluation interface - */ -class CV_EXPORTS FeatureEvaluator : public Algorithm -{ -public: - /** @brief Set channels for feature evaluation - - @param channels array of channels to be set - */ - virtual void setChannels(InputArrayOfArrays channels) = 0; - - /** @brief Set window position to sample features with shift. By default position is (0, 0). - - @param position position to be set - */ - virtual void setPosition(Size position) = 0; - - /** @brief Evaluate feature value with given index for current channels and window position. - - @param feature_ind index of feature to be evaluated - */ - virtual int evaluate(size_t feature_ind) const = 0; - - /** @brief Evaluate all features for current channels and window position. - - @param feature_values matrix-column of evaluated feature values - */ - virtual void evaluateAll(OutputArray feature_values) const = 0; - - virtual void assertChannels() = 0; -}; - -/** @brief Construct feature evaluator. - -@param features features for evaluation -@param type feature type. Can be "icf" or "acf" - */ -CV_EXPORTS Ptr -createFeatureEvaluator(const std::vector >& features, - const std::string& type); - -/** @brief Generate integral features. Returns vector of features. -@param window_size size of window in which features should be evaluated -@param type feature type. Can be "icf" or "acf" -@param count number of features to generate. -@param channel_count number of feature channels - */ -std::vector > -generateFeatures(Size window_size, const std::string& type, - int count = INT_MAX, int channel_count = 10); - -//sort in-place of columns of the input matrix -void sort_columns_without_copy(Mat& m, Mat indices = Mat()); - -/** @brief Parameters for WaldBoost. weak_count — number of weak learners, alpha — cascade thresholding param. - */ -struct CV_EXPORTS WaldBoostParams -{ - int weak_count; - float alpha; - - WaldBoostParams(): weak_count(100), alpha(0.02f) - {} -}; - -/** @brief WaldBoost object detector from @cite Sochman05 . -*/ -class CV_EXPORTS WaldBoost : public Algorithm -{ -public: - /** @brief Train WaldBoost cascade for given data. - - Returns feature indices chosen for cascade. Feature enumeration starts from 0. - @param data matrix of feature values, size M x N, one feature per row - @param labels matrix of samples class labels, size 1 x N. Labels can be from {-1, +1} - @param use_fast_log - */ - virtual std::vector train(Mat& data, - const Mat& labels, bool use_fast_log=false) = 0; - - /** @brief Predict objects class given object that can compute object features. - - Returns unnormed confidence value — measure of confidence that object is from class +1. - @param feature_evaluator object that can compute features by demand - */ - virtual float predict( - const Ptr& feature_evaluator) const = 0; -}; - -/** @brief Construct WaldBoost object. - */ -CV_EXPORTS Ptr -createWaldBoost(const WaldBoostParams& params = WaldBoostParams()); - -/** @brief Params for ICFDetector training. - */ -struct CV_EXPORTS ICFDetectorParams -{ - int feature_count; - int weak_count; - int model_n_rows; - int model_n_cols; - int bg_per_image; - std::string features_type; - float alpha; - bool is_grayscale; - bool use_fast_log; - - ICFDetectorParams(): feature_count(UINT_MAX), weak_count(100), - model_n_rows(56), model_n_cols(56), bg_per_image(5), alpha(0.02f), is_grayscale(false), use_fast_log(false) - {} -}; - -/** @brief Integral Channel Features from @cite Dollar09 . +/** @brief WaldBoost detector */ -class CV_EXPORTS ICFDetector -{ +class CV_EXPORTS WBDetector { public: - - ICFDetector(): waldboost_(), features_(), ftype_() {} - - /** @brief Train detector. - - @param pos_filenames path to folder with images of objects (wildcards like /my/path/\*.png are allowed) - @param bg_filenames path to folder with background images - @param params parameters for detector training - */ - void train(const std::vector& pos_filenames, - const std::vector& bg_filenames, - ICFDetectorParams params = ICFDetectorParams()); - - /** @brief Detect objects on image. - @param image image for detection - @param objects output array of bounding boxes - @param scaleFactor scale between layers in detection pyramid - @param minSize min size of objects in pixels - @param maxSize max size of objects in pixels - @param threshold - @param slidingStep sliding window step - @param values output vector with values of positive samples - */ - void detect(const Mat& image, std::vector& objects, - float scaleFactor, Size minSize, Size maxSize, float threshold, int slidingStep, std::vector& values); - - /** @brief Detect objects on image. - @param img image for detection - @param objects output array of bounding boxes - @param minScaleFactor min factor by which the image will be resized - @param maxScaleFactor max factor by which the image will be resized - @param factorStep scaling factor is incremented each pyramid layer according to this parameter - @param threshold - @param slidingStep sliding window step - @param values output vector with values of positive samples - */ - void detect(const Mat& img, std::vector& objects, float minScaleFactor, float maxScaleFactor, float factorStep, float threshold, int slidingStep, std::vector& values); + /** @brief Read detector from FileNode. + @param node FileNode for input + */ + virtual void read(const FileNode &node) = 0; /** @brief Write detector to FileStorage. @param fs FileStorage for output - */ - void write(FileStorage &fs) const; - - /** @brief Write ICFDetector to FileNode - @param node FileNode for reading - */ - void read(const FileNode &node); - -private: - Ptr waldboost_; - std::vector > features_; - int model_n_rows_; - int model_n_cols_; - std::string ftype_; + */ + virtual void write(FileStorage &fs) const = 0; + + /** @brief Train WaldBoost detector + @param pos_samples Path to directory with cropped positive samples + @param neg_imgs Path to directory with negative (background) images + */ + virtual void train( + const std::string& pos_samples, + const std::string& neg_imgs) = 0; + + /** @brief Detect objects on image using WaldBoost detector + @param img Input image for detection + @param bboxes Bounding boxes coordinates output vector + @param confidences Confidence values for bounding boxes output vector + */ + virtual void detect( + const Mat& img, + std::vector &bboxes, + std::vector &confidences) = 0; + + /** @brief Create instance of WBDetector + */ + static Ptr create(); + + virtual ~WBDetector(){} }; -CV_EXPORTS void write(FileStorage& fs, String&, const ICFDetector& detector); - -CV_EXPORTS void read(const FileNode& node, ICFDetector& d, - const ICFDetector& default_value = ICFDetector()); //! @} diff --git a/modules/xobjdetect/include/opencv2/xobjdetect/private.hpp b/modules/xobjdetect/include/opencv2/xobjdetect/private.hpp deleted file mode 100644 index 3873413db..000000000 --- a/modules/xobjdetect/include/opencv2/xobjdetect/private.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __OPENCV_XOBJDETECT_PRIVATE_HPP__ -#define __OPENCV_XOBJDETECT_PRIVATE_HPP__ - -#ifndef __OPENCV_BUILD -# error this is a private header, do not include it outside OpenCV -#endif - -#include - -namespace cv -{ -namespace xobjdetect -{ - -class CV_EXPORTS Stump -{ -public: - - /* Initialize zero stump */ - Stump(): threshold_(0), polarity_(1), pos_value_(1), neg_value_(-1) {} - - /* Initialize stump with given threshold, polarity - and classification values */ - Stump(int threshold, int polarity, float pos_value, float neg_value): - threshold_(threshold), polarity_(polarity), - pos_value_(pos_value), neg_value_(neg_value) {} - - /* Train stump for given data - - data — matrix of feature values, size M x N, one feature per row - - labels — matrix of sample class labels, size 1 x N. Labels can be from - {-1, +1} - - weights — matrix of sample weights, size 1 x N - - visited_features: vector of already visited features (ignored in successive calls) - - Returns chosen feature index. Feature enumeration starts from 0 - */ - int train(const Mat& data, const Mat& labels, const Mat& weights, const std::vector& visited_features, bool use_fast_log = false); - - /* Predict object class given - - value — feature value. Feature must be the same as was chosen - during training stump - - Returns real value, sign(value) means class - */ - float predict(int value) const; - - /* Write stump in FileStorage */ - void write(FileStorage& fs) const - { - fs << "{" - << "threshold" << threshold_ - << "polarity" << polarity_ - << "pos_value" << pos_value_ - << "neg_value" << neg_value_ - << "}"; - } - - /* Read stump */ - void read(const FileNode& node) - { - threshold_ = (int)node["threshold"]; - polarity_ = (int)node["polarity"]; - pos_value_ = (float)node["pos_value"]; - neg_value_ = (float)node["neg_value"]; - } - -private: - /* Stump decision threshold */ - int threshold_; - /* Stump polarity, can be from {-1, +1} */ - int polarity_; - /* Classification values for positive and negative classes */ - float pos_value_, neg_value_; -}; - -void read(const FileNode& node, Stump& s, const Stump& default_value=Stump()); - -void write(FileStorage& fs, String&, const Stump& s); - -} /* namespace xobjdetect */ -} /* namespace cv */ - -#endif // __OPENCV_XOBJDETECT_PRIVATE_HPP__ diff --git a/modules/xobjdetect/src/acffeature.cpp b/modules/xobjdetect/src/acffeature.cpp deleted file mode 100644 index aac2601ef..000000000 --- a/modules/xobjdetect/src/acffeature.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" - -using std::vector; - -using std::min; - -#include -using std::cout; -using std::endl; - -namespace cv -{ -namespace xobjdetect -{ - -static bool isNull(const Mat_ &m) -{ - bool null_data = true; - for( int row = 0; row < m.rows; ++row ) - { - for( int col = 0; col < m.cols; ++col ) - if( m.at(row, col) ) - null_data = false; - } - return null_data; -} - -class FeatureEvaluatorImpl : public FeatureEvaluator -{ -public: - FeatureEvaluatorImpl(const vector >& features): - features_(features), channels_(), position_() - { - CV_Assert(features.size() > 0); - } - - virtual void assertChannels() - { - bool null_data = true; - for( size_t i = 0; i < channels_.size(); ++i ) - null_data &= isNull(channels_[i]); - CV_Assert(!null_data); - } - - virtual void evaluateAll(OutputArray feature_values) const - { - Mat_ feature_vals(1, (int)features_.size()); - for( int i = 0; i < (int)features_.size(); ++i ) - { - feature_vals(0, i) = evaluate(i); - } - feature_values.assign(feature_vals); - } - -protected: - /* Features to evaluate */ - vector > features_; - /* Channels for feature evaluation */ - std::vector channels_; - /* Channels window position */ - Size position_; -}; - -class ICFFeatureEvaluatorImpl : public FeatureEvaluatorImpl -{ -public: - ICFFeatureEvaluatorImpl(const vector >& features): - FeatureEvaluatorImpl(features) - { - } - - virtual void setChannels(InputArrayOfArrays channels); - virtual void setPosition(Size position); - virtual int evaluate(size_t feature_ind) const; -}; - -void ICFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels) -{ - channels_.clear(); - vector ch; - channels.getMatVector(ch); - - for( size_t i = 0; i < ch.size(); ++i ) - { - const Mat &channel = ch[i]; - Mat integral_channel; - integral(channel, integral_channel, CV_32F); - integral_channel.convertTo(integral_channel, CV_32S); - channels_.push_back(integral_channel.clone()); - } -} - -void ICFFeatureEvaluatorImpl::setPosition(Size position) -{ - position_ = position; -} - - -int ICFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const -{ - /* - - //following return is equal to this commented code, left here for readability. The new code runs much faster. - * - const vector& feature = features_[feature_ind]; - int x = feature[0] + position_.height; - int y = feature[1] + position_.width; - int x_to = feature[2] + position_.height; - int y_to = feature[3] + position_.width; - int n = feature[4]; - const Mat_& ch = channels_[n]; - return ch(y_to + 1, x_to + 1) - ch(y, x_to + 1) - ch(y_to + 1, x) + ch(y, x); - */ - - CV_Assert(feature_ind < features_.size()); - - return *(channels_[features_[feature_ind][4]].ptr()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][3] + position_.width+1))+ features_[feature_ind][2] + position_.height + 1)) - - *(channels_[features_[feature_ind][4]].ptr()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][1] + position_.width))+ features_[feature_ind][2] + position_.height + 1)) - - *(channels_[features_[feature_ind][4]].ptr()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][3] + position_.width+1))+ features_[feature_ind][0] + position_.height)) + - *(channels_[features_[feature_ind][4]].ptr()+((channels_[features_[feature_ind][4]].cols*(features_[feature_ind][1] + position_.width))+ features_[feature_ind][0] + position_.height)); -} - -class ACFFeatureEvaluatorImpl : public FeatureEvaluatorImpl -{ -public: - ACFFeatureEvaluatorImpl(const vector >& features): - FeatureEvaluatorImpl(features) - { - } - - virtual void setChannels(InputArrayOfArrays channels); - virtual void setPosition(Size position); - virtual int evaluate(size_t feature_ind) const; -}; - -void ACFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels) -{ - channels_.clear(); - vector ch; - channels.getMatVector(ch); - - for( size_t i = 0; i < ch.size(); ++i ) - { - const Mat &channel = ch[i]; - Mat_ acf_channel = Mat_::zeros(channel.rows / 4, channel.cols / 4); - for( int row = 0; row < channel.rows; row += 4 ) - { - for( int col = 0; col < channel.cols; col += 4 ) - { - int sum = 0; - for( int cell_row = row; cell_row < row + 4; ++cell_row ) - for( int cell_col = col; cell_col < col + 4; ++cell_col ) - sum += (int)channel.at(cell_row, cell_col); - - acf_channel(row / 4, col / 4) = sum; - } - } - - channels_.push_back(acf_channel.clone()); - } -} - -void ACFFeatureEvaluatorImpl::setPosition(Size position) -{ - position_ = Size(position.width / 4, position.height / 4); -} - -int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const -{ - CV_Assert(feature_ind < features_.size()); - - const vector& feature = features_[feature_ind]; - int x = feature[0]; - int y = feature[1]; - int n = feature[2]; - return channels_[n].at(y + position_.width, x + position_.height); -} - -Ptr createFeatureEvaluator( - const vector >& features, const std::string& type) -{ - FeatureEvaluator *evaluator = NULL; - if( type == "acf" ) - evaluator = new ACFFeatureEvaluatorImpl(features); - else if( type == "icf" ) - evaluator = new ICFFeatureEvaluatorImpl(features); - else - CV_Error(CV_StsBadArg, "type value is either acf or icf"); - - return Ptr(evaluator); -} - -vector > generateFeatures(Size window_size, const std::string& type, - int count, int channel_count) -{ - CV_Assert(count > 0); - vector > features; - if( type == "acf" ) - { - int cur_count = 0; - int max_count = window_size.width * window_size.height / 16; - count = min(count, max_count); - for( int x = 0; x < window_size.width / 4; ++x ) - for( int y = 0; y < window_size.height / 4; ++y ) - for( int n = 0; n < channel_count; ++n ) - { - int f[] = {x, y, n}; - vector feature(f, f + sizeof(f) / sizeof(*f)); - features.push_back(feature); - if( (cur_count += 1) == count ) - break; - } - } - else if( type == "icf" ) - { - RNG rng; - for( int i = 0; i < count; ++i ) - { - int x = rng.uniform(0, window_size.width - 1); - int y = rng.uniform(0, window_size.height - 1); - int x_to = rng.uniform(x, window_size.width - 1); - int y_to = rng.uniform(y, window_size.height - 1); - int n = rng.uniform(0, channel_count - 1); - int f[] = {x, y, x_to, y_to, n}; - vector feature(f, f + sizeof(f) / sizeof(*f)); - features.push_back(feature); - } - } - else - CV_Error(CV_StsBadArg, "type value is either acf or icf"); - - return features; -} - -void computeChannels(InputArray image, vector& channels) -{ - Mat_ grad; - Mat_ angles; - Mat luv, gray, src; - - if(image.getMat().channels() > 1) - { - src = Mat(image.getMat().rows, image.getMat().cols, CV_32FC3); - image.getMat().convertTo(src, CV_32FC3, 1./255); - - cvtColor(src, gray, CV_RGB2GRAY); - cvtColor(src, luv, CV_RGB2Luv); - } - else - { - src = Mat(image.getMat().rows, image.getMat().cols, CV_32FC1); - image.getMat().convertTo(src, CV_32FC1, 1./255); - src.copyTo(gray); - } - - Mat_ row_der, col_der; - Sobel(gray, row_der, CV_32F, 0, 1); - Sobel(gray, col_der, CV_32F, 1, 0); - - cartToPolar(col_der, row_der, grad, angles, true); - //magnitude(row_der, col_der, grad); - - Mat_ hist = Mat_::zeros(grad.rows, grad.cols); - //const float to_deg = 180 / 3.1415926f; - for (int row = 0; row < grad.rows; ++row) { - for (int col = 0; col < grad.cols; ++col) { - //float angle = atan2(row_der(row, col), col_der(row, col)) * to_deg; - float angle = angles(row, col); - if (angle > 180) - angle -= 180; - if (angle < 0) - angle += 180; - int ind = (int)(angle / 30); - - // If angle == 180, prevent index overflow - if (ind == 6) - ind = 5; - - hist(row, col)[ind] = grad(row, col) * 255; - } - } - - channels.clear(); - - if(image.getMat().channels() > 1) - { - Mat luv_channels[3]; - split(luv, luv_channels); - for( int i = 0; i < 3; ++i ) - channels.push_back(luv_channels[i]); - } - - channels.push_back(grad); - - vector hist_channels; - split(hist, hist_channels); - - for( size_t i = 0; i < hist_channels.size(); ++i ) - channels.push_back(hist_channels[i]); -} - -} /* namespace xobjdetect */ -} /* namespace cv */ diff --git a/modules/xobjdetect/src/cascadeclassifier.h b/modules/xobjdetect/src/cascadeclassifier.h new file mode 100644 index 000000000..b948480dd --- /dev/null +++ b/modules/xobjdetect/src/cascadeclassifier.h @@ -0,0 +1,95 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 _OPENCV_CASCADECLASSIFIER_H_ +#define _OPENCV_CASCADECLASSIFIER_H_ + +#include "precomp.hpp" + +#define CC_CASCADE_FILENAME "cascade.xml" +#define CC_PARAMS_FILENAME "params.xml" + +#define CC_CASCADE_PARAMS "cascadeParams" +#define CC_STAGE_TYPE "stageType" +#define CC_FEATURE_TYPE "featureType" +#define CC_HEIGHT "height" +#define CC_WIDTH "width" + +#define CC_STAGE_NUM "stageNum" +#define CC_STAGES "stages" +#define CC_STAGE_PARAMS "stageParams" + +#define CC_BOOST "BOOST" +#define CC_BOOST_TYPE "boostType" +#define CC_DISCRETE_BOOST "DAB" +#define CC_REAL_BOOST "RAB" +#define CC_LOGIT_BOOST "LB" +#define CC_GENTLE_BOOST "GAB" +#define CC_MINHITRATE "minHitRate" +#define CC_MAXFALSEALARM "maxFalseAlarm" +#define CC_TRIM_RATE "weightTrimRate" +#define CC_MAX_DEPTH "maxDepth" +#define CC_WEAK_COUNT "maxWeakCount" +#define CC_STAGE_THRESHOLD "stageThreshold" +#define CC_WEAK_CLASSIFIERS "weakClassifiers" +#define CC_INTERNAL_NODES "internalNodes" +#define CC_LEAF_VALUES "leafValues" + +#define CC_FEATURES FEATURES +#define CC_FEATURE_PARAMS "featureParams" +#define CC_MAX_CAT_COUNT "maxCatCount" +#define CC_FEATURE_SIZE "featSize" + +#define CC_HAAR "HAAR" +#define CC_MODE "mode" +#define CC_MODE_BASIC "BASIC" +#define CC_MODE_CORE "CORE" +#define CC_MODE_ALL "ALL" +#define CC_RECTS "rects" +#define CC_TILTED "tilted" + +#define CC_LBP "LBP" +#define CC_RECT "rect" + +#endif diff --git a/modules/xobjdetect/src/feature_evaluator.cpp b/modules/xobjdetect/src/feature_evaluator.cpp new file mode 100644 index 000000000..41dfbf5e0 --- /dev/null +++ b/modules/xobjdetect/src/feature_evaluator.cpp @@ -0,0 +1,131 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" + +namespace cv { +namespace xobjdetect { + +float calcNormFactor( const Mat& sum, const Mat& sqSum ) +{ + CV_DbgAssert( sum.cols > 3 && sqSum.rows > 3 ); + Rect normrect( 1, 1, sum.cols - 3, sum.rows - 3 ); + size_t p0, p1, p2, p3; + CV_SUM_OFFSETS( p0, p1, p2, p3, normrect, sum.step1() ) + double area = normrect.width * normrect.height; + const int *sp = sum.ptr(); + int valSum = sp[p0] - sp[p1] - sp[p2] + sp[p3]; + const double *sqp = sqSum.ptr(); + double valSqSum = sqp[p0] - sqp[p1] - sqp[p2] + sqp[p3]; + return (float) sqrt( (double) (area * valSqSum - (double)valSum * valSum) ); +} + +CvParams::CvParams() : name( "params" ) {} +void CvParams::printDefaults() const +{ std::cout << "--" << name << "--" << std::endl; } +void CvParams::printAttrs() const {} +bool CvParams::scanAttr( const std::string, const std::string ) { return false; } + + +//---------------------------- FeatureParams -------------------------------------- + +CvFeatureParams::CvFeatureParams() : maxCatCount( 0 ), featSize( 1 ) +{ + name = CC_FEATURE_PARAMS; +} + +void CvFeatureParams::init( const CvFeatureParams& fp ) +{ + maxCatCount = fp.maxCatCount; + featSize = fp.featSize; +} + +void CvFeatureParams::write( FileStorage &fs ) const +{ + fs << CC_MAX_CAT_COUNT << maxCatCount; + fs << CC_FEATURE_SIZE << featSize; +} + +bool CvFeatureParams::read( const FileNode &node ) +{ + if ( node.empty() ) + return false; + maxCatCount = node[CC_MAX_CAT_COUNT]; + featSize = node[CC_FEATURE_SIZE]; + return ( maxCatCount >= 0 && featSize >= 1 ); +} + +Ptr CvFeatureParams::create() +{ + return Ptr(new CvLBPFeatureParams); +} + +//------------------------------------- FeatureEvaluator --------------------------------------- + +void CvFeatureEvaluator::init(const CvFeatureParams *_featureParams, + int _maxSampleCount, Size _winSize ) +{ + CV_Assert(_maxSampleCount > 0); + featureParams = (CvFeatureParams *)_featureParams; + winSize = _winSize; + numFeatures = 0; + cls.create( (int)_maxSampleCount, 1, CV_32FC1 ); + generateFeatures(); +} + +void CvFeatureEvaluator::setImage(const Mat &, uchar clsLabel, int idx, const std::vector&) +{ + //CV_Assert(img.cols == winSize.width); + //CV_Assert(img.rows == winSize.height); + CV_Assert(idx < cls.rows); + cls.ptr(idx)[0] = clsLabel; +} + +Ptr CvFeatureEvaluator::create() +{ + return Ptr(new CvLBPEvaluator); +} + +} +} diff --git a/modules/xobjdetect/src/feature_evaluator.hpp b/modules/xobjdetect/src/feature_evaluator.hpp new file mode 100644 index 000000000..2b5920233 --- /dev/null +++ b/modules/xobjdetect/src/feature_evaluator.hpp @@ -0,0 +1,151 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 _OPENCV_FEATURES_H_ +#define _OPENCV_FEATURES_H_ + +#include + +#define FEATURES "features" + +#define CV_SUM_OFFSETS( p0, p1, p2, p3, rect, step ) \ + /* (x, y) */ \ + (p0) = (rect).x + (step) * (rect).y; \ + /* (x + w, y) */ \ + (p1) = (rect).x + (rect).width + (step) * (rect).y; \ + /* (x + w, y) */ \ + (p2) = (rect).x + (step) * ((rect).y + (rect).height); \ + /* (x + w, y + h) */ \ + (p3) = (rect).x + (rect).width + (step) * ((rect).y + (rect).height); + +#define CV_TILTED_OFFSETS( p0, p1, p2, p3, rect, step ) \ + /* (x, y) */ \ + (p0) = (rect).x + (step) * (rect).y; \ + /* (x - h, y + h) */ \ + (p1) = (rect).x - (rect).height + (step) * ((rect).y + (rect).height);\ + /* (x + w, y + w) */ \ + (p2) = (rect).x + (rect).width + (step) * ((rect).y + (rect).width); \ + /* (x + w - h, y + w + h) */ \ + (p3) = (rect).x + (rect).width - (rect).height \ + + (step) * ((rect).y + (rect).width + (rect).height); + +namespace cv { +namespace xobjdetect { + +float calcNormFactor( const cv::Mat& sum, const cv::Mat& sqSum ); + +template +void _writeFeatures( const std::vector features, cv::FileStorage &fs, const cv::Mat& featureMap ) +{ + fs << FEATURES << "["; + const cv::Mat_& featureMap_ = (const cv::Mat_&)featureMap; + for ( int fi = 0; fi < featureMap.cols; fi++ ) + if ( featureMap_(0, fi) >= 0 ) + { + fs << "{"; + features[fi].write( fs ); + fs << "}"; + } + fs << "]"; +} + +class CvParams +{ +public: + CvParams(); + virtual ~CvParams() {} + // from|to file + virtual void write( cv::FileStorage &fs ) const = 0; + virtual bool read( const cv::FileNode &node ) = 0; + // from|to screen + virtual void printDefaults() const; + virtual void printAttrs() const; + virtual bool scanAttr( const std::string prmName, const std::string val ); + std::string name; +}; + +class CvFeatureParams : public CvParams +{ +public: + enum { HAAR = 0, LBP = 1, HOG = 2 }; + CvFeatureParams(); + virtual void init( const CvFeatureParams& fp ); + virtual void write( cv::FileStorage &fs ) const; + virtual bool read( const cv::FileNode &node ); + static cv::Ptr create(); + int maxCatCount; // 0 in case of numerical features + int featSize; // 1 in case of simple features (HAAR, LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features +}; + +class CvFeatureEvaluator +{ +public: + virtual ~CvFeatureEvaluator() {} + virtual void init(const CvFeatureParams *_featureParams, + int _maxSampleCount, cv::Size _winSize ); + virtual void setImage(const cv::Mat& img, uchar clsLabel, int idx, const std::vector &feature_ind); + virtual void setWindow(const cv::Point& p) = 0; + virtual void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const = 0; + virtual float operator()(int featureIdx) = 0; + static cv::Ptr create(); + + int getNumFeatures() const { return numFeatures; } + int getMaxCatCount() const { return featureParams->maxCatCount; } + int getFeatureSize() const { return featureParams->featSize; } + const cv::Mat& getCls() const { return cls; } + float getCls(int si) const { return cls.at(si, 0); } +protected: + virtual void generateFeatures() = 0; + + int npos, nneg; + int numFeatures; + cv::Size winSize; + CvFeatureParams *featureParams; + cv::Mat cls; +}; + +} +} + +#endif diff --git a/modules/xobjdetect/src/icfdetector.cpp b/modules/xobjdetect/src/icfdetector.cpp deleted file mode 100644 index aa7829233..000000000 --- a/modules/xobjdetect/src/icfdetector.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -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 names of the copyright holders nor the names of the 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 copyright holders 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 -using std::ostringstream; - -#include -using std::setfill; -using std::setw; - -#include -using std::cout; -using std::endl; - -#include "precomp.hpp" - -using std::vector; -using std::string; - -using std::min; -using std::max; - - -namespace cv -{ - -namespace xobjdetect -{ - - -void ICFDetector::train(const vector& pos_filenames, - const vector& bg_filenames, - ICFDetectorParams params) -{ - - int color; - if(params.is_grayscale == false) - color = IMREAD_COLOR; - else - color = IMREAD_GRAYSCALE; - - model_n_rows_ = params.model_n_rows; - model_n_cols_ = params.model_n_cols; - ftype_ = params.features_type; - - Size model_size(params.model_n_cols, params.model_n_rows); - - vector samples; /* positive samples + negative samples */ - Mat sample, resized_sample; - int pos_count = 0; - - for( size_t i = 0; i < pos_filenames.size(); ++i, ++pos_count ) - { - cout << setw(6) << (i + 1) << "/" << pos_filenames.size() << "\r"; - Mat img = imread(pos_filenames[i], color); - resize(img, resized_sample, model_size); - samples.push_back(resized_sample.clone()); - } - cout << "\n"; - - int neg_count = 0; - RNG rng; - for( size_t i = 0; i < bg_filenames.size(); ++i ) - { - cout << setw(6) << (i + 1) << "/" << bg_filenames.size() << "\r"; - Mat img = imread(bg_filenames[i], color); - for( int j = 0; j < params.bg_per_image; ++j, ++neg_count) - { - Rect r; - r.x = rng.uniform(0, img.cols-model_size.width); - r.width = model_size.width; - r.y = rng.uniform(0, img.rows-model_size.height); - r.height = model_size.height; - sample = img.colRange(r.x, r.x + r.width).rowRange(r.y, r.y + r.height); - samples.push_back(sample.clone()); - } - } - cout << "\n"; - - Mat_ labels(1, pos_count + neg_count); - for( int i = 0; i < pos_count; ++i) - labels(0, i) = 1; - for( int i = pos_count; i < pos_count + neg_count; ++i ) - labels(0, i) = -1; - - - vector > features; - if(params.is_grayscale == false) - features = generateFeatures(model_size, params.features_type, params.feature_count, 10); - else - features = generateFeatures(model_size, params.features_type, params.feature_count, 7); - - Ptr evaluator = createFeatureEvaluator(features, params.features_type); - - - Mat_ data = Mat_::zeros((int)features.size(), (int)samples.size()); - Mat_ feature_col(1, (int)samples.size()); - - vector channels; - for( int i = 0; i < (int)samples.size(); ++i ) - { - cout << setw(6) << i << "/" << samples.size() << "\r"; - computeChannels(samples[i], channels); - evaluator->setChannels(channels); - //evaluator->assertChannels(); - evaluator->evaluateAll(feature_col); - - CV_Assert(feature_col.cols == (int)features.size()); - - for( int j = 0; j < feature_col.cols; ++j ) - data(j, i) = feature_col(0, j); - } - cout << "\n"; - samples.clear(); - - WaldBoostParams wparams; - wparams.weak_count = params.weak_count; - wparams.alpha = params.alpha; - - waldboost_ = createWaldBoost(wparams); - vector indices = waldboost_->train(data, labels, params.use_fast_log); - cout << "indices: "; - for( size_t i = 0; i < indices.size(); ++i ) - cout << indices[i] << " "; - cout << endl; - - features_.clear(); - for( size_t i = 0; i < indices.size(); ++i ) - features_.push_back(features[indices[i]]); -} - -void ICFDetector::write(FileStorage& fs) const -{ - fs << "{"; - fs << "model_n_rows" << model_n_rows_; - fs << "model_n_cols" << model_n_cols_; - fs << "ftype" << String(ftype_.c_str()); - fs << "waldboost"; - waldboost_->write(fs); - fs << "features" << "["; - for( size_t i = 0; i < features_.size(); ++i ) - { - fs << features_[i]; - } - fs << "]"; - fs << "}"; -} - -void ICFDetector::read(const FileNode& node) -{ - waldboost_ = Ptr(createWaldBoost(WaldBoostParams())); - String f_temp; - node["model_n_rows"] >> model_n_rows_; - node["model_n_cols"] >> model_n_cols_; - f_temp = (String)node["ftype"]; - this->ftype_ = (string)f_temp.c_str(); - waldboost_->read(node["waldboost"]); - FileNode features = node["features"]; - features_.clear(); - vector p; - for( FileNodeIterator n = features.begin(); n != features.end(); ++n ) - { - (*n) >> p; - features_.push_back(p); - } -} - -void ICFDetector::detect(const Mat& img, vector& objects, - float scaleFactor, Size minSize, Size maxSize, float threshold, int slidingStep, std::vector& values) -{ - - - float scale_from = min(model_n_cols_ / (float)maxSize.width, - model_n_rows_ / (float)maxSize.height); - float scale_to = max(model_n_cols_ / (float)minSize.width, - model_n_rows_ / (float)minSize.height); - objects.clear(); - Ptr evaluator = createFeatureEvaluator(features_, ftype_); - Mat rescaled_image; - vector channels; - - for( float scale = scale_from; scale < scale_to + 0.001; scale *= scaleFactor ) - { - int new_width = int(img.cols * scale); - new_width -= new_width % 4; - int new_height = int(img.rows * scale); - new_height -= new_height % 4; - - resize(img, rescaled_image, Size(new_width, new_height)); - computeChannels(rescaled_image, channels); - evaluator->setChannels(channels); - for( int row = 0; row <= rescaled_image.rows - model_n_rows_; row += slidingStep) - { - for( int col = 0; col <= rescaled_image.cols - model_n_cols_; - col += slidingStep ) - { - evaluator->setPosition(Size(row, col)); - float value = waldboost_->predict(evaluator); - if( value > threshold ) - { - values.push_back(value); - int x = (int)(col / scale); - int y = (int)(row / scale); - int width = (int)(model_n_cols_ / scale); - int height = (int)(model_n_rows_ / scale); - objects.push_back(Rect(x, y, width, height)); - } - } - } - - } - -} - -void ICFDetector::detect(const Mat& img, vector& objects, - float minScaleFactor, float maxScaleFactor, float factorStep, float threshold, int slidingStep, std::vector& values) -{ - - if(factorStep <= 0) - { - CV_Error_(CV_StsBadArg, ("factorStep must be > 0")); - } - - objects.clear(); - Ptr evaluator = createFeatureEvaluator(features_, ftype_); - Mat rescaled_image; - vector channels; - - for( float scale = minScaleFactor; scale < maxScaleFactor + 0.001; scale += factorStep ) - { - if(scale < 1.0) - resize(img, rescaled_image, Size(),scale, scale, INTER_AREA); - else if (scale > 1.0) - resize(img, rescaled_image, Size(),scale, scale, INTER_CUBIC); - else //scale == 1.0 - img.copyTo(rescaled_image); - - computeChannels(rescaled_image, channels); - evaluator->setChannels(channels); - for( int row = 0; row <= rescaled_image.rows - model_n_rows_; row += slidingStep) - { - for( int col = 0; col <= rescaled_image.cols - model_n_cols_; - col += slidingStep ) - { - evaluator->setPosition(Size(row, col)); - float value = waldboost_->predict(evaluator); - if( value > threshold ) - { - values.push_back(value); - int x = (int)(col / scale); - int y = (int)(row / scale); - int width = (int)(model_n_cols_ / scale); - int height = (int)(model_n_rows_ / scale); - objects.push_back(Rect(x, y, width, height)); - } - } - } - - } - -} - -void write(FileStorage& fs, String&, const ICFDetector& detector) -{ - detector.write(fs); -} - -void read(const FileNode& node, ICFDetector& d, - const ICFDetector& default_value) -{ - if( node.empty() ) - d = default_value; - else - d.read(node); -} - -} /* namespace xobjdetect */ -} /* namespace cv */ diff --git a/modules/xobjdetect/src/lbpfeatures.cpp b/modules/xobjdetect/src/lbpfeatures.cpp new file mode 100644 index 000000000..3f67ea88a --- /dev/null +++ b/modules/xobjdetect/src/lbpfeatures.cpp @@ -0,0 +1,128 @@ + +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" + +namespace cv { +namespace xobjdetect { + +CvLBPFeatureParams::CvLBPFeatureParams() +{ + maxCatCount = 256; + name = LBPF_NAME; +} + +void CvLBPEvaluator::init(const CvFeatureParams *_featureParams, int _maxSampleCount, Size _winSize) +{ + CV_Assert( _maxSampleCount > 0); + sum.create((int)_maxSampleCount, (_winSize.width + 1) * (_winSize.height + 1), CV_32SC1); + CvFeatureEvaluator::init( _featureParams, _maxSampleCount, _winSize ); +} + +void CvLBPEvaluator::setImage(const Mat &img, uchar clsLabel, int idx, + const std::vector &feature_ind) +{ + CV_DbgAssert( !sum.empty() ); + CvFeatureEvaluator::setImage( img, clsLabel, idx, feature_ind ); + integral( img, sum ); + cur_sum = sum; + offset_ = int(sum.ptr(1) - sum.ptr()); + for (size_t i = 0; i < feature_ind.size(); ++i) { + features[feature_ind[i]].calcPoints(offset_); + } +} + +void CvLBPEvaluator::writeFeatures( FileStorage &fs, const Mat& featureMap ) const +{ + _writeFeatures( features, fs, featureMap ); +} + +void CvLBPEvaluator::generateFeatures() +{ + int offset = winSize.width + 1; + for( int x = 0; x < winSize.width; x++ ) + for( int y = 0; y < winSize.height; y++ ) + for( int w = 1; w <= winSize.width / 3; w++ ) + for( int h = 1; h <= winSize.height / 3; h++ ) + if ( (x+3*w <= winSize.width) && (y+3*h <= winSize.height) ) + features.push_back( Feature(offset, x, y, w, h ) ); + numFeatures = (int)features.size(); +} + +CvLBPEvaluator::Feature::Feature() +{ + rect = cvRect(0, 0, 0, 0); +} + +CvLBPEvaluator::Feature::Feature( int offset, int x, int y, int _blockWidth, int _blockHeight ) +{ + x_ = x; + y_ = y; + block_w_ = _blockWidth; + block_h_ = _blockHeight; + offset_ = offset; + calcPoints(offset); +} + +void CvLBPEvaluator::Feature::calcPoints(int offset) +{ + Rect tr = rect = cvRect(x_, y_, block_w_, block_h_); + CV_SUM_OFFSETS( p[0], p[1], p[4], p[5], tr, offset ) + tr.x += 2*rect.width; + CV_SUM_OFFSETS( p[2], p[3], p[6], p[7], tr, offset ) + tr.y +=2*rect.height; + CV_SUM_OFFSETS( p[10], p[11], p[14], p[15], tr, offset ) + tr.x -= 2*rect.width; + CV_SUM_OFFSETS( p[8], p[9], p[12], p[13], tr, offset ) + offset_ = offset; +} + +void CvLBPEvaluator::Feature::write(FileStorage &fs) const +{ + fs << CC_RECT << "[:" << rect.x << rect.y << rect.width << rect.height << "]"; +} + +} +} diff --git a/modules/xobjdetect/src/lbpfeatures.h b/modules/xobjdetect/src/lbpfeatures.h new file mode 100644 index 000000000..0fc564a8b --- /dev/null +++ b/modules/xobjdetect/src/lbpfeatures.h @@ -0,0 +1,116 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 _OPENCV_LBPFEATURES_H_ +#define _OPENCV_LBPFEATURES_H_ + +#include "precomp.hpp" + + +#define LBPF_NAME "lbpFeatureParams" + +namespace cv { +namespace xobjdetect { + +struct CvLBPFeatureParams : CvFeatureParams +{ + CvLBPFeatureParams(); + +}; + +class CvLBPEvaluator : public CvFeatureEvaluator +{ +public: + virtual ~CvLBPEvaluator() {} + virtual void init(const CvFeatureParams *_featureParams, + int _maxSampleCount, cv::Size _winSize ); + virtual void setImage(const cv::Mat& img, uchar clsLabel, int idx, const std::vector &feature_ind); + virtual void setWindow(const cv::Point& p) + { cur_sum = sum.rowRange(p.y, p.y + winSize.height).colRange(p.x, p.x + winSize.width); } + virtual float operator()(int featureIdx) + { return (float)features[featureIdx].calc( cur_sum ); } + virtual void writeFeatures( cv::FileStorage &fs, const cv::Mat& featureMap ) const; +protected: + virtual void generateFeatures(); + + class Feature + { + public: + Feature(); + Feature( int offset, int x, int y, int _block_w, int _block_h ); + uchar calc( const cv::Mat& _sum ); + void write( cv::FileStorage &fs ) const; + + cv::Rect rect; + int p[16]; + + int x_, y_, block_w_, block_h_, offset_; + void calcPoints(int offset); + }; + std::vector features; + + cv::Mat sum, cur_sum; + int offset_; +}; + +inline uchar CvLBPEvaluator::Feature::calc(const cv::Mat &_sum) +{ + const int* psum = _sum.ptr(); + + int cval = psum[p[5]] - psum[p[6]] - psum[p[9]] + psum[p[10]]; + + return (uchar)((psum[p[0]] - psum[p[1]] - psum[p[4]] + psum[p[5]] >= cval ? 128 : 0) | // 0 + (psum[p[1]] - psum[p[2]] - psum[p[5]] + psum[p[6]] >= cval ? 64 : 0) | // 1 + (psum[p[2]] - psum[p[3]] - psum[p[6]] + psum[p[7]] >= cval ? 32 : 0) | // 2 + (psum[p[6]] - psum[p[7]] - psum[p[10]] + psum[p[11]] >= cval ? 16 : 0) | // 5 + (psum[p[10]] - psum[p[11]] - psum[p[14]] + psum[p[15]] >= cval ? 8 : 0) | // 8 + (psum[p[9]] - psum[p[10]] - psum[p[13]] + psum[p[14]] >= cval ? 4 : 0) | // 7 + (psum[p[8]] - psum[p[9]] - psum[p[12]] + psum[p[13]] >= cval ? 2 : 0) | // 6 + (psum[p[4]] - psum[p[5]] - psum[p[8]] + psum[p[9]] >= cval ? 1 : 0)); // 3 +} + +} +} + +#endif diff --git a/modules/xobjdetect/src/precomp.hpp b/modules/xobjdetect/src/precomp.hpp index 811329940..a83f78715 100644 --- a/modules/xobjdetect/src/precomp.hpp +++ b/modules/xobjdetect/src/precomp.hpp @@ -1,7 +1,6 @@ /* - -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, copy or use the software. @@ -9,7 +8,12 @@ copy or use the software. For Open Source Computer Vision Library (3-clause BSD License) -Copyright (C) 2013, OpenCV Foundation, all rights reserved. +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. Third party copyrights are property of their respective owners. Redistribution and use in source and binary forms, with or without modification, @@ -28,31 +32,50 @@ are permitted provided that the following conditions are met: 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 copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages +warranties of merchantability and fitness for a particular purpose are disclaimed. +In no event shall copyright holders 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 __OPENCV_XOBJDETECT_PRECOMP_HPP__ #define __OPENCV_XOBJDETECT_PRECOMP_HPP__ #include -#include #include #include #include +#include +#include + #include +#include + +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include + +#include "cascadeclassifier.h" +#include "feature_evaluator.hpp" +#include "lbpfeatures.h" +#include "waldboost.hpp" +#include "wbdetector.hpp" +#include #endif /* __OPENCV_XOBJDETECT_PRECOMP_HPP__ */ diff --git a/modules/xobjdetect/src/stump.cpp b/modules/xobjdetect/src/stump.cpp deleted file mode 100644 index 221445a29..000000000 --- a/modules/xobjdetect/src/stump.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, -copy or use the software. - - - License Agreement - For Open Source Computer Vision Library - (3-clause BSD License) - -Copyright (C) 2013, OpenCV Foundation, all rights reserved. -Third party copyrights are property of their respective owners. - -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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" - -namespace cv -{ -namespace xobjdetect -{ - -/* Cumulative sum by rows */ -static void cumsum(const Mat_& src, Mat_ dst) -{ - CV_Assert(src.cols > 0); - - for( int row = 0; row < src.rows; ++row ) - { - dst(row, 0) = src(row, 0); - for( int col = 1; col < src.cols; ++col ) - { - dst(row, col) = dst(row, col - 1) + src(row, col); - } - } -} - -//fast log implementation. A bit less accurate but ~5x faster -inline float fast_log2 (float val) -{ - int * const exp_ptr = reinterpret_cast (&val); - int x = *exp_ptr; - const int log_2 = ((x >> 23) & 255) - 128; - x &= ~(255 << 23); - x += 127 << 23; - *exp_ptr = x; - - val = ((-1.0f/3) * val + 2) * val - 2.0f/3; // (1) - - return (val + log_2); -} - -inline float fast_log (const float &val) -{ - return (fast_log2 (val) * 0.69314718f); -} - -int Stump::train(const Mat& data, const Mat& labels, const Mat& weights, const std::vector& visited_features, bool use_fast_log) -{ - CV_Assert(labels.rows == 1 && labels.cols == data.cols); - CV_Assert(weights.rows == 1 && weights.cols == data.cols); - CV_Assert(data.cols > 1); - /* Assert that data and labels have int type */ - /* Assert that weights have float type */ - - Mat_ d = Mat_::zeros(1, data.cols); - const Mat_& l = labels; - const Mat_& w = weights; - - Mat_ indices(1, l.cols); - - Mat_ sorted_d(1, data.cols); - Mat_ sorted_l(1, l.cols); - Mat_ sorted_w(1, w.cols); - - - Mat_ pos_c_w = Mat_::zeros(1, w.cols); - Mat_ neg_c_w = Mat_::zeros(1, w.cols); - - - float min_err = FLT_MAX; - int min_row = -1; - int min_thr = -1; - int min_pol = -1; - float min_pos = 1; - float min_neg = -1; - float eps = 1.0f / (4 * l.cols); - - /* For every feature */ - for( int row = 0; row < data.rows; ++row ) - { - if(std::find(visited_features.begin(), visited_features.end(), row) != visited_features.end()) { - //feature discarded - continue; - } - data.row(row).copyTo(d.row(0)); - - sortIdx(d, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); - - for( int col = 0; col < indices.cols; ++col ) - { - int ind = indices(0, col); - sorted_d(0, col) = d(0, ind); - sorted_l(0, col) = l(0, ind); - sorted_w(0, col) = w(0, ind); - } - - Mat_ pos_w = Mat_::zeros(1, w.cols); - Mat_ neg_w = Mat_::zeros(1, w.cols); - for( int col = 0; col < d.cols; ++col ) - { - float weight = sorted_w(0, col); - if( sorted_l(0, col) == +1) - pos_w(0, col) = weight; - else - neg_w(0, col) = weight; - } - - cumsum(pos_w, pos_c_w); - cumsum(neg_w, neg_c_w); - - float pos_total_w = pos_c_w(0, w.cols - 1); - float neg_total_w = neg_c_w(0, w.cols - 1); - - for( int col = 0; col < w.cols - 1; ++col ) - { - float err, h_pos, h_neg; - float pos_wrong, pos_right; - float neg_wrong, neg_right; - - /* Direct polarity */ - - pos_wrong = pos_c_w(0, col); - pos_right = pos_total_w - pos_wrong; - - neg_right = neg_c_w(0, col); - neg_wrong = neg_total_w - neg_right; - - err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); - - if(use_fast_log) - { - h_pos = .5f * fast_log((pos_right + eps) / (pos_wrong + eps)); - h_neg = .5f * fast_log((neg_wrong + eps) / (neg_right + eps)); - } - else - { - h_pos = .5f * log((pos_right + eps) / (pos_wrong + eps)); - h_neg = .5f * log((neg_wrong + eps) / (neg_right + eps)); - } - - if( err < min_err ) - { - min_err = err; - min_row = row; - min_thr = (sorted_d(0, col) + sorted_d(0, col + 1)) / 2; - min_pol = +1; - min_pos = h_pos; - min_neg = h_neg; - } - - /* Opposite polarity */ - - swap(pos_right, pos_wrong); - swap(neg_right, neg_wrong); - - err = sqrt(pos_right * neg_wrong) + sqrt(pos_wrong * neg_right); - - if( err < min_err ) - { - min_err = err; - min_row = row; - min_thr = (sorted_d(0, col) + sorted_d(0, col + 1)) / 2; - min_pol = -1; - min_pos = -h_pos; - min_neg = -h_neg; - } - - } - } - - threshold_ = min_thr; - polarity_ = min_pol; - pos_value_ = min_pos; - neg_value_ = min_neg; - - return min_row; -} - -float Stump::predict(int value) const -{ - return polarity_ * (value - threshold_) > 0 ? pos_value_ : neg_value_; -} - - -void read(const FileNode& node, Stump& s, const Stump& default_value) -{ - if( node.empty() ) - s = default_value; - else - s.read(node); -} - -void write(FileStorage& fs, String&, const Stump& s) -{ - s.write(fs); -} - -} /* namespace xobjdetect */ -} /* namespace cv */ diff --git a/modules/xobjdetect/src/waldboost.cpp b/modules/xobjdetect/src/waldboost.cpp index 8866ab260..8c1394621 100644 --- a/modules/xobjdetect/src/waldboost.cpp +++ b/modules/xobjdetect/src/waldboost.cpp @@ -1,7 +1,6 @@ /* - -By downloading, copying, installing or using the software you agree to this -license. If you do not agree to this license, do not download, install, +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, copy or use the software. @@ -9,7 +8,12 @@ copy or use the software. For Open Source Computer Vision Library (3-clause BSD License) -Copyright (C) 2013, OpenCV Foundation, all rights reserved. +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. Third party copyrights are property of their respective owners. Redistribution and use in source and binary forms, with or without modification, @@ -28,360 +32,416 @@ are permitted provided that the following conditions are met: 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 copyright holders or contributors be liable for -any direct, indirect, incidental, special, exemplary, or consequential damages +warranties of merchantability and fitness for a particular purpose are disclaimed. +In no event shall copyright holders 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 "precomp.hpp" -using std::swap; - -using std::vector; - -#include -using std::cout; -using std::endl; - - - - - +namespace cv { +namespace xobjdetect { -namespace cv +static void compute_cdf(const Mat1b& data, + const Mat1f& weights, + Mat1f& cdf) { + for (int i = 0; i < cdf.cols; ++i) + cdf(0, i) = 0; -namespace xobjdetect -{ - //sort in-place of columns of the input matrix - void sort_columns_without_copy(Mat& m, Mat indices) - { - - if(indices.data == 0) - sortIdx(m, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); - - Mat indices_of_indices; - sortIdx(indices, indices_of_indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); - - std::vector visited; - for(int c = 0; c(0,ind_v))).copyTo(column); - } - else - { - temp_column.copyTo(column); - } - - - if(indices_of_indices.at(0,next) != next) //value is in the right place - { - //store the next value to change - (m.col(indices_of_indices.at(0,next))).copyTo(temp_column); - //insert the value to change at the right place - column.copyTo(m.col(indices_of_indices.at(0,next))); - - //find the index of the next value to change - next = indices_of_indices.at(0,next); - //if the idenx is not visited yet - if(visited[next] == false) - { - //then mark it as visited, it will be computed in the next round - visited[next] = true; - } - else - { - //find first non visited index - int i = 0; - while(i<(int)visited.size() && visited[i] == true) - { - i++; - } - ind_v = i; - next = i; - temp_column = Mat(); - - } - } - else // value is already at the right place - { - visited[next] = true; - int i = 0; - while(i<(int)visited.size() && visited[i] == true) - { - i++; - } - next = i; - temp_column = Mat(); - ind_v = i; - } - - + for (int i = 0; i < weights.cols; ++i) { + cdf(0, data(0, i)) += weights(0, i); } - - - } -class WaldBoostImpl : public WaldBoost + for (int i = 1; i < cdf.cols; ++i) { + cdf(0, i) += cdf(0, i - 1); + } +} + +static void compute_min_step(const Mat &data_pos, const Mat &data_neg, size_t n_bins, + Mat &data_min, Mat &data_step) { -public: - /* Initialize WaldBoost cascade with default of specified parameters */ - WaldBoostImpl(const WaldBoostParams& params): - params_(params) - {} + // Check that quantized data will fit in unsigned char + assert(n_bins <= 256); - virtual std::vector train(Mat& data, - const Mat& labels, bool use_fast_log=false); + assert(data_pos.rows == data_neg.rows); - virtual float predict( - const Ptr& feature_evaluator) const; + Mat reduced_pos, reduced_neg; - virtual void write(FileStorage& fs) const; + reduce(data_pos, reduced_pos, 1, CV_REDUCE_MIN); + reduce(data_neg, reduced_neg, 1, CV_REDUCE_MIN); + min(reduced_pos, reduced_neg, data_min); + data_min -= 0.01; - virtual void read(const FileNode& node); + Mat data_max; + reduce(data_pos, reduced_pos, 1, CV_REDUCE_MAX); + reduce(data_neg, reduced_neg, 1, CV_REDUCE_MAX); + max(reduced_pos, reduced_neg, data_max); + data_max += 0.01; -private: - /* Parameters for cascade training */ - WaldBoostParams params_; - /* Stumps in cascade */ - std::vector stumps_; - /* Rejection thresholds for linear combination at every stump evaluation */ - std::vector thresholds_; -}; + data_step = (data_max - data_min) / (double)(n_bins - 1); +} -static int count(const Mat_ &m, int elem) +static void quantize_data(Mat &data, Mat1f &data_min, Mat1f &data_step) { - int res = 0; - for( int row = 0; row < m.rows; ++row ) - for( int col = 0; col < m.cols; ++col ) - if( m(row, col) == elem) - res += 1; - return res; +//#pragma omp parallel for + for (int col = 0; col < data.cols; ++col) { + data.col(col) -= data_min; + data.col(col) /= data_step; + } + data.convertTo(data, CV_8U); } -void WaldBoostImpl::read(const FileNode& node) +WaldBoost::WaldBoost(int weak_count): + weak_count_(weak_count), + thresholds_(), + alphas_(), + feature_indices_(), + polarities_(), + cascade_thresholds_() {} + +WaldBoost::WaldBoost(): + weak_count_(), + thresholds_(), + alphas_(), + feature_indices_(), + polarities_(), + cascade_thresholds_() {} + +std::vector WaldBoost::get_feature_indices() { - FileNode params = node["waldboost_params"]; - params_.weak_count = (int)(params["weak_count"]); - params_.alpha = (float)(params["alpha"]); - - FileNode stumps = node["waldboost_stumps"]; - stumps_.clear(); - for( FileNodeIterator n = stumps.begin(); n != stumps.end(); ++n ) - { - Stump s; - *n >> s; - stumps_.push_back(s); - } + return feature_indices_; +} - FileNode thresholds = node["waldboost_thresholds"]; - thresholds_.clear(); - for( FileNodeIterator n = thresholds.begin(); n != thresholds.end(); ++n ) - { - float t; - *n >> t; - thresholds_.push_back(t); +void WaldBoost::detect(Ptr eval, + const Mat& img, const std::vector& scales, + std::vector& bboxes, Mat1f& confidences) +{ + bboxes.clear(); + confidences.release(); + + Mat resized_img; + int step = 4; + float h; + for (size_t i = 0; i < scales.size(); ++i) { + float scale = scales[i]; + resize(img, resized_img, Size(), scale, scale); + eval->setImage(resized_img, 0, 0, feature_indices_); + int n_rows = (int)(24 / scale); + int n_cols = (int)(24 / scale); + for (int r = 0; r + 24 < resized_img.rows; r += step) { + for (int c = 0; c + 24 < resized_img.cols; c += step) { + //eval->setImage(resized_img(Rect(c, r, 24, 24)), 0, 0); + eval->setWindow(Point(c, r)); + if (predict(eval, &h) == +1) { + int row = (int)(r / scale); + int col = (int)(c / scale); + bboxes.push_back(Rect(col, row, n_cols, n_rows)); + confidences.push_back(h); + } + } + } } + groupRectangles(bboxes, 3, 0.7); } -void WaldBoostImpl::write(FileStorage& fs) const +void WaldBoost::detect(Ptr eval, + const Mat& img, const std::vector& scales, + std::vector& bboxes, std::vector& confidences) { - fs << "{"; - fs << "waldboost_params" << "{" - << "weak_count" << params_.weak_count - << "alpha" << params_.alpha - << "}"; - - fs << "waldboost_stumps" << "["; - for( size_t i = 0; i < stumps_.size(); ++i ) - fs << stumps_[i]; - fs << "]"; - - fs << "waldboost_thresholds" << "["; - for( size_t i = 0; i < thresholds_.size(); ++i ) - fs << thresholds_[i]; - fs << "]"; - fs << "}"; - + bboxes.clear(); + confidences.clear(); + + Mat resized_img; + int step = 4; + float h; + for (size_t i = 0; i < scales.size(); ++i) { + float scale = scales[i]; + resize(img, resized_img, Size(), scale, scale); + eval->setImage(resized_img, 0, 0, feature_indices_); + int n_rows = (int)(24 / scale); + int n_cols = (int)(24 / scale); + for (int r = 0; r + 24 < resized_img.rows; r += step) { + for (int c = 0; c + 24 < resized_img.cols; c += step) { + eval->setWindow(Point(c, r)); + if (predict(eval, &h) == +1) { + int row = (int)(r / scale); + int col = (int)(c / scale); + bboxes.push_back(Rect(col, row, n_cols, n_rows)); + confidences.push_back(h); + } + } + } + } + std::vector levels(bboxes.size(), 0); + groupRectangles(bboxes, levels, confidences, 3, 0.7); } -vector WaldBoostImpl::train(Mat& data, const Mat& labels_, bool use_fast_log) +void WaldBoost::fit(Mat& data_pos, Mat& data_neg) { - CV_Assert(labels_.rows == 1 && labels_.cols == data.cols); - CV_Assert(data.rows >= params_.weak_count); - - Mat labels; - labels_.copyTo(labels); - - bool null_data = true; - for( int row = 0; row < data.rows; ++row ) - { - for( int col = 0; col < data.cols; ++col ) - if( data.at(row, col) ) - null_data = false; - } - CV_Assert(!null_data); - - int pos_count = count(labels, +1); - int neg_count = count(labels, -1); - - Mat_ weights(labels.rows, labels.cols); - float pos_weight = 1.0f / (2 * pos_count); - float neg_weight = 1.0f / (2 * neg_count); - for( int col = 0; col < weights.cols; ++col ) - { - if( labels.at(0, col) == +1 ) - weights.at(0, col) = pos_weight; - else - weights.at(0, col) = neg_weight; + // data_pos: F x N_pos + // data_neg: F x N_neg + // every feature corresponds to row + // every sample corresponds to column + assert(data_pos.rows >= weak_count_); + assert(data_pos.rows == data_neg.rows); + + std::vector feature_ignore; + for (int i = 0; i < data_pos.rows; ++i) { + feature_ignore.push_back(false); } - vector feature_indices_pool; - for( int ind = 0; ind < data.rows; ++ind ) - feature_indices_pool.push_back(ind); + Mat1f pos_weights(1, data_pos.cols, 1.0f / (2 * data_pos.cols)); + Mat1f neg_weights(1, data_neg.cols, 1.0f / (2 * data_neg.cols)); + Mat1f pos_trace(1, data_pos.cols, 0.0f); + Mat1f neg_trace(1, data_neg.cols, 0.0f); - vector feature_indices; - vector visited_features; - Mat_ trace = Mat_::zeros(labels.rows, labels.cols); - stumps_.clear(); - thresholds_.clear(); - for( int i = 0; i < params_.weak_count; ++i) - { - Stump s; - int feature_ind = s.train(data, labels, weights, visited_features, use_fast_log); - stumps_.push_back(s); - int ind = feature_indices_pool[feature_ind]; - //we don't need to erase the feature index anymore, because we ignore them if already visited - //feature_indices_pool.erase(feature_indices_pool.begin() + feature_ind); - feature_indices.push_back(ind); - - // Recompute weights - for( int col = 0; col < weights.cols; ++col ) - { - float h = s.predict(data.at(feature_ind, col)); - trace(0, col) += h; - int label = labels.at(0, col); - weights.at(0, col) *= exp(-label * h); - } + bool quantize = false; + if (data_pos.type() != CV_8U) { + std::cerr << "quantize" << std::endl; + quantize = true; + } - // set to zero row for feature in data - for(int jc = 0; jc(feature_ind, jc) = 0; - } - visited_features.push_back(feature_ind); + Mat1f data_min, data_step; + int n_bins = 256; + if (quantize) { + compute_min_step(data_pos, data_neg, n_bins, data_min, data_step); + quantize_data(data_pos, data_min, data_step); + quantize_data(data_neg, data_min, data_step); + } + std::cerr << "pos=" << data_pos.cols << " neg=" << data_neg.cols << std::endl; + for (int i = 0; i < weak_count_; ++i) { + // Train weak learner with lowest error using weights + double min_err = DBL_MAX; + int min_feature_ind = -1; + int min_polarity = 0; + int threshold_q = 0; + float min_threshold = 0; +//#pragma omp parallel for + for (int feat_i = 0; feat_i < data_pos.rows; ++feat_i) { + if (feature_ignore[feat_i]) + continue; + + // Construct cdf + Mat1f pos_cdf(1, n_bins), neg_cdf(1, n_bins); + compute_cdf(data_pos.row(feat_i), pos_weights, pos_cdf); + compute_cdf(data_neg.row(feat_i), neg_weights, neg_cdf); + + float neg_total = (float)sum(neg_weights)[0]; + Mat1f err_direct = pos_cdf + neg_total - neg_cdf; + Mat1f err_backward = 1.0f - err_direct; + + int idx1[2], idx2[2]; + double err1, err2; + minMaxIdx(err_direct, &err1, NULL, idx1); + minMaxIdx(err_backward, &err2, NULL, idx2); +//#pragma omp critical + { + if (min(err1, err2) < min_err) { + if (err1 < err2) { + min_err = err1; + min_polarity = +1; + threshold_q = idx1[1]; + } else { + min_err = err2; + min_polarity = -1; + threshold_q = idx2[1]; + } + min_feature_ind = feat_i; + if (quantize) { + min_threshold = data_min(feat_i, 0) + data_step(feat_i, 0) * + (threshold_q + .5f); + } else { + min_threshold = threshold_q + .5f; + } + } + } + } - // Normalize weights - float z = (float)sum(weights)[0]; - for( int col = 0; col < weights.cols; ++col) - { - weights.at(0, col) /= z; + float alpha = .5f * (float)log((1 - min_err) / min_err); + alphas_.push_back(alpha); + feature_indices_.push_back(min_feature_ind); + thresholds_.push_back(min_threshold); + polarities_.push_back(min_polarity); + feature_ignore[min_feature_ind] = true; + + double loss = 0; + // Update positive weights + for (int j = 0; j < data_pos.cols; ++j) { + int val = data_pos.at(min_feature_ind, j); + int label = min_polarity * (val - threshold_q) >= 0 ? +1 : -1; + pos_weights(0, j) *= exp(-alpha * label); + pos_trace(0, j) += alpha * label; + loss += exp(-pos_trace(0, j)) / (2.0f * data_pos.cols); } - // Sort trace - Mat indices; - sortIdx(trace, indices, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); - Mat new_weights = Mat_::zeros(weights.rows, weights.cols); - Mat new_labels = Mat_::zeros(labels.rows, labels.cols); - Mat new_trace; - for( int col = 0; col < new_weights.cols; ++col ) - { - new_weights.at(0, col) = - weights.at(0, indices.at(0, col)); - new_labels.at(0, col) = - labels.at(0, indices.at(0, col)); - } - - //sort in-place to save memory - sort_columns_without_copy(data, indices); - sort(trace, new_trace, cv::SORT_EVERY_ROW | cv::SORT_ASCENDING); - - // Compute threshold for trace - /* - int col = 0; - for( int pos_i = 0; - pos_i < pos_count * params_.alpha && col < new_labels.cols; - ++col ) - { - if( new_labels.at(0, col) == +1 ) - ++pos_i; + // Update negative weights + for (int j = 0; j < data_neg.cols; ++j) { + int val = data_neg.at(min_feature_ind, j); + int label = min_polarity * (val - threshold_q) >= 0 ? +1 : -1; + neg_weights(0, j) *= exp(alpha * label); + neg_trace(0, j) += alpha * label; + loss += exp(+neg_trace(0, j)) / (2.0f * data_neg.cols); } - */ - - int cur_pos = 0, cur_neg = 0; - int max_col = 0; - for( int col = 0; col < new_labels.cols - 1; ++col ) { - if (new_labels.at(0, col) == +1 ) - ++cur_pos; - else - ++cur_neg; - - float p_neg = cur_neg / (float)neg_count; - float p_pos = cur_pos / (float)pos_count; - if( params_.alpha * p_neg > p_pos ) - max_col = col; + double cascade_threshold = -1; + minMaxIdx(pos_trace, &cascade_threshold); + cascade_thresholds_.push_back((float)cascade_threshold); + + std::cerr << "i=" << std::setw(4) << i; + std::cerr << " feat=" << std::setw(5) << min_feature_ind; + std::cerr << " thr=" << std::setw(3) << threshold_q; + std::cerr << " casthr=" << std::fixed << std::setprecision(3) + << cascade_threshold; + std::cerr << " alpha=" << std::fixed << std::setprecision(3) + << alpha << " err=" << std::fixed << std::setprecision(3) << min_err + << " loss=" << std::scientific << loss << std::endl; + + //int pos = 0; + //for (int j = 0; j < data_pos.cols; ++j) { + // if (pos_trace(0, j) > cascade_threshold - 0.5) { + // pos_trace(0, pos) = pos_trace(0, j); + // data_pos.col(j).copyTo(data_pos.col(pos)); + // pos_weights(0, pos) = pos_weights(0, j); + // pos += 1; + // } + //} + //std::cerr << "pos " << data_pos.cols << "/" << pos << std::endl; + //pos_trace = pos_trace.colRange(0, pos); + //data_pos = data_pos.colRange(0, pos); + //pos_weights = pos_weights.colRange(0, pos); + + int pos = 0; + for (int j = 0; j < data_neg.cols; ++j) { + if (neg_trace(0, j) > cascade_threshold - 0.5) { + neg_trace(0, pos) = neg_trace(0, j); + data_neg.col(j).copyTo(data_neg.col(pos)); + neg_weights(0, pos) = neg_weights(0, j); + pos += 1; + } } + std::cerr << "neg " << data_neg.cols << "/" << pos << std::endl; + neg_trace = neg_trace.colRange(0, pos); + data_neg = data_neg.colRange(0, pos); + neg_weights = neg_weights.colRange(0, pos); - thresholds_.push_back(new_trace.at(0, max_col)); - // Drop samples below threshold - //uses Rois instead of copyTo to save memory - data = data(Rect(max_col, 0, data.cols - max_col, data.rows)); - new_trace.colRange(max_col, new_trace.cols).copyTo(trace); - new_weights.colRange(max_col, new_weights.cols).copyTo(weights); - new_labels.colRange(max_col, new_labels.cols).copyTo(labels); - - pos_count = count(labels, +1); - neg_count = count(labels, -1); - - if( data.cols < 2 || neg_count == 0) - { + if (loss < 1e-50 || min_err > 0.5) { + std::cerr << "Stopping early" << std::endl; + weak_count_ = i + 1; break; } + + // Normalize weights + double z = (sum(pos_weights) + sum(neg_weights))[0]; + pos_weights /= z; + neg_weights /= z; } - return feature_indices; } -float WaldBoostImpl::predict( - const Ptr& feature_evaluator) const +int WaldBoost::predict(Ptr eval, float *h) const { - float trace = 0; - CV_Assert(stumps_.size() == thresholds_.size()); - for( size_t i = 0; i < stumps_.size(); ++i ) - { - int value = feature_evaluator->evaluate(i); - trace += stumps_[i].predict(value); - - if( trace < thresholds_[i] ) + assert(feature_indices_.size() == size_t(weak_count_)); + assert(cascade_thresholds_.size() == size_t(weak_count_)); + float res = 0; + int count = weak_count_; + for (int i = 0; i < count; ++i) { + float val = (*eval)(feature_indices_[i]); + int label = polarities_[i] * (val - thresholds_[i]) > 0 ? +1: -1; + res += alphas_[i] * label; + if (res < cascade_thresholds_[i]) { return -1; + } } - return trace; + *h = res; + return res > cascade_thresholds_[count - 1] ? +1 : -1; } -Ptr -createWaldBoost(const WaldBoostParams& params) +void WaldBoost::write(FileStorage &fs) const { - return Ptr(new WaldBoostImpl(params)); + fs << "{"; + fs << "waldboost_params" + << "{" << "weak_count" << weak_count_ << "}"; + + fs << "thresholds" << "["; + for (size_t i = 0; i < thresholds_.size(); ++i) + fs << thresholds_[i]; + fs << "]"; + + fs << "alphas" << "["; + for (size_t i = 0; i < alphas_.size(); ++i) + fs << alphas_[i]; + fs << "]"; + + fs << "polarities" << "["; + for (size_t i = 0; i < polarities_.size(); ++i) + fs << polarities_[i]; + fs << "]"; + + fs << "cascade_thresholds" << "["; + for (size_t i = 0; i < cascade_thresholds_.size(); ++i) + fs << cascade_thresholds_[i]; + fs << "]"; + + fs << "feature_indices" << "["; + for (size_t i = 0; i < feature_indices_.size(); ++i) + fs << feature_indices_[i]; + fs << "]"; + + fs << "}"; } +void WaldBoost::read(const FileNode &node) +{ + weak_count_ = (int)(node["waldboost_params"]["weak_count"]); + thresholds_.resize(weak_count_); + alphas_.resize(weak_count_); + polarities_.resize(weak_count_); + cascade_thresholds_.resize(weak_count_); + feature_indices_.resize(weak_count_); + + FileNodeIterator n; + + n = node["thresholds"].begin(); + for (int i = 0; i < weak_count_; ++i, ++n) + *n >> thresholds_[i]; + + n = node["alphas"].begin(); + for (int i = 0; i < weak_count_; ++i, ++n) + *n >> alphas_[i]; + + n = node["polarities"].begin(); + for (int i = 0; i < weak_count_; ++i, ++n) + *n >> polarities_[i]; + + n = node["cascade_thresholds"].begin(); + for (int i = 0; i < weak_count_; ++i, ++n) + *n >> cascade_thresholds_[i]; + + n = node["feature_indices"].begin(); + for (int i = 0; i < weak_count_; ++i, ++n) + *n >> feature_indices_[i]; +} -} /* namespace xobjdetect */ -} /* namespace cv */ +void WaldBoost::reset(int weak_count) +{ + weak_count_ = weak_count; + thresholds_.clear(); + alphas_.clear(); + feature_indices_.clear(); + polarities_.clear(); + cascade_thresholds_.clear(); +} + +WaldBoost::~WaldBoost() +{ +} + +} +} diff --git a/modules/xobjdetect/src/waldboost.hpp b/modules/xobjdetect/src/waldboost.hpp new file mode 100644 index 000000000..9247619e4 --- /dev/null +++ b/modules/xobjdetect/src/waldboost.hpp @@ -0,0 +1,94 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 __OPENCV_XOBJDETECT_WALDBOOST_HPP__ +#define __OPENCV_XOBJDETECT_WALDBOOST_HPP__ + +#include "precomp.hpp" + +namespace cv { +namespace xobjdetect { + +class WaldBoost { +public: + WaldBoost(int weak_count); + WaldBoost(); + std::vector get_feature_indices(); + + void detect(Ptr eval, + const Mat& img, + const std::vector& scales, + std::vector& bboxes, + Mat1f& confidences); + + void detect(Ptr eval, + const Mat& img, + const std::vector& scales, + std::vector& bboxes, + std::vector& confidences); + + void fit(Mat& data_pos, Mat& data_neg); + int predict(Ptr eval, float *h) const; + void save(const std::string& filename); + void load(const std::string& filename); + + void read(const FileNode &node); + void write(FileStorage &fs) const; + + void reset(int weak_count); + ~WaldBoost(); + +private: + int weak_count_; + std::vector thresholds_; + std::vector alphas_; + std::vector feature_indices_; + std::vector polarities_; + std::vector cascade_thresholds_; +}; + +} +} + +#endif diff --git a/modules/xobjdetect/src/wbdetector.cpp b/modules/xobjdetect/src/wbdetector.cpp new file mode 100644 index 000000000..395ea1e48 --- /dev/null +++ b/modules/xobjdetect/src/wbdetector.cpp @@ -0,0 +1,222 @@ +/* +By downloading, copying, installing or using the software you agree to this license. +If you do not agree to this license, do not download, install, +copy or use the software. + + + License Agreement + For Open Source Computer Vision Library + (3-clause BSD License) + +Copyright (C) 2000-2015, Intel Corporation, all rights reserved. +Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved. +Copyright (C) 2009-2015, NVIDIA Corporation, all rights reserved. +Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved. +Copyright (C) 2015, OpenCV Foundation, all rights reserved. +Copyright (C) 2015, Itseez Inc., all rights reserved. +Third party copyrights are property of their respective owners. + +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 names of the copyright holders nor the names of the 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 copyright holders 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 "precomp.hpp" + +using std::cerr; +using std::endl; +using std::vector; +using std::string; + +namespace cv { +namespace xobjdetect { + +static vector sample_patches( + const string& path, + int n_rows, + int n_cols, + size_t n_patches) +{ + vector filenames; + glob(path, filenames); + vector patches; + size_t patch_count = 0; + for (size_t i = 0; i < filenames.size(); ++i) { + Mat img = imread(filenames[i], CV_LOAD_IMAGE_GRAYSCALE); + for (int row = 0; row + n_rows < img.rows; row += n_rows) { + for (int col = 0; col + n_cols < img.cols; col += n_cols) { + patches.push_back(img(Rect(col, row, n_cols, n_rows)).clone()); + patch_count += 1; + if (patch_count == n_patches) { + goto sampling_finished; + } + } + } + } +sampling_finished: + return patches; +} + +static vector read_imgs(const string& path) +{ + vector filenames; + glob(path, filenames); + vector imgs; + for (size_t i = 0; i < filenames.size(); ++i) { + imgs.push_back(imread(filenames[i], CV_LOAD_IMAGE_GRAYSCALE)); + } + return imgs; +} + +void WBDetectorImpl::read(const FileNode& node) +{ + boost_.read(node); +} + + +void WBDetectorImpl::write(FileStorage &fs) const +{ + boost_.write(fs); +} + +void WBDetectorImpl::train( + const string& pos_samples_path, + const string& neg_imgs_path) +{ + + vector pos_imgs = read_imgs(pos_samples_path); + vector neg_imgs = sample_patches(neg_imgs_path, 24, 24, pos_imgs.size() * 10); + + assert(pos_imgs.size()); + assert(neg_imgs.size()); + + int n_features; + Mat pos_data, neg_data; + + Ptr eval = CvFeatureEvaluator::create(); + eval->init(CvFeatureParams::create(), 1, Size(24, 24)); + n_features = eval->getNumFeatures(); + + const int stages[] = {64, 128, 256, 512, 1024}; + const int stage_count = sizeof(stages) / sizeof(*stages); + const int stage_neg = (int)(pos_imgs.size() * 5); + const int max_per_image = 100; + + const float scales_arr[] = {.3f, .4f, .5f, .6f, .7f, .8f, .9f, 1.0f}; + const vector scales(scales_arr, + scales_arr + sizeof(scales_arr) / sizeof(*scales_arr)); + + vector neg_filenames; + glob(neg_imgs_path, neg_filenames); + + + for (int i = 0; i < stage_count; ++i) { + + cerr << "compute features" << endl; + + pos_data = Mat1b(n_features, (int)pos_imgs.size()); + neg_data = Mat1b(n_features, (int)neg_imgs.size()); + + for (size_t k = 0; k < pos_imgs.size(); ++k) { + eval->setImage(pos_imgs[k], +1, 0, boost_.get_feature_indices()); + for (int j = 0; j < n_features; ++j) { + pos_data.at(j, (int)k) = (uchar)(*eval)(j); + } + } + + for (size_t k = 0; k < neg_imgs.size(); ++k) { + eval->setImage(neg_imgs[k], 0, 0, boost_.get_feature_indices()); + for (int j = 0; j < n_features; ++j) { + neg_data.at(j, (int)k) = (uchar)(*eval)(j); + } + } + + + boost_.reset(stages[i]); + boost_.fit(pos_data, neg_data); + + if (i + 1 == stage_count) { + break; + } + + int bootstrap_count = 0; + size_t img_i = 0; + for (; img_i < neg_filenames.size(); ++img_i) { + cerr << "win " << bootstrap_count << "/" << stage_neg + << " img " << (img_i + 1) << "/" << neg_filenames.size() << "\r"; + Mat img = imread(neg_filenames[img_i], CV_LOAD_IMAGE_GRAYSCALE); + vector bboxes; + Mat1f confidences; + boost_.detect(eval, img, scales, bboxes, confidences); + + if (confidences.rows > 0) { + Mat1i indices; + sortIdx(confidences, indices, + CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING); + + int win_count = min(max_per_image, confidences.rows); + win_count = min(win_count, stage_neg - bootstrap_count); + Mat window; + for (int k = 0; k < win_count; ++k) { + resize(img(bboxes[indices(k, 0)]), window, Size(24, 24)); + neg_imgs.push_back(window.clone()); + bootstrap_count += 1; + } + if (bootstrap_count >= stage_neg) { + break; + } + } + } + cerr << "bootstrapped " << bootstrap_count << " windows from " + << (img_i + 1) << " images" << endl; + } +} + +void WBDetectorImpl::detect( + const Mat& img, + vector &bboxes, + vector &confidences) +{ + Mat test_img = img.clone(); + bboxes.clear(); + confidences.clear(); + vector scales; + for (float scale = 0.2f; scale < 1.2f; scale *= 1.1f) { + scales.push_back(scale); + } + Ptr params = CvFeatureParams::create(); + Ptr eval = CvFeatureEvaluator::create(); + eval->init(params, 1, Size(24, 24)); + boost_.detect(eval, img, scales, bboxes, confidences); + assert(confidences.size() == bboxes.size()); +} + +Ptr +WBDetector::create() +{ + return Ptr(new WBDetectorImpl()); +} + +} +} diff --git a/modules/adas/include/opencv2/adas.hpp b/modules/xobjdetect/src/wbdetector.hpp similarity index 71% rename from modules/adas/include/opencv2/adas.hpp rename to modules/xobjdetect/src/wbdetector.hpp index d41ca0054..86247ea0f 100644 --- a/modules/adas/include/opencv2/adas.hpp +++ b/modules/xobjdetect/src/wbdetector.hpp @@ -39,6 +39,39 @@ the use of this software, even if advised of the possibility of such damage. */ -/** @defgroup adas Advanced Driver Assistance -*/ +#ifndef __OPENCV_XOBJDETECT_DETECTOR_HPP__ +#define __OPENCV_XOBJDETECT_DETECTOR_HPP__ + +#include +#include +#include +#include +#include "precomp.hpp" + +namespace cv +{ +namespace xobjdetect +{ + +class WBDetectorImpl : public WBDetector { +public: + virtual void read(const FileNode &node); + virtual void write(FileStorage &fs) const; + + virtual void train( + const std::string& pos_samples, + const std::string& neg_imgs); + + virtual void detect( + const Mat& img, + std::vector &bboxes, + std::vector &confidences); + +private: + WaldBoost boost_; +}; + +} /* namespace xobjdetect */ +} /* namespace cv */ +#endif /* __OPENCV_XOBJDETECT_DETECTOR_HPP__ */ diff --git a/modules/xobjdetect/tools/CMakeLists.txt b/modules/xobjdetect/tools/CMakeLists.txt new file mode 100644 index 000000000..5c40af12e --- /dev/null +++ b/modules/xobjdetect/tools/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(waldboost_detector) diff --git a/modules/adas/tools/fcw_train/CMakeLists.txt b/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt similarity index 97% rename from modules/adas/tools/fcw_train/CMakeLists.txt rename to modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt index 5b1d78303..5f34f1e71 100644 --- a/modules/adas/tools/fcw_train/CMakeLists.txt +++ b/modules/xobjdetect/tools/waldboost_detector/CMakeLists.txt @@ -1,4 +1,4 @@ -set(name fcw_train) +set(name waldboost_detector) set(the_target opencv_${name}) set(OPENCV_${the_target}_DEPS opencv_core opencv_imgcodecs opencv_videoio diff --git a/modules/xobjdetect/tools/waldboost_detector/waldboost_detector.cpp b/modules/xobjdetect/tools/waldboost_detector/waldboost_detector.cpp new file mode 100644 index 000000000..490cdd585 --- /dev/null +++ b/modules/xobjdetect/tools/waldboost_detector/waldboost_detector.cpp @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +using namespace std; +using namespace cv; +using namespace cv::xobjdetect; + +int main(int argc, char **argv) +{ + if (argc < 5) { + cerr << "Usage: " << argv[0] << " train " << endl; + cerr << " " << argv[0] << " detect " << endl; + return 0; + } + + string mode = argv[1]; + Ptr detector = WBDetector::create(); + if (mode == "train") { + assert(argc == 5); + detector->train(argv[3], argv[4]); + FileStorage fs(argv[2], FileStorage::WRITE); + fs << "waldboost"; + detector->write(fs); + } else if (mode == "detect") { + assert(argc == 6); + vector bboxes; + vector confidences; + Mat img = imread(argv[3], CV_LOAD_IMAGE_GRAYSCALE); + FileStorage fs(argv[2], FileStorage::READ); + detector->read(fs.getFirstTopLevelNode()); + detector->detect(img, bboxes, confidences); + + FILE *fhandle = fopen(argv[5], "a"); + for (size_t i = 0; i < bboxes.size(); ++i) { + Rect o = bboxes[i]; + fprintf(fhandle, "%s;%u;%u;%u;%u;%lf\n", + argv[3], o.x, o.y, o.width, o.height, confidences[i]); + } + for (size_t i = 0; i < bboxes.size(); ++i) { + rectangle(img, bboxes[i], Scalar(255, 0, 0)); + } + imwrite(argv[4], img); + } +}