Merge remote-tracking branch 'upstream/3.4' into merge-3.4
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 3 Dec 2021 12:32:49 +0000 (12:32 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 3 Dec 2021 12:32:49 +0000 (12:32 +0000)
65 files changed:
1  2 
modules/calib3d/src/calibration.cpp
modules/calib3d/src/compat_ptsetreg.cpp
modules/calib3d/test/test_cameracalibration.cpp
modules/calib3d/test/test_fundam.cpp
modules/calib3d/test/test_undistort.cpp
modules/core/src/array.cpp
modules/core/src/datastructs.cpp
modules/core/src/dxt.cpp
modules/core/src/opencl/runtime/opencl_clblas.cpp
modules/core/src/opencl/runtime/opencl_clfft.cpp
modules/core/src/opencl/runtime/opencl_core.cpp
modules/core/src/persistence.cpp
modules/core/src/persistence_xml.cpp
modules/core/src/persistence_yml.cpp
modules/core/src/precomp.hpp
modules/core/test/test_ds.cpp
modules/core/test/test_mat.cpp
modules/core/test/test_math.cpp
modules/dnn/include/opencv2/dnn/all_layers.hpp
modules/dnn/src/dnn.cpp
modules/dnn/src/layers/elementwise_layers.cpp
modules/dnn/src/layers/fully_connected_layer.cpp
modules/dnn/src/layers/layers_common.simd.hpp
modules/dnn/src/layers/lrn_layer.cpp
modules/dnn/src/layers/recurrent_layers.cpp
modules/dnn/src/ocl4dnn/src/ocl4dnn_conv_spatial.cpp
modules/dnn/src/onnx/onnx_graph_simplifier.cpp
modules/dnn/src/onnx/onnx_importer.cpp
modules/dnn/src/opencl/activations.cl
modules/dnn/test/test_backends.cpp
modules/dnn/test/test_caffe_importer.cpp
modules/dnn/test/test_darknet_importer.cpp
modules/dnn/test/test_halide_layers.cpp
modules/dnn/test/test_layers.cpp
modules/dnn/test/test_misc.cpp
modules/dnn/test/test_onnx_importer.cpp
modules/dnn/test/test_tf_importer.cpp
modules/dnn/test/test_torch_importer.cpp
modules/features2d/test/test_nearestneighbors.cpp
modules/imgproc/src/approx.cpp
modules/imgproc/src/contours.cpp
modules/imgproc/src/distransform.cpp
modules/imgproc/src/drawing.cpp
modules/imgproc/src/hough.cpp
modules/imgproc/src/precomp.hpp
modules/imgproc/src/subdivision2d.cpp
modules/imgproc/test/test_approxpoly.cpp
modules/imgproc/test/test_color.cpp
modules/imgproc/test/test_contours.cpp
modules/imgproc/test/test_convhull.cpp
modules/imgproc/test/test_filter.cpp
modules/imgproc/test/test_imgwarp.cpp
modules/imgproc/test/test_templmatch.cpp
modules/imgproc/test/test_thresh.cpp
modules/objdetect/src/cascadedetect.cpp
modules/objdetect/src/hog.cpp
modules/objdetect/test/test_cascadeandhog.cpp
modules/ts/src/ocl_perf.cpp
modules/ts/src/ts.cpp
modules/ts/src/ts_arrtest.cpp
modules/ts/src/ts_func.cpp
modules/ts/src/ts_perf.cpp
modules/videoio/src/cap_ffmpeg_impl.hpp
modules/videoio/src/cap_v4l.cpp
modules/videoio/src/precomp.hpp

Simple merge
Simple merge
@@@ -885,455 -772,143 +885,455 @@@ int CV_InitInverseRectificationMapTest:
      zero_new_cam = (cvtest::randInt(rng)%2) == 0 ? false : true;
      zero_R = (cvtest::randInt(rng)%2) == 0 ? false : true;
  
 -    if (useCPlus)
 +    return code;
 +}
 +
 +void CV_InitInverseRectificationMapTest::prepare_to_validation(int/* test_case_idx*/)
 +{
 +    // Configure Parameters
 +    Mat _a0 = test_mat[INPUT][0];
 +    Mat _d0 = zero_distortion ? cv::Mat() : test_mat[INPUT][1];
 +    Mat _R0 = zero_R ? cv::Mat() : test_mat[INPUT][2];
 +    Mat _new_cam0 = zero_new_cam ? test_mat[INPUT][0] : test_mat[INPUT][3];
 +    Mat _mapx(img_size, CV_32F), _mapy(img_size, CV_32F);
 +
 +    double a[9], d[5]={0., 0., 0., 0. , 0.}, R[9]={1., 0., 0., 0., 1., 0., 0., 0., 1.}, a1[9];
 +    Mat _a(3, 3, CV_64F, a), _a1(3, 3, CV_64F, a1);
 +    Mat _d(_d0.rows,_d0.cols, CV_MAKETYPE(CV_64F,_d0.channels()),d);
 +    Mat _R(3, 3, CV_64F, R);
 +    double fx, fy, cx, cy, ifx, ify, cxn, cyn;
 +
 +    // Camera matrix
 +    CV_Assert(_a0.size() == Size(3, 3));
 +    _a0.convertTo(_a, CV_64F);
 +    if( !_new_cam0.empty() )
      {
 -        camera_mat = test_mat[INPUT][1];
 -        distortion_coeffs = test_mat[INPUT][2];
 -        R = test_mat[INPUT][3];
 -        new_camera_mat = test_mat[INPUT][4];
 +        CV_Assert(_new_cam0.size() == Size(3, 3));
 +        _new_cam0.convertTo(_a1, CV_64F);
 +    }
 +    else
 +    {
 +        _a.copyTo(_a1);
      }
  
 -    return code;
 +    // Distortion
 +    CV_Assert(_d0.empty() ||
 +              _d0.size() == Size(5, 1) ||
 +              _d0.size() == Size(1, 5) ||
 +              _d0.size() == Size(4, 1) ||
 +              _d0.size() == Size(1, 4));
 +    if( !_d0.empty() )
 +        _d0.convertTo(_d, CV_64F);
 +
 +    // Rotation
 +    if( !_R0.empty() )
 +    {
 +        CV_Assert(_R0.size() == Size(3, 3));
 +        Mat tmp;
 +        _R0.convertTo(_R, CV_64F);
 +    }
 +
 +    // Copy camera matrix
 +    fx = a[0]; fy = a[4]; cx = a[2]; cy = a[5];
 +
 +    // Copy new camera matrix
 +    ifx = a1[0]; ify = a1[4]; cxn = a1[2]; cyn = a1[5];
 +
 +    // Undistort
 +    for( int v = 0; v < img_size.height; v++ )
 +    {
 +        for( int u = 0; u < img_size.width; u++ )
 +        {
 +            // Convert from image to pin-hole coordinates
 +            double x = (u - cx)/fx;
 +            double y = (v - cy)/fy;
 +
 +            // Undistort
 +            double x2 = x*x, y2 = y*y;
 +            double r2 = x2 + y2;
 +            double cdist = 1./(1. + (d[0] + (d[1] + d[4]*r2)*r2)*r2); // (1. + (d[5] + (d[6] + d[7]*r2)*r2)*r2) == 1 as d[5-7]=0;
 +            double x_ = (x - (d[2]*2.*x*y + d[3]*(r2 + 2.*x2)))*cdist;
 +            double y_ = (y - (d[3]*2.*x*y + d[2]*(r2 + 2.*y2)))*cdist;
 +
 +            // Rectify
 +            double X = R[0]*x_ + R[1]*y_ + R[2];
 +            double Y = R[3]*x_ + R[4]*y_ + R[5];
 +            double Z = R[6]*x_ + R[7]*y_ + R[8];
 +            double x__ = X/Z;
 +            double y__ = Y/Z;
 +
 +            // Convert from pin-hole to image coordinates
 +            _mapy.at<float>(v, u) = (float)(y__*ify + cyn);
 +            _mapx.at<float>(v, u) = (float)(x__*ifx + cxn);
 +        }
 +    }
 +
 +    // Convert
 +    _mapx.convertTo(test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
 +    _mapy.convertTo(test_mat[REF_OUTPUT][1], test_mat[REF_OUTPUT][0].type());
  }
  
 -void CV_InitUndistortRectifyMapTest::prepare_to_validation(int/* test_case_idx*/)
 +void CV_InitInverseRectificationMapTest::run_func()
  {
 -#if 0
 -    int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
 -    double cam[9] = {0,0,0,0,0,0,0,0,1};
 -    double rot[9] = {1,0,0,0,1,0,0,0,1};
 -    vector<double> dist(dist_size);
 -    vector<double> new_cam(test_mat[INPUT][4].cols * test_mat[INPUT][4].rows);
 -    vector<Point2d> points(N_POINTS);
 -    vector<Point2d> r_points(N_POINTS);
 -    //Run reference calculations
 -    Mat ref_points(test_mat[INPUT][0].size(),CV_64FC2,&r_points[0]);
 -    Mat _camera(3,3,CV_64F,cam);
 -    Mat _rot(3,3,CV_64F,rot);
 -    Mat _distort(test_mat[INPUT][2].size(),CV_64F,&dist[0]);
 -    Mat _new_cam(test_mat[INPUT][4].size(),CV_64F,&new_cam[0]);
 -    Mat _points(test_mat[INPUT][0].size(),CV_64FC2,&points[0]);
 -
 -    cvtest::convert(test_mat[INPUT][1],_camera,_camera.type());
 -    cvtest::convert(test_mat[INPUT][2],_distort,_distort.type());
 -    cvtest::convert(test_mat[INPUT][3],_rot,_rot.type());
 -    cvtest::convert(test_mat[INPUT][4],_new_cam,_new_cam.type());
 -
 -    //Applying precalculated undistort rectify map
 -    if (!useCPlus)
 +    cv::Mat camera_mat = test_mat[INPUT][0];
 +    cv::Mat dist = zero_distortion ? cv::Mat() : test_mat[INPUT][1];
 +    cv::Mat R = zero_R ? cv::Mat() : test_mat[INPUT][2];
 +    cv::Mat new_cam = zero_new_cam ? cv::Mat() : test_mat[INPUT][3];
 +    cv::Mat& mapx = test_mat[OUTPUT][0], &mapy = test_mat[OUTPUT][1];
 +    cv::initInverseRectificationMap(camera_mat,dist,R,new_cam,img_size,map_type,mapx,mapy);
 +}
 +
 +double CV_InitInverseRectificationMapTest::get_success_error_level( int /*test_case_idx*/, int /*i*/, int /*j*/ )
 +{
 +    return 8;
 +}
 +
 +//////////////////////////////////////////////////////////////////////////////////////////////////////
 +
 +TEST(Calib3d_DefaultNewCameraMatrix, accuracy) { CV_DefaultNewCameraMatrixTest test; test.safe_run(); }
 +TEST(Calib3d_UndistortPoints, accuracy) { CV_UndistortPointsTest test; test.safe_run(); }
 +TEST(Calib3d_InitUndistortRectifyMap, accuracy) { CV_InitUndistortRectifyMapTest test; test.safe_run(); }
 +TEST(DISABLED_Calib3d_InitInverseRectificationMap, accuracy) { CV_InitInverseRectificationMapTest test; test.safe_run(); }
 +
 +////////////////////////////// undistort /////////////////////////////////
 +
 +static void test_remap( const Mat& src, Mat& dst, const Mat& mapx, const Mat& mapy,
 +                        Mat* mask=0, int interpolation=CV_INTER_LINEAR )
 +{
 +    int x, y, k;
 +    int drows = dst.rows, dcols = dst.cols;
 +    int srows = src.rows, scols = src.cols;
 +    const uchar* sptr0 = src.ptr();
 +    int depth = src.depth(), cn = src.channels();
 +    int elem_size = (int)src.elemSize();
 +    int step = (int)(src.step / CV_ELEM_SIZE(depth));
 +    int delta;
 +
 +    if( interpolation != CV_INTER_CUBIC )
      {
 -        mapx = cv::Mat(_mapx);
 -        mapy = cv::Mat(_mapy);
 +        delta = 0;
 +        scols -= 1; srows -= 1;
      }
 -    cv::Mat map1,map2;
 -    cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
 -    CvMat _map1 = map1;
 -    CvMat _map2 = map2;
 -    const Point2d* sptr = (const Point2d*)test_mat[INPUT][0].data;
 -    for( int i = 0;i < N_POINTS; i++ )
 +    else
      {
 -        int u = saturate_cast<int>(sptr[i].x);
 -        int v = saturate_cast<int>(sptr[i].y);
 -        points[i].x = _map1.data.fl[v*_map1.cols + u];
 -        points[i].y = _map2.data.fl[v*_map2.cols + u];
 +        delta = 1;
 +        scols = MAX(scols - 3, 0);
 +        srows = MAX(srows - 3, 0);
      }
  
 -    //---
 +    int scols1 = MAX(scols - 2, 0);
 +    int srows1 = MAX(srows - 2, 0);
  
 -    cv::undistortPoints(_points, ref_points, _camera,
 -                        zero_distortion ? Mat() : _distort,
 -                        zero_R ? Mat::eye(3,3,CV_64F) : _rot,
 -                        zero_new_cam ? _camera : _new_cam);
 -    //cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
 -    cvtest::convert(ref_points, test_mat[REF_OUTPUT][0], test_mat[REF_OUTPUT][0].type());
 -    cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
 +    if( mask )
 +        *mask = Scalar::all(0);
  
 -    cvReleaseMat(&_mapx);
 -    cvReleaseMat(&_mapy);
 -#else
 -    int dist_size = test_mat[INPUT][2].cols > test_mat[INPUT][2].rows ? test_mat[INPUT][2].cols : test_mat[INPUT][2].rows;
 -    double cam[9] = {0,0,0,0,0,0,0,0,1};
 -    double rot[9] = {1,0,0,0,1,0,0,0,1};
 -    double* dist = new double[dist_size ];
 -    double* new_cam = new double[test_mat[INPUT][4].cols * test_mat[INPUT][4].rows];
 -    double* points = new double[N_POINTS*2];
 -    double* r_points = new double[N_POINTS*2];
 -    //Run reference calculations
 -    CvMat ref_points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,r_points);
 -    CvMat _camera = cvMat(3,3,CV_64F,cam);
 -    CvMat _rot = cvMat(3,3,CV_64F,rot);
 -    CvMat _distort = cvMat(test_mat[INPUT][2].rows,test_mat[INPUT][2].cols,CV_64F,dist);
 -    CvMat _new_cam = cvMat(test_mat[INPUT][4].rows,test_mat[INPUT][4].cols,CV_64F,new_cam);
 -    CvMat _points= cvMat(test_mat[INPUT][0].rows,test_mat[INPUT][0].cols,CV_64FC2,points);
 +    for( y = 0; y < drows; y++ )
 +    {
 +        uchar* dptr = dst.ptr(y);
 +        const float* mx = mapx.ptr<float>(y);
 +        const float* my = mapy.ptr<float>(y);
 +        uchar* m = mask ? mask->ptr(y) : 0;
 +
 +        for( x = 0; x < dcols; x++, dptr += elem_size )
 +        {
 +            float xs = mx[x];
 +            float ys = my[x];
 +            int ixs = cvFloor(xs);
 +            int iys = cvFloor(ys);
 +
 +            if( (unsigned)(ixs - delta - 1) >= (unsigned)scols1 ||
 +                (unsigned)(iys - delta - 1) >= (unsigned)srows1 )
 +            {
 +                if( m )
 +                    m[x] = 1;
 +                if( (unsigned)(ixs - delta) >= (unsigned)scols ||
 +                    (unsigned)(iys - delta) >= (unsigned)srows )
 +                    continue;
 +            }
  
 -    CvMat _input1 = cvMat(test_mat[INPUT][1]);
 -    CvMat _input2 = cvMat(test_mat[INPUT][2]);
 -    CvMat _input3 = cvMat(test_mat[INPUT][3]);
 -    CvMat _input4 = cvMat(test_mat[INPUT][4]);
 +            xs -= ixs;
 +            ys -= iys;
  
 -    cvtest::convert(cvarrToMat(&_input1), cvarrToMat(&_camera), -1);
 -    cvtest::convert(cvarrToMat(&_input2), cvarrToMat(&_distort), -1);
 -    cvtest::convert(cvarrToMat(&_input3), cvarrToMat(&_rot), -1);
 -    cvtest::convert(cvarrToMat(&_input4), cvarrToMat(&_new_cam), -1);
 +            switch( depth )
 +            {
 +            case CV_8U:
 +                {
 +                const uchar* sptr = sptr0 + iys*step + ixs*cn;
 +                for( k = 0; k < cn; k++ )
 +                {
 +                    float v00 = sptr[k];
 +                    float v01 = sptr[cn + k];
 +                    float v10 = sptr[step + k];
 +                    float v11 = sptr[step + cn + k];
 +
 +                    v00 = v00 + xs*(v01 - v00);
 +                    v10 = v10 + xs*(v11 - v10);
 +                    v00 = v00 + ys*(v10 - v00);
 +                    dptr[k] = (uchar)cvRound(v00);
 +                }
 +                }
 +                break;
 +            case CV_16U:
 +                {
 +                const ushort* sptr = (const ushort*)sptr0 + iys*step + ixs*cn;
 +                for( k = 0; k < cn; k++ )
 +                {
 +                    float v00 = sptr[k];
 +                    float v01 = sptr[cn + k];
 +                    float v10 = sptr[step + k];
 +                    float v11 = sptr[step + cn + k];
 +
 +                    v00 = v00 + xs*(v01 - v00);
 +                    v10 = v10 + xs*(v11 - v10);
 +                    v00 = v00 + ys*(v10 - v00);
 +                    ((ushort*)dptr)[k] = (ushort)cvRound(v00);
 +                }
 +                }
 +                break;
 +            case CV_32F:
 +                {
 +                const float* sptr = (const float*)sptr0 + iys*step + ixs*cn;
 +                for( k = 0; k < cn; k++ )
 +                {
 +                    float v00 = sptr[k];
 +                    float v01 = sptr[cn + k];
 +                    float v10 = sptr[step + k];
 +                    float v11 = sptr[step + cn + k];
 +
 +                    v00 = v00 + xs*(v01 - v00);
 +                    v10 = v10 + xs*(v11 - v10);
 +                    v00 = v00 + ys*(v10 - v00);
 +                    ((float*)dptr)[k] = (float)v00;
 +                }
 +                }
 +                break;
 +            default:
-                 assert(0);
++                CV_Assert(0);
 +            }
 +        }
 +    }
 +}
  
 -    //Applying precalculated undistort rectify map
 -    if (!useCPlus)
 +class CV_ImgWarpBaseTest : public cvtest::ArrayTest
 +{
 +public:
 +    CV_ImgWarpBaseTest( bool warp_matrix );
 +
 +protected:
 +    int read_params( const cv::FileStorage& fs );
 +    int prepare_test_case( int test_case_idx );
 +    void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
 +    void get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high );
 +    void fill_array( int test_case_idx, int i, int j, Mat& arr );
 +
 +    int interpolation;
 +    int max_interpolation;
 +    double spatial_scale_zoom, spatial_scale_decimate;
 +};
 +
 +
 +CV_ImgWarpBaseTest::CV_ImgWarpBaseTest( bool warp_matrix )
 +{
 +    test_array[INPUT].push_back(NULL);
 +    if( warp_matrix )
 +        test_array[INPUT].push_back(NULL);
 +    test_array[INPUT_OUTPUT].push_back(NULL);
 +    test_array[REF_INPUT_OUTPUT].push_back(NULL);
 +    max_interpolation = 5;
 +    interpolation = 0;
 +    element_wise_relative_error = false;
 +    spatial_scale_zoom = 0.01;
 +    spatial_scale_decimate = 0.005;
 +}
 +
 +
 +int CV_ImgWarpBaseTest::read_params( const cv::FileStorage& fs )
 +{
 +    int code = cvtest::ArrayTest::read_params( fs );
 +    return code;
 +}
 +
 +
 +void CV_ImgWarpBaseTest::get_minmax_bounds( int i, int j, int type, Scalar& low, Scalar& high )
 +{
 +    cvtest::ArrayTest::get_minmax_bounds( i, j, type, low, high );
 +    if( CV_MAT_DEPTH(type) == CV_32F )
      {
 -        mapx = cv::cvarrToMat(_mapx);
 -        mapy = cv::cvarrToMat(_mapy);
 +        low = Scalar::all(-10.);
 +        high = Scalar::all(10);
      }
 -    cv::Mat map1,map2;
 -    cv::convertMaps(mapx,mapy,map1,map2,CV_32FC1);
 -    CvMat _map1 = cvMat(map1);
 -    CvMat _map2 = cvMat(map2);
 -    for (int i=0;i<N_POINTS;i++)
 +}
 +
 +
 +void CV_ImgWarpBaseTest::get_test_array_types_and_sizes( int test_case_idx,
 +                                                vector<vector<Size> >& sizes, vector<vector<int> >& types )
 +{
 +    RNG& rng = ts->get_rng();
 +    int depth = cvtest::randInt(rng) % 3;
 +    int cn = cvtest::randInt(rng) % 3 + 1;
 +    cvtest::ArrayTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
 +    depth = depth == 0 ? CV_8U : depth == 1 ? CV_16U : CV_32F;
 +    cn += cn == 2;
 +
 +    types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = CV_MAKETYPE(depth, cn);
 +    if( test_array[INPUT].size() > 1 )
 +        types[INPUT][1] = cvtest::randInt(rng) & 1 ? CV_32FC1 : CV_64FC1;
 +
 +    interpolation = cvtest::randInt(rng) % max_interpolation;
 +}
 +
 +
 +void CV_ImgWarpBaseTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
 +{
 +    if( i != INPUT || j != 0 )
 +        cvtest::ArrayTest::fill_array( test_case_idx, i, j, arr );
 +}
 +
 +int CV_ImgWarpBaseTest::prepare_test_case( int test_case_idx )
 +{
 +    int code = cvtest::ArrayTest::prepare_test_case( test_case_idx );
 +    Mat& img = test_mat[INPUT][0];
 +    int i, j, cols = img.cols;
 +    int type = img.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
 +    double scale = depth == CV_16U ? 1000. : 255.*0.5;
 +    double space_scale = spatial_scale_decimate;
 +    vector<float> buffer(img.cols*cn);
 +
 +    if( code <= 0 )
 +        return code;
 +
 +    if( test_mat[INPUT_OUTPUT][0].cols >= img.cols &&
 +        test_mat[INPUT_OUTPUT][0].rows >= img.rows )
 +        space_scale = spatial_scale_zoom;
 +
 +    for( i = 0; i < img.rows; i++ )
      {
 -        double u = test_mat[INPUT][0].ptr<double>()[2*i];
 -        double v = test_mat[INPUT][0].ptr<double>()[2*i+1];
 -        _points.data.db[2*i] = (double)_map1.data.fl[(int)v*_map1.cols+(int)u];
 -        _points.data.db[2*i+1] = (double)_map2.data.fl[(int)v*_map2.cols+(int)u];
 +        uchar* ptr = img.ptr(i);
 +        switch( cn )
 +        {
 +        case 1:
 +            for( j = 0; j < cols; j++ )
 +                buffer[j] = (float)((sin((i+1)*space_scale)*sin((j+1)*space_scale)+1.)*scale);
 +            break;
 +        case 2:
 +            for( j = 0; j < cols; j++ )
 +            {
 +                buffer[j*2] = (float)((sin((i+1)*space_scale)+1.)*scale);
 +                buffer[j*2+1] = (float)((sin((i+j)*space_scale)+1.)*scale);
 +            }
 +            break;
 +        case 3:
 +            for( j = 0; j < cols; j++ )
 +            {
 +                buffer[j*3] = (float)((sin((i+1)*space_scale)+1.)*scale);
 +                buffer[j*3+1] = (float)((sin(j*space_scale)+1.)*scale);
 +                buffer[j*3+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
 +            }
 +            break;
 +        case 4:
 +            for( j = 0; j < cols; j++ )
 +            {
 +                buffer[j*4] = (float)((sin((i+1)*space_scale)+1.)*scale);
 +                buffer[j*4+1] = (float)((sin(j*space_scale)+1.)*scale);
 +                buffer[j*4+2] = (float)((sin((i+j)*space_scale)+1.)*scale);
 +                buffer[j*4+3] = (float)((sin((i-j)*space_scale)+1.)*scale);
 +            }
 +            break;
 +        default:
-             assert(0);
++            CV_Assert(0);
 +        }
 +
 +        /*switch( depth )
 +        {
 +        case CV_8U:
 +            for( j = 0; j < cols*cn; j++ )
 +                ptr[j] = (uchar)cvRound(buffer[j]);
 +            break;
 +        case CV_16U:
 +            for( j = 0; j < cols*cn; j++ )
 +                ((ushort*)ptr)[j] = (ushort)cvRound(buffer[j]);
 +            break;
 +        case CV_32F:
 +            for( j = 0; j < cols*cn; j++ )
 +                ((float*)ptr)[j] = (float)buffer[j];
 +            break;
 +        default:
-             assert(0);
++            CV_Assert(0);
 +        }*/
 +        cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
 +        cv::Mat dst(1, cols*cn, depth, ptr);
 +        src.convertTo(dst, dst.type());
      }
  
 -    //---
 +    return code;
 +}
  
 -    cvUndistortPoints(&_points,&ref_points,&_camera,
 -                      zero_distortion ? 0 : &_distort, zero_R ? 0 : &_rot, zero_new_cam ? &_camera : &_new_cam);
 -    //cvTsDistortPoints(&_points,&ref_points,&_camera,&_distort,&_rot,&_new_cam);
 -    CvMat dst = cvMat(test_mat[REF_OUTPUT][0]);
 -    cvtest::convert(cvarrToMat(&ref_points), cvarrToMat(&dst), -1);
  
 -    cvtest::copy(test_mat[INPUT][0],test_mat[OUTPUT][0]);
 +class CV_UndistortTest : public CV_ImgWarpBaseTest
 +{
 +public:
 +    CV_UndistortTest();
  
 -    delete[] dist;
 -    delete[] new_cam;
 -    delete[] points;
 -    delete[] r_points;
 -    cvReleaseMat(&_mapx);
 -    cvReleaseMat(&_mapy);
 -#endif
 +protected:
 +    void get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types );
 +    void run_func();
 +    int prepare_test_case( int test_case_idx );
 +    void prepare_to_validation( int /*test_case_idx*/ );
 +    double get_success_error_level( int test_case_idx, int i, int j );
 +    void fill_array( int test_case_idx, int i, int j, Mat& arr );
 +
 +private:
 +    cv::Mat input0;
 +    cv::Mat input1;
 +    cv::Mat input2;
 +    cv::Mat input_new_cam;
 +    cv::Mat input_output;
 +
 +    bool zero_new_cam;
 +    bool zero_distortion;
 +};
 +
 +
 +CV_UndistortTest::CV_UndistortTest() : CV_ImgWarpBaseTest( false )
 +{
 +    //spatial_scale_zoom = spatial_scale_decimate;
 +    test_array[INPUT].push_back(NULL);
 +    test_array[INPUT].push_back(NULL);
 +    test_array[INPUT].push_back(NULL);
 +
 +    spatial_scale_decimate = spatial_scale_zoom;
  }
  
 -void CV_InitUndistortRectifyMapTest::run_func()
 +
 +void CV_UndistortTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
 +{
 +    RNG& rng = ts->get_rng();
 +    CV_ImgWarpBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
 +    int type = types[INPUT][0];
 +    type = CV_MAKETYPE( CV_8U, CV_MAT_CN(type) );
 +    types[INPUT][0] = types[INPUT_OUTPUT][0] = types[REF_INPUT_OUTPUT][0] = type;
 +    types[INPUT][1] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
 +    types[INPUT][2] = cvtest::randInt(rng)%2 ? CV_64F : CV_32F;
 +    sizes[INPUT][1] = cvSize(3,3);
 +    sizes[INPUT][2] = cvtest::randInt(rng)%2 ? cvSize(4,1) : cvSize(1,4);
 +    types[INPUT][3] =  types[INPUT][1];
 +    sizes[INPUT][3] = sizes[INPUT][1];
 +    interpolation = CV_INTER_LINEAR;
 +}
 +
 +
 +void CV_UndistortTest::fill_array( int test_case_idx, int i, int j, Mat& arr )
  {
 -    if (useCPlus)
 +    if( i != INPUT )
 +        CV_ImgWarpBaseTest::fill_array( test_case_idx, i, j, arr );
 +}
 +
 +
 +void CV_UndistortTest::run_func()
 +{
 +    if (zero_distortion)
      {
 -        cv::Mat input2,input3,input4;
 -        input2 = zero_distortion ? cv::Mat() : test_mat[INPUT][2];
 -        input3 = zero_R ? cv::Mat() : test_mat[INPUT][3];
 -        input4 = zero_new_cam ? cv::Mat() : test_mat[INPUT][4];
 -        cv::initUndistortRectifyMap(camera_mat,input2,input3,input4,img_size,mat_type,mapx,mapy);
 +        cv::undistort(input0,input_output,input1,cv::Mat());
      }
      else
      {
Simple merge
Simple merge
Simple merge
index 419c4df,0000000..ef2cee0
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,129 @@@
-     assert(ID >= 0 && ID < (int)(sizeof(openclamdblas_fn)/sizeof(openclamdblas_fn[0])));
 +/*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) 2010-2013, Advanced Micro Devices, 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 OpenCV Foundation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (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"
 +
 +#ifdef HAVE_CLAMDBLAS
 +
 +#include "opencv2/core/opencl/runtime/opencl_core.hpp"
 +#include "opencv2/core/opencl/runtime/opencl_clblas.hpp"
 +
 +#if defined(_WIN32)
 +#include <windows.h>
 +
 +    static void* WinGetProcAddress(const char* name)
 +    {
 +        static HMODULE opencl_module = NULL;
 +        if (!opencl_module)
 +        {
 +            opencl_module = GetModuleHandleA("clBLAS.dll");
 +            if (!opencl_module)
 +            {
 +                opencl_module = LoadLibraryA("clBLAS.dll");
 +                if (!opencl_module)
 +                    return NULL;
 +            }
 +        }
 +        return (void*)GetProcAddress(opencl_module, name);
 +    }
 +    #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name)
 +#endif // _WIN32
 +
 +#if defined(__linux__)
 +    #include <dlfcn.h>
 +    #include <stdio.h>
 +
 +    static void* GetProcAddress (const char* name)
 +    {
 +        static void* h = NULL;
 +        if (!h)
 +        {
 +            h = dlopen("libclBLAS.so", RTLD_LAZY | RTLD_GLOBAL);
 +            if (!h)
 +                return NULL;
 +        }
 +
 +        return dlsym(h, name);
 +    }
 +    #define CV_CL_GET_PROC_ADDRESS(name) GetProcAddress(name)
 +#endif
 +
 +#ifndef CV_CL_GET_PROC_ADDRESS
 +#ifdef __GNUC__
 +#warning("OPENCV: OpenCL BLAS dynamic library loader: check configuration")
 +#else
 +#pragma message("WARNING: OPENCV: OpenCL BLAS dynamic library loader: check configuration")
 +#endif
 +#define CV_CL_GET_PROC_ADDRESS(name) NULL
 +#endif
 +
 +static void* openclamdblas_check_fn(int ID);
 +
 +#include "runtime_common.hpp"
 +
 +//
 +// BEGIN OF CUSTOM FUNCTIONS
 +//
 +
 +#define CUSTOM_FUNCTION_ID 1000
 +
 +//
 +// END OF CUSTOM FUNCTIONS HERE
 +//
 +
 +#include "autogenerated/opencl_clblas_impl.hpp"
 +
 +static void* openclamdblas_check_fn(int ID)
 +{
++    CV_Assert(ID >= 0 && ID < (int)(sizeof(openclamdblas_fn)/sizeof(openclamdblas_fn[0])));
 +    const struct DynamicFnEntry* e = openclamdblas_fn[ID];
 +    void* func = CV_CL_GET_PROC_ADDRESS(e->fnName);
 +    if (!func)
 +    {
 +        throw cv::Exception(cv::Error::OpenCLApiCallError,
 +                cv::format("OpenCL AMD BLAS function is not available: [%s]", e->fnName),
 +                CV_Func, __FILE__, __LINE__);
 +    }
 +    *(e->ppFn) = func;
 +    return func;
 +}
 +
 +#endif
index 44e7466,0000000..3272cd9
mode 100644,000000..100644
--- /dev/null
@@@ -1,129 -1,0 +1,129 @@@
-     assert(ID >= 0 && ID < (int)(sizeof(openclamdfft_fn)/sizeof(openclamdfft_fn[0])));
 +/*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) 2010-2013, Advanced Micro Devices, 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 OpenCV Foundation or contributors be liable for any direct,
 +// indirect, incidental, special, exemplary, or consequential damages
 +// (including, but not limited to, procurement of substitute goods or services;
 +// loss of use, data, or profits; or business interruption) however caused
 +// and on any theory of liability, whether in contract, strict liability,
 +// or tort (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"
 +
 +#ifdef HAVE_CLAMDFFT
 +
 +#include "opencv2/core/opencl/runtime/opencl_core.hpp"
 +#include "opencv2/core/opencl/runtime/opencl_clfft.hpp"
 +
 +#if defined(_WIN32)
 +#include <windows.h>
 +
 +    static void* WinGetProcAddress(const char* name)
 +    {
 +        static HMODULE opencl_module = NULL;
 +        if (!opencl_module)
 +        {
 +            opencl_module = GetModuleHandleA("clFFT.dll");
 +            if (!opencl_module)
 +            {
 +                opencl_module = LoadLibraryA("clFFT.dll");
 +                if (!opencl_module)
 +                    return NULL;
 +            }
 +        }
 +        return (void*)GetProcAddress(opencl_module, name);
 +    }
 +    #define CV_CL_GET_PROC_ADDRESS(name) WinGetProcAddress(name)
 +#endif // _WIN32
 +
 +#if defined(__linux__)
 +    #include <dlfcn.h>
 +    #include <stdio.h>
 +
 +    static void* GetProcAddress (const char* name)
 +    {
 +        static void* h = NULL;
 +        if (!h)
 +        {
 +            h = dlopen("libclFFT.so", RTLD_LAZY | RTLD_GLOBAL);
 +            if (!h)
 +                return NULL;
 +        }
 +
 +        return dlsym(h, name);
 +    }
 +    #define CV_CL_GET_PROC_ADDRESS(name) GetProcAddress(name)
 +#endif
 +
 +#ifndef CV_CL_GET_PROC_ADDRESS
 +#ifdef __GNUC__
 +#warning("OPENCV: OpenCL FFT dynamic library loader: check configuration")
 +#else
 +#pragma message("WARNING: OPENCV: OpenCL FFT dynamic library loader: check configuration")
 +#endif
 +#define CV_CL_GET_PROC_ADDRESS(name) NULL
 +#endif
 +
 +static void* openclamdfft_check_fn(int ID);
 +
 +#include "runtime_common.hpp"
 +
 +//
 +// BEGIN OF CUSTOM FUNCTIONS
 +//
 +
 +#define CUSTOM_FUNCTION_ID 1000
 +
 +//
 +// END OF CUSTOM FUNCTIONS HERE
 +//
 +
 +#include "autogenerated/opencl_clfft_impl.hpp"
 +
 +static void* openclamdfft_check_fn(int ID)
 +{
++    CV_Assert(ID >= 0 && ID < (int)(sizeof(openclamdfft_fn)/sizeof(openclamdfft_fn[0])));
 +    const struct DynamicFnEntry* e = openclamdfft_fn[ID];
 +    void* func = CV_CL_GET_PROC_ADDRESS(e->fnName);
 +    if (!func)
 +    {
 +        throw cv::Exception(cv::Error::OpenCLApiCallError,
 +                cv::format("OpenCL AMD FFT function is not available: [%s]", e->fnName),
 +                CV_Func, __FILE__, __LINE__);
 +    }
 +    *(e->ppFn) = func;
 +    return func;
 +}
 +
 +#endif
Simple merge
@@@ -50,811 -85,953 +50,811 @@@ public
              }
              else
              {
 -                int l = (int)strlen(ptr);
 -                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !icvEof(fs) )
 -                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
 +                struct_flags = FileNode::EMPTY + (key ? FileNode::MAP : FileNode::SEQ);
 +                //fs->is_first = 0;
              }
 -            fs->lineno++;  // FIXIT doesn't really work with long lines. It must be counted via '\n' or '\r' symbols, not the number of icvGets() calls.
 +
 +            if( !FileNode::isEmptyCollection(struct_flags) )
 +                ptr = fs->flush();
          }
 -    }
 -    return ptr;
 -}
  
 +        if( !key )
 +            key = "_";
 +        else if( key[0] == '_' && key[1] == '\0' )
 +            CV_Error( cv::Error::StsBadArg, "A single _ is a reserved tag name" );
  
 -static void icvXMLGetMultilineStringContent(CvFileStorage* fs,
 -    char* ptr, char* &beg, char* &end)
 -{
 -    ptr = icvXMLSkipSpaces(fs, ptr, CV_XML_INSIDE_TAG);
 -    beg = ptr;
 -    end = ptr;
 -    if ( fs->dummy_eof )
 -        return ; /* end of file */
 -
 -    if ( *beg == '<' )
 -        return; /* end of string */
 -
 -    /* find end */
 -    while( cv_isprint(*ptr) ) /* no check for base64 string */
 -        ++ ptr;
 -    if ( *ptr == '\0' )
 -        CV_PARSE_ERROR( "Unexpected end of line" );
 -
 -    end = ptr;
 -}
 -
 +        len = (int)strlen( key );
 +        *ptr++ = '<';
 +        if( tag_type == CV_XML_CLOSING_TAG )
 +        {
 +            if( !attrlist.empty() )
 +                CV_Error( cv::Error::StsBadArg, "Closing tag should not include any attributes" );
 +            *ptr++ = '/';
 +        }
  
 -static char* icvXMLParseBase64(CvFileStorage* fs, char* ptr, CvFileNode * node)
 -{
 -    char * beg = 0;
 -    char * end = 0;
 +        if( !cv_isalpha(key[0]) && key[0] != '_' )
 +            CV_Error( cv::Error::StsBadArg, "Key should start with a letter or _" );
  
 -    icvXMLGetMultilineStringContent(fs, ptr, beg, end);
 -    if (beg >= end)
 -        return end; // CV_PARSE_ERROR("Empty Binary Data");
 +        ptr = fs->resizeWriteBuffer( ptr, len );
 +        for( i = 0; i < len; i++ )
 +        {
 +            char c = key[i];
 +            if( !cv_isalnum(c) && c != '_' && c != '-' )
 +                CV_Error( cv::Error::StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );
 +            ptr[i] = c;
 +        }
 +        ptr += len;
  
 -    /* calc (decoded) total_byte_size from header */
 -    std::string dt;
 -    {
 -        if (end - beg < static_cast<int>(base64::ENCODED_HEADER_SIZE))
 -            CV_PARSE_ERROR("Unrecognized Base64 header");
 +        int nattr = (int)attrlist.size();
 +        CV_Assert( nattr % 2 == 0 );
  
 -        std::vector<char> header(base64::HEADER_SIZE + 1, ' ');
 -        base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE);
 -        if ( !base64::read_base64_header(header, dt) || dt.empty() )
 -            CV_PARSE_ERROR("Invalid `dt` in Base64 header");
 +        for( i = 0; i < nattr; i += 2 )
 +        {
 +            size_t len0 = attrlist[i].size();
 +            size_t len1 = attrlist[i+1].size();
 +            CV_Assert( len0 > 0 );
  
 -        beg += base64::ENCODED_HEADER_SIZE;
 -    }
 +            ptr = fs->resizeWriteBuffer( ptr, (int)(len0 + len1 + 4) );
 +            *ptr++ = ' ';
  
 -    /* get all Base64 data */
 -    std::string base64_buffer; // not an efficient way.
 -    base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE );
 -    while( beg < end )
 -    {
 -        base64_buffer.append( beg, end );
 -        beg = end;
 -        icvXMLGetMultilineStringContent( fs, beg, beg, end );
 -    }
 -    if ( base64_buffer.empty() ||
 -         !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) )
 -        CV_PARSE_ERROR( "Invalid Base64 data." );
 -
 -    /* alloc buffer for all decoded data(include header) */
 -    std::vector<uchar> binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) );
 -    int total_byte_size = static_cast<int>(
 -        base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false )
 -        );
 -    {
 -        base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() );
 -        const uchar * buffer_beg = reinterpret_cast<const uchar *>( base64_buffer.data() );
 -        const uchar * buffer_end = buffer_beg + base64_buffer.size();
 -        parser.read( buffer_beg, buffer_end );
 -        parser.flush();
 -    }
 +            memcpy( ptr, attrlist[i].c_str(), len0 );
 +            ptr += len0;
 +            *ptr++ = '=';
 +            *ptr++ = '\"';
 +            if( len1 > 0 )
 +                memcpy( ptr, attrlist[i+1].c_str(), len1 );
 +            ptr += len1;
 +            *ptr++ = '\"';
 +        }
  
 -    node->tag = CV_NODE_NONE;
 -    int struct_flags = CV_NODE_SEQ;
 -    /* after icvFSCreateCollection, node->tag == struct_flags */
 -    icvFSCreateCollection(fs, struct_flags, node);
 -    base64::make_seq(fs, binary_buffer.data(), total_byte_size, dt.c_str(), *node->data.seq);
 -
 -    if (fs->dummy_eof) {
 -        /* end of file */
 -        return fs->buffer_start;
 -    } else {
 -        /* end of line */
 -        return end;
 +        if( tag_type == CV_XML_EMPTY_TAG )
 +            *ptr++ = '/';
 +        *ptr++ = '>';
 +        fs->setBufferPtr(ptr);
 +        current_struct.flags = struct_flags & ~FileNode::EMPTY;
      }
 -}
  
 -
 -static char*
 -icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
 -                CvAttrList** _list, int* _tag_type );
 -
 -static char*
 -icvXMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
 -                  int value_type CV_DEFAULT(CV_NODE_NONE))
 -{
 -    CvFileNode *elem = node;
 -    bool have_space = true, is_simple = true;
 -    int is_user_type = CV_NODE_IS_USER(value_type);
 -    memset( node, 0, sizeof(*node) );
 -
 -    value_type = CV_NODE_TYPE(value_type);
 -
 -    for(;;)
 +    FStructData startWriteStruct(const FStructData& parent, const char* key,
 +                                 int struct_flags, const char* type_name=0)
      {
 -        char c = *ptr, d;
 -        char* endptr;
 -
 -        if( cv_isspace(c) || c == '\0' || (c == '<' && ptr[1] == '!' && ptr[2] == '-') )  // FIXIT ptr[1], ptr[2] - out of bounds read without check or data fetch (#11061)
 +        std::vector<std::string> attrlist;
 +        if( type_name && *type_name )
          {
 -            ptr = icvXMLSkipSpaces( fs, ptr, 0 );
 -            have_space = true;
 -            c = *ptr;
 +            attrlist.push_back("type_id");
 +            attrlist.push_back(type_name);
          }
  
 -        d = ptr[1];  // FIXIT ptr[1] - out of bounds read without check or data fetch (#11061)
 +        writeTag( key, CV_XML_OPENING_TAG, attrlist );
  
 -        if( c =='<' || c == '\0' )
 -        {
 -            CvStringHashNode *key = 0, *key2 = 0;
 -            CvAttrList* list = 0;
 -            CvTypeInfo* info = 0;
 -            int tag_type = 0;
 -            int is_noname = 0;
 -            const char* type_name = 0;
 -            int elem_type = CV_NODE_NONE;
 -
 -            if( d == '/' || c == '\0' )
 -                break;
 +        FStructData current_struct;
 +        current_struct.tag = key ? std::string(key) : std::string();
 +        current_struct.flags = struct_flags;
 +        current_struct.indent = parent.indent + CV_XML_INDENT;
  
 -            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
 +        return current_struct;
 +    }
  
 -            if( tag_type == CV_XML_DIRECTIVE_TAG )
 -                CV_PARSE_ERROR( "Directive tags are not allowed here" );
 -            if( tag_type == CV_XML_EMPTY_TAG )
 -                CV_PARSE_ERROR( "Empty tags are not supported" );
 +    void endWriteStruct(const FStructData& current_struct)
 +    {
 +        writeTag( current_struct.tag.c_str(), CV_XML_CLOSING_TAG );
 +    }
  
 -            CV_Assert(tag_type == CV_XML_OPENING_TAG);
 +    void write(const char* key, int value)
 +    {
 +        char buf[128], *ptr = fs::itoa( value, buf, 10 );
 +        writeScalar( key, ptr);
 +    }
  
 -            /* for base64 string */
 -            bool is_binary_string = false;
 +    void write( const char* key, double value )
 +    {
 +        char buf[128];
 +        writeScalar( key, fs::doubleToString( buf, value, false ) );
 +    }
  
 -            type_name = list ? cvAttrValue( list, "type_id" ) : 0;
 -            if( type_name )
 -            {
 -                if( strcmp( type_name, "str" ) == 0 )
 -                    elem_type = CV_NODE_STRING;
 -                else if( strcmp( type_name, "map" ) == 0 )
 -                    elem_type = CV_NODE_MAP;
 -                else if( strcmp( type_name, "seq" ) == 0 )
 -                    elem_type = CV_NODE_SEQ;
 -                else if (strcmp(type_name, "binary") == 0)
 -                {
 -                    elem_type = CV_NODE_NONE;
 -                    is_binary_string = true;
 -                }
 -                else
 -                {
 -                    info = cvFindType( type_name );
 -                    if( info )
 -                        elem_type = CV_NODE_USER;
 -                }
 -            }
 +    void write(const char* key, const char* str, bool quote)
 +    {
 +        char buf[CV_FS_MAX_LEN*6+16];
 +        char* data = (char*)str;
 +        int i, len;
  
 -            is_noname = key->str.len == 1 && key->str.ptr[0] == '_';
 -            if( !CV_NODE_IS_COLLECTION(node->tag) )
 -            {
 -                icvFSCreateCollection( fs, is_noname ? CV_NODE_SEQ : CV_NODE_MAP, node );
 -            }
 -            else if( is_noname ^ CV_NODE_IS_SEQ(node->tag) )
 -                CV_PARSE_ERROR( is_noname ? "Map element should have a name" :
 -                              "Sequence element should not have name (use <_></_>)" );
 +        if( !str )
 +            CV_Error( cv::Error::StsNullPtr, "Null string pointer" );
  
 -            if( is_noname )
 -                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
 -            else
 -                elem = cvGetFileNode( fs, node, key, 1 );
 -            CV_Assert(elem);
 -            if (!is_binary_string)
 -                ptr = icvXMLParseValue( fs, ptr, elem, elem_type);
 -            else {
 -                /* for base64 string */
 -                ptr = icvXMLParseBase64( fs, ptr, elem);
 -                ptr = icvXMLSkipSpaces( fs, ptr, 0 );
 -            }
 +        len = (int)strlen(str);
 +        if( len > CV_FS_MAX_LEN )
 +            CV_Error( cv::Error::StsBadArg, "The written string is too long" );
  
 -            if( !is_noname )
 -                elem->tag |= CV_NODE_NAMED;
 -            is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag);
 -            elem->info = info;
 -            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
 -            if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
 -                CV_PARSE_ERROR( "Mismatched closing tag" );
 -            have_space = true;
 -        }
 -        else
 +        if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
          {
 -            if( !have_space )
 -                CV_PARSE_ERROR( "There should be space between literals" );
 -
 -            elem = node;
 -            if( node->tag != CV_NODE_NONE )
 +            bool need_quote = quote || len == 0;
 +            data = buf;
 +            *data++ = '\"';
 +            for( i = 0; i < len; i++ )
              {
 -                if( !CV_NODE_IS_COLLECTION(node->tag) )
 -                    icvFSCreateCollection( fs, CV_NODE_SEQ, node );
 -
 -                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
 -                elem->info = 0;
 -            }
 +                char c = str[i];
  
 -            if( value_type != CV_NODE_STRING &&
 -                (cv_isdigit(c) || ((c == '-' || c == '+') &&
 -                (cv_isdigit(d) || d == '.')) || (c == '.' && cv_isalnum(d))) ) // a number
 -            {
 -                double fval;
 -                int ival;
 -                endptr = ptr + (c == '-' || c == '+');
 -                while( cv_isdigit(*endptr) )
 -                    endptr++;
 -                if( *endptr == '.' || *endptr == 'e' )
 +                if( (uchar)c >= 128 || c == ' ' )
                  {
 -                    fval = icv_strtod( fs, ptr, &endptr );
 -                    /*if( endptr == ptr || cv_isalpha(*endptr) )
 -                        icvProcessSpecialDouble( fs, ptr, &fval, &endptr ));*/
 -                    elem->tag = CV_NODE_REAL;
 -                    elem->data.f = fval;
 +                    *data++ = c;
 +                    need_quote = true;
                  }
 -                else
 +                else if( !cv_isprint(c) || c == '<' || c == '>' || c == '&' || c == '\'' || c == '\"' )
                  {
 -                    ival = (int)strtol( ptr, &endptr, 0 );
 -                    elem->tag = CV_NODE_INT;
 -                    elem->data.i = ival;
 -                }
 -
 -                if( endptr == ptr )
 -                    CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
 -
 -                ptr = endptr;
 -                CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 -            }
 -            else
 -            {
 -                // string
 -                char buf[CV_FS_MAX_LEN+16] = {0};
 -                int i = 0, len, is_quoted = 0;
 -                elem->tag = CV_NODE_STRING;
 -                if( c == '\"' )
 -                    is_quoted = 1;
 -                else
 -                    --ptr;
 -
 -                for( ;; )
 -                {
 -                    c = *++ptr;
 -                    CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 -                    if( !cv_isalnum(c) )
 +                    *data++ = '&';
 +                    if( c == '<' )
                      {
 -                        if( c == '\"' )
 -                        {
 -                            if( !is_quoted )
 -                                CV_PARSE_ERROR( "Literal \" is not allowed within a string. Use &quot;" );
 -                            ++ptr;
 -                            break;
 -                        }
 -                        else if( !cv_isprint(c) || c == '<' || (!is_quoted && cv_isspace(c)))
 -                        {
 -                            if( is_quoted )
 -                                CV_PARSE_ERROR( "Closing \" is expected" );
 -                            break;
 -                        }
 -                        else if( c == '\'' || c == '>' )
 -                        {
 -                            CV_PARSE_ERROR( "Literal \' or > are not allowed. Use &apos; or &gt;" );
 -                        }
 -                        else if( c == '&' )
 -                        {
 -                            if( *++ptr == '#' )
 -                            {
 -                                int val, base = 10;
 -                                ptr++;
 -                                if( *ptr == 'x' )
 -                                {
 -                                    base = 16;
 -                                    ptr++;
 -                                }
 -                                val = (int)strtol( ptr, &endptr, base );
 -                                if( (unsigned)val > (unsigned)255 ||
 -                                    !endptr || *endptr != ';' )
 -                                    CV_PARSE_ERROR( "Invalid numeric value in the string" );
 -                                c = (char)val;
 -                            }
 -                            else
 -                            {
 -                                endptr = ptr;
 -                                do c = *++endptr;
 -                                while( cv_isalnum(c) );
 -                                if( c != ';' )
 -                                    CV_PARSE_ERROR( "Invalid character in the symbol entity name" );
 -                                len = (int)(endptr - ptr);
 -                                if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
 -                                    c = '<';
 -                                else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
 -                                    c = '>';
 -                                else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
 -                                    c = '&';
 -                                else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
 -                                    c = '\'';
 -                                else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
 -                                    c = '\"';
 -                                else
 -                                {
 -                                    memcpy( buf + i, ptr-1, len + 2 );
 -                                    i += len + 2;
 -                                }
 -                            }
 -                            ptr = endptr;
 -                            CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 -                        }
 +                        memcpy(data, "lt", 2);
 +                        data += 2;
 +                    }
 +                    else if( c == '>' )
 +                    {
 +                        memcpy(data, "gt", 2);
 +                        data += 2;
 +                    }
 +                    else if( c == '&' )
 +                    {
 +                        memcpy(data, "amp", 3);
 +                        data += 3;
                      }
 -                    buf[i++] = c;
 -                    if( i >= CV_FS_MAX_LEN )
 -                        CV_PARSE_ERROR( "Too long string literal" );
 +                    else if( c == '\'' )
 +                    {
 +                        memcpy(data, "apos", 4);
 +                        data += 4;
 +                    }
 +                    else if( c == '\"' )
 +                    {
 +                        memcpy( data, "quot", 4);
 +                        data += 4;
 +                    }
 +                    else
 +                    {
 +                        sprintf( data, "#x%02x", (uchar)c );
 +                        data += 4;
 +                    }
 +                    *data++ = ';';
 +                    need_quote = 1;
                  }
 -                elem->data.str = cvMemStorageAllocString( fs->memstorage, buf, i );
 +                else
 +                    *data++ = c;
              }
 -
 -            if( !CV_NODE_IS_COLLECTION(value_type) && value_type != CV_NODE_NONE )
 -                break;
 -            have_space = false;
 +            if( !need_quote && (cv_isdigit(str[0]) ||
 +                                str[0] == '+' || str[0] == '-' || str[0] == '.' ))
 +                need_quote = true;
 +
 +            if( need_quote )
 +                *data++ = '\"';
 +            len = (int)(data - buf) - !need_quote;
 +            *data++ = '\0';
 +            data = buf + (int)!need_quote;
          }
 -    }
  
 -    if( (CV_NODE_TYPE(node->tag) == CV_NODE_NONE ||
 -        (CV_NODE_TYPE(node->tag) != value_type &&
 -        !CV_NODE_IS_COLLECTION(node->tag))) &&
 -        CV_NODE_IS_COLLECTION(value_type) )
 -    {
 -        icvFSCreateCollection( fs, CV_NODE_IS_MAP(value_type) ?
 -                                        CV_NODE_MAP : CV_NODE_SEQ, node );
 +        writeScalar( key, data );
      }
  
 -    if( value_type != CV_NODE_NONE &&
 -        value_type != CV_NODE_TYPE(node->tag) )
 -        CV_PARSE_ERROR( "The actual type is different from the specified type" );
 -
 -    if( CV_NODE_IS_COLLECTION(node->tag) && is_simple )
 -            node->data.seq->flags |= CV_NODE_SEQ_SIMPLE;
 -
 -    node->tag |= is_user_type ? CV_NODE_USER : 0;
 -    return ptr;
 -}
 -
 -
 -static char*
 -icvXMLParseTag( CvFileStorage* fs, char* ptr, CvStringHashNode** _tag,
 -                CvAttrList** _list, int* _tag_type )
 -{
 -    int tag_type = 0;
 -    CvStringHashNode* tagname = 0;
 -    CvAttrList *first = 0, *last = 0;
 -    int count = 0, max_count = 4;
 -    int attr_buf_size = (max_count*2 + 1)*sizeof(char*) + sizeof(CvAttrList);
 -    char* endptr;
 -    char c;
 -    int have_space;
 -
 -    if( *ptr == '\0' )
 -        CV_PARSE_ERROR( "Preliminary end of the stream" );
 -
 -    if( *ptr != '<' )
 -        CV_PARSE_ERROR( "Tag should start with \'<\'" );
 -
 -    ptr++;
 -    CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 -    if( cv_isalnum(*ptr) || *ptr == '_' )
 -        tag_type = CV_XML_OPENING_TAG;
 -    else if( *ptr == '/' )
 -    {
 -        tag_type = CV_XML_CLOSING_TAG;
 -        ptr++;
 -    }
 -    else if( *ptr == '?' )
 -    {
 -        tag_type = CV_XML_HEADER_TAG;
 -        ptr++;
 -    }
 -    else if( *ptr == '!' )
 +    void writeScalar(const char* key, const char* data)
      {
 -        tag_type = CV_XML_DIRECTIVE_TAG;
 -        CV_Assert( ptr[1] != '-' || ptr[2] != '-' );
 -        ptr++;
 -    }
 -    else
 -        CV_PARSE_ERROR( "Unknown tag type" );
 -
 -    for(;;)
 -    {
 -        CvStringHashNode* attrname;
 -
 -        if( !cv_isalpha(*ptr) && *ptr != '_' )
 -            CV_PARSE_ERROR( "Name should start with a letter or underscore" );
 +        fs->check_if_write_struct_is_delayed(false);
 +        if ( fs->get_state_of_writing_base64() == FileStorage_API::Uncertain )
 +        {
 +            fs->switch_to_Base64_state( FileStorage_API::NotUse );
 +        }
 +        else if ( fs->get_state_of_writing_base64() == FileStorage_API::InUse )
 +        {
 +            CV_Error( cv::Error::StsError, "At present, output Base64 data only." );
 +        }
  
 -        endptr = ptr - 1;
 -        do c = *++endptr;
 -        while( cv_isalnum(c) || c == '_' || c == '-' );
 +        int len = (int)strlen(data);
 +        if( key && *key == '\0' )
 +            key = 0;
  
 -        attrname = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
 -        CV_Assert(attrname);
 -        ptr = endptr;
 -        CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 +        FStructData& current_struct = fs->getCurrentStruct();
 +        int struct_flags = current_struct.flags;
  
 -        if( !tagname )
 -            tagname = attrname;
 -        else
 +        if( FileNode::isMap(struct_flags) ||
 +           (!FileNode::isCollection(struct_flags) && key) )
          {
 -            if( tag_type == CV_XML_CLOSING_TAG )
 -                CV_PARSE_ERROR( "Closing tag should not contain any attributes" );
 -
 -            if( !last || count >= max_count )
 -            {
 -                CvAttrList* chunk;
 -
 -                chunk = (CvAttrList*)cvMemStorageAlloc( fs->memstorage, attr_buf_size );
 -                memset( chunk, 0, attr_buf_size );
 -                chunk->attr = (const char**)(chunk + 1);
 -                count = 0;
 -                if( !last )
 -                    first = last = chunk;
 -                else
 -                    last = last->next = chunk;
 -            }
 -            last->attr[count*2] = attrname->str.ptr;
 +            writeTag( key, CV_XML_OPENING_TAG );
 +            char* ptr = fs->resizeWriteBuffer( fs->bufferPtr(), len );
 +            memcpy( ptr, data, len );
 +            fs->setBufferPtr( ptr + len );
 +            writeTag( key, CV_XML_CLOSING_TAG );
          }
 -
 -        if( last )
 +        else
          {
 -            CvFileNode stub;
 +            char* ptr = fs->bufferPtr();
 +            int new_offset = (int)(ptr - fs->bufferStart()) + len;
  
 -            if( *ptr != '=' )
 -            {
 -                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
 -                if( *ptr != '=' )
 -                    CV_PARSE_ERROR( "Attribute name should be followed by \'=\'" );
 -            }
 +            if( key )
 +                CV_Error( cv::Error::StsBadArg, "elements with keys can not be written to sequence" );
 +
 +            current_struct.flags = FileNode::SEQ;
  
 -            c = *++ptr;
 -            if( c != '\"' && c != '\'' )
 +            if( (new_offset > fs->wrapMargin() && new_offset - current_struct.indent > 10) ||
 +               (ptr > fs->bufferStart() && ptr[-1] == '>') )
              {
 -                ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
 -                if( *ptr != '\"' && *ptr != '\'' )
 -                    CV_PARSE_ERROR( "Attribute value should be put into single or double quotes" );
 +                ptr = fs->flush();
              }
 +            else if( ptr > fs->bufferStart() + current_struct.indent && ptr[-1] != '>' )
 +                *ptr++ = ' ';
  
 -            ptr = icvXMLParseValue( fs, ptr, &stub, CV_NODE_STRING );
 -            CV_Assert( stub.tag == CV_NODE_STRING );
 -            last->attr[count*2+1] = stub.data.str.ptr;
 -            count++;
 +            memcpy( ptr, data, len );
 +            fs->setBufferPtr(ptr + len);
          }
 +    }
  
 -        c = *ptr;
 -        have_space = cv_isspace(c) || c == '\0';
 -
 -        if( c != '>' )
 -        {
 -            ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
 -            c = *ptr;
 -        }
 +    void writeComment(const char* comment, bool eol_comment)
 +    {
 +        FStructData& current_struct = fs->getCurrentStruct();
 +        int len;
 +        int multiline;
 +        const char* eol;
 +        char* ptr;
 +
 +        if( !comment )
 +            CV_Error( cv::Error::StsNullPtr, "Null comment" );
 +
 +        if( strstr(comment, "--") != 0 )
 +            CV_Error( cv::Error::StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
 +
 +        len = (int)strlen(comment);
 +        eol = strchr(comment, '\n');
 +        multiline = eol != 0;
 +        ptr = fs->bufferPtr();
 +
 +        if( multiline || !eol_comment || fs->bufferEnd() - ptr < len + 5 )
 +            ptr = fs->flush();
 +        else if( ptr > fs->bufferStart() + current_struct.indent )
 +            *ptr++ = ' ';
  
 -        if( c == '>' )
 +        if( !multiline )
          {
 -            if( tag_type == CV_XML_HEADER_TAG )
 -                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
 -            ptr++;
 -            break;
 +            ptr = fs->resizeWriteBuffer( ptr, len + 9 );
 +            sprintf( ptr, "<!-- %s -->", comment );
 +            len = (int)strlen(ptr);
          }
 -        else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
 +        else
          {
 -            if( ptr[1] != '>'  )  // FIXIT ptr[1] - out of bounds read without check
 -                CV_PARSE_ERROR( "Invalid closing tag for <?xml ..." );
 -            ptr += 2;
 -            break;
 +            strcpy( ptr, "<!--" );
 +            len = 4;
          }
 -        else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )  // FIXIT ptr[1] - out of bounds read without check
 +
 +        fs->setBufferPtr(ptr + len);
 +        ptr = fs->flush();
 +
 +        if( multiline )
          {
 -            tag_type = CV_XML_EMPTY_TAG;
 -            ptr += 2;
 -            break;
 +            while( comment )
 +            {
 +                if( eol )
 +                {
 +                    ptr = fs->resizeWriteBuffer( ptr, (int)(eol - comment) + 1 );
 +                    memcpy( ptr, comment, eol - comment + 1 );
 +                    ptr += eol - comment;
 +                    comment = eol + 1;
 +                    eol = strchr( comment, '\n' );
 +                }
 +                else
 +                {
 +                    len = (int)strlen(comment);
 +                    ptr = fs->resizeWriteBuffer( ptr, len );
 +                    memcpy( ptr, comment, len );
 +                    ptr += len;
 +                    comment = 0;
 +                }
 +                fs->setBufferPtr(ptr);
 +                ptr = fs->flush();
 +            }
 +            sprintf( ptr, "-->" );
 +            fs->setBufferPtr(ptr + 3);
 +            fs->flush();
          }
 -
 -        if( !have_space )
 -            CV_PARSE_ERROR( "There should be space between attributes" );
      }
  
 -    *_tag = tagname;
 -    *_tag_type = tag_type;
 -    *_list = first;
 -
 -    return ptr;
 -}
 +    void startNextStream()
 +    {
 +        fs->puts( "\n<!-- next stream -->\n" );
 +    }
  
 +protected:
 +    FileStorage_API* fs;
 +};
  
 -void icvXMLParse( CvFileStorage* fs )
 +class XMLParser : public FileStorageParser
  {
 -    char* ptr = fs->buffer_start;
 -    CvStringHashNode *key = 0, *key2 = 0;
 -    CvAttrList* list = 0;
 -    int tag_type = 0;
 -
 -    // CV_XML_INSIDE_TAG is used to prohibit leading comments
 -    ptr = icvXMLSkipSpaces( fs, ptr, CV_XML_INSIDE_TAG );
 -
 -    if( memcmp( ptr, "<?xml", 5 ) != 0 )  // FIXIT ptr[1..] - out of bounds read without check
 -        CV_PARSE_ERROR( "Valid XML should start with \'<?xml ...?>\'" );
 -
 -    ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
 -
 -    /*{
 -        const char* version = cvAttrValue( list, "version" );
 -        if( version && strncmp( version, "1.", 2 ) != 0 )
 -            CV_Error( CV_StsParseError, "Unsupported version of XML" );
 -    }*/
 -    // we support any 8-bit encoding, so we do not need to check the actual encoding.
 -    // we do not support utf-16, but in the case of utf-16 we will not get here anyway.
 -    /*{
 -        const char* encoding = cvAttrValue( list, "encoding" );
 -        if( encoding && strcmp( encoding, "ASCII" ) != 0 &&
 -            strcmp( encoding, "UTF-8" ) != 0 &&
 -            strcmp( encoding, "utf-8" ) != 0 )
 -            CV_PARSE_ERROR( "Unsupported encoding" );
 -    }*/
 -
 -    while( *ptr != '\0' )
 +public:
 +    XMLParser(FileStorage_API* _fs) : fs(_fs)
      {
 -        ptr = icvXMLSkipSpaces( fs, ptr, 0 );
 -
 -        if( *ptr != '\0' )
 -        {
 -            CvFileNode* root_node;
 -            ptr = icvXMLParseTag( fs, ptr, &key, &list, &tag_type );
 -            if( tag_type != CV_XML_OPENING_TAG ||
 -                !key ||
 -                strcmp(key->str.ptr,"opencv_storage") != 0 )
 -                CV_PARSE_ERROR( "<opencv_storage> tag is missing" );
 -
 -            root_node = (CvFileNode*)cvSeqPush( fs->roots, 0 );
 -            ptr = icvXMLParseValue( fs, ptr, root_node, CV_NODE_NONE );
 -            ptr = icvXMLParseTag( fs, ptr, &key2, &list, &tag_type );
 -            if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
 -                CV_PARSE_ERROR( "</opencv_storage> tag is missing" );
 -            ptr = icvXMLSkipSpaces( fs, ptr, 0 );
 -        }
      }
 -    CV_Assert( fs->dummy_eof != 0 );
 -}
 -
 -
 -/****************************************************************************************\
 -*                                       XML Emitter                                      *
 -\****************************************************************************************/
  
 -#define icvXMLFlush icvFSFlush
 +    virtual ~XMLParser() {}
  
 -static void
 -icvXMLWriteTag( CvFileStorage* fs, const char* key, int tag_type, CvAttrList list )
 -{
 -    char* ptr = fs->buffer;
 -    int i, len = 0;
 -    int struct_flags = fs->struct_flags;
 +    char* skipSpaces( char* ptr, int mode )
 +    {
 +        if (!ptr)
 +            CV_PARSE_ERROR_CPP("Invalid input");
  
 -    if( key && key[0] == '\0' )
 -        key = 0;
 +        int level = 0;
  
 -    if( tag_type == CV_XML_OPENING_TAG || tag_type == CV_XML_EMPTY_TAG )
 -    {
 -        if( CV_NODE_IS_COLLECTION(struct_flags) )
 +        for(;;)
          {
 -            if( CV_NODE_IS_MAP(struct_flags) ^ (key != 0) )
 -                CV_Error( CV_StsBadArg, "An attempt to add element without a key to a map, "
 -                                        "or add element with key to sequence" );
 -        }
 -        else
 -        {
 -            struct_flags = CV_NODE_EMPTY + (key ? CV_NODE_MAP : CV_NODE_SEQ);
 -            fs->is_first = 0;
 -        }
 +            char c;
 +            ptr--;
  
 -        if( !CV_NODE_IS_EMPTY(struct_flags) )
 -            ptr = icvXMLFlush(fs);
 -    }
 +            if( mode == CV_XML_INSIDE_COMMENT )
 +            {
 +                do c = *++ptr;
 +                while( cv_isprint_or_tab(c) && (c != '-' || ptr[1] != '-' || ptr[2] != '>') );
  
 -    if( !key )
 -        key = "_";
 -    else if( key[0] == '_' && key[1] == '\0' )
 -        CV_Error( CV_StsBadArg, "A single _ is a reserved tag name" );
 +                if( c == '-' )
 +                {
-                     assert( ptr[1] == '-' && ptr[2] == '>' );
++                    CV_Assert( ptr[1] == '-' && ptr[2] == '>' );
 +                    mode = 0;
 +                    ptr += 3;
 +                }
 +            }
 +            else if( mode == CV_XML_INSIDE_DIRECTIVE )
 +            {
 +                // !!!NOTE!!! This is not quite correct, but should work in most cases
 +                do
 +                {
 +                    c = *++ptr;
 +                    level += c == '<';
 +                    level -= c == '>';
 +                    if( level < 0 )
 +                        return ptr;
 +                } while( cv_isprint_or_tab(c) );
 +            }
 +            else
 +            {
 +                do c = *++ptr;
 +                while( c == ' ' || c == '\t' );
  
 -    len = (int)strlen( key );
 -    *ptr++ = '<';
 -    if( tag_type == CV_XML_CLOSING_TAG )
 -    {
 -        if( list.attr )
 -            CV_Error( CV_StsBadArg, "Closing tag should not include any attributes" );
 -        *ptr++ = '/';
 -    }
 +                if( c == '<' && ptr[1] == '!' && ptr[2] == '-' && ptr[3] == '-' )
 +                {
 +                    if( mode != 0 )
 +                        CV_PARSE_ERROR_CPP( "Comments are not allowed here" );
 +                    mode = CV_XML_INSIDE_COMMENT;
 +                    ptr += 4;
 +                }
 +                else if( cv_isprint(c) )
 +                    break;
 +            }
  
 -    if( !cv_isalpha(key[0]) && key[0] != '_' )
 -        CV_Error( CV_StsBadArg, "Key should start with a letter or _" );
 +            if( !cv_isprint(*ptr) )
 +            {
 +                if( *ptr != '\0' && *ptr != '\n' && *ptr != '\r' )
 +                    CV_PARSE_ERROR_CPP( "Invalid character in the stream" );
 +                ptr = fs->gets();
 +                if( !ptr || *ptr == '\0' )
 +                    break;
 +            }
 +        }
 +        return ptr;
 +    }
  
 -    ptr = icvFSResizeWriteBuffer( fs, ptr, len );
 -    for( i = 0; i < len; i++ )
 +    bool getBase64Row(char* ptr, int /*indent*/, char* &beg, char* &end)
      {
 -        char c = key[i];
 -        if( !cv_isalnum(c) && c != '_' && c != '-' )
 -            CV_Error( CV_StsBadArg, "Key name may only contain alphanumeric characters [a-zA-Z0-9], '-' and '_'" );
 -        ptr[i] = c;
 +        beg = end = ptr = skipSpaces(ptr, CV_XML_INSIDE_TAG);
 +        if( !ptr || !*ptr )
 +            return false;
 +
 +        // closing XML tag
 +        if ( *beg == '<' )
 +            return false;
 +
 +        // find end of the row
 +        while( cv_isprint(*ptr) )
 +            ++ptr;
 +        if ( *ptr == '\0' )
 +            CV_PARSE_ERROR_CPP( "Unexpected end of line" );
 +
 +        end = ptr;
 +        return true;
      }
 -    ptr += len;
  
 -    for(;;)
 +    char* parseValue( char* ptr, FileNode& node )
      {
 -        const char** attr = list.attr;
 +        if (!ptr)
 +            CV_PARSE_ERROR_CPP("Invalid input");
  
 -        for( ; attr && attr[0] != 0; attr += 2 )
 +        FileNode new_elem;
 +        bool have_space = true;
 +        int value_type = node.type();
 +        std::string key, key2, type_name;
 +
 +        for(;;)
          {
 -            int len0 = (int)strlen(attr[0]);
 -            int len1 = (int)strlen(attr[1]);
 +            char c = *ptr, d;
 +            char* endptr;
  
 -            ptr = icvFSResizeWriteBuffer( fs, ptr, len0 + len1 + 4 );
 -            *ptr++ = ' ';
 -            memcpy( ptr, attr[0], len0 );
 -            ptr += len0;
 -            *ptr++ = '=';
 -            *ptr++ = '\"';
 -            memcpy( ptr, attr[1], len1 );
 -            ptr += len1;
 -            *ptr++ = '\"';
 -        }
 -        if( !list.next )
 -            break;
 -        list = *list.next;
 -    }
 +            // FIXIT ptr[1], ptr[2] - out of bounds read without check or data fetch (#11061)
 +            if( cv_isspace(c) || c == '\0' ||
 +                (c == '<' && ptr[1] == '!' && ptr[2] == '-') )
 +            {
 +                ptr = skipSpaces( ptr, 0 );
 +                if (!ptr)
 +                    CV_PARSE_ERROR_CPP("Invalid input");
 +                have_space = true;
 +                c = *ptr;
 +            }
  
 -    if( tag_type == CV_XML_EMPTY_TAG )
 -        *ptr++ = '/';
 -    *ptr++ = '>';
 -    fs->buffer = ptr;
 -    fs->struct_flags = struct_flags & ~CV_NODE_EMPTY;
 -}
 +            d = ptr[1];  // FIXIT ptr[1] - out of bounds read without check or data fetch (#11061)
  
 +            if( c =='<' || c == '\0' )
 +            {
 +                int tag_type = 0;
 +                int elem_type = FileNode::NONE;
  
 -void icvXMLStartWriteStruct( CvFileStorage* fs, const char* key, int struct_flags, const char* type_name)
 -{
 -    CvXMLStackRecord parent;
 -    const char* attr[10];
 -    int idx = 0;
 +                if( d == '/' || c == '\0' )
 +                    break;
  
 -    struct_flags = (struct_flags & (CV_NODE_TYPE_MASK|CV_NODE_FLOW)) | CV_NODE_EMPTY;
 -    if( !CV_NODE_IS_COLLECTION(struct_flags))
 -        CV_Error( CV_StsBadArg,
 -        "Some collection type: CV_NODE_SEQ or CV_NODE_MAP must be specified" );
 +                ptr = parseTag( ptr, key, type_name, tag_type );
  
 -    if ( type_name && *type_name == '\0' )
 -        type_name = 0;
 +                if( tag_type == CV_XML_DIRECTIVE_TAG )
 +                    CV_PARSE_ERROR_CPP( "Directive tags are not allowed here" );
 +                if( tag_type == CV_XML_EMPTY_TAG )
 +                    CV_PARSE_ERROR_CPP( "Empty tags are not supported" );
  
 -    if( type_name )
 -    {
 -        attr[idx++] = "type_id";
 -        attr[idx++] = type_name;
 -    }
 -    attr[idx++] = 0;
 +                CV_Assert(tag_type == CV_XML_OPENING_TAG);
  
 -    icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(attr,0) );
 +                /* for base64 string */
 +                bool binary_string = false;
  
 -    parent.struct_flags = fs->struct_flags & ~CV_NODE_EMPTY;
 -    parent.struct_indent = fs->struct_indent;
 -    parent.struct_tag = fs->struct_tag;
 -    cvSaveMemStoragePos( fs->strstorage, &parent.pos );
 -    cvSeqPush( fs->write_stack, &parent );
 +                if( !type_name.empty() )
 +                {
 +                    const char* tn = type_name.c_str();
 +                    if( strcmp(tn, "str") == 0 )
 +                        elem_type = FileNode::STRING;
 +                    else if( strcmp( tn, "map" ) == 0 )
 +                        elem_type = FileNode::MAP;
 +                    else if( strcmp( tn, "seq" ) == 0 )
 +                        elem_type = FileNode::SEQ;
 +                    else if( strcmp( tn, "binary") == 0)
 +                        binary_string = true;
 +                }
  
 -    fs->struct_indent += CV_XML_INDENT;
 -    if( !CV_NODE_IS_FLOW(struct_flags) )
 -        icvXMLFlush( fs );
 +                new_elem = fs->addNode(node, key, elem_type, 0);
 +                if (!binary_string)
 +                    ptr = parseValue(ptr, new_elem);
 +                else
 +                {
 +                    ptr = fs->parseBase64( ptr, 0, new_elem);
 +                    ptr = skipSpaces( ptr, 0 );
 +                    if (!ptr)
 +                        CV_PARSE_ERROR_CPP("Invalid input");
 +                }
  
 -    fs->struct_flags = struct_flags;
 -    if( key )
 -    {
 -        fs->struct_tag = cvMemStorageAllocString( fs->strstorage, (char*)key, -1 );
 -    }
 -    else
 -    {
 -        fs->struct_tag.ptr = 0;
 -        fs->struct_tag.len = 0;
 -    }
 -}
 +                ptr = parseTag( ptr, key2, type_name, tag_type );
 +                if( tag_type != CV_XML_CLOSING_TAG || key2 != key )
 +                    CV_PARSE_ERROR_CPP( "Mismatched closing tag" );
 +                have_space = true;
 +            }
 +            else
 +            {
 +                if( !have_space )
 +                    CV_PARSE_ERROR_CPP( "There should be space between literals" );
  
 +                FileNode* elem = &node;
 +                if( node.type() != FileNode::NONE )
 +                {
 +                    fs->convertToCollection( FileNode::SEQ, node );
 +                    new_elem = fs->addNode(node, std::string(), FileNode::NONE, 0);
 +                    elem = &new_elem;
 +                }
  
 -void icvXMLEndWriteStruct( CvFileStorage* fs )
 -{
 -    CvXMLStackRecord parent;
 +                if( value_type != FileNode::STRING &&
 +                   (cv_isdigit(c) || ((c == '-' || c == '+') &&
 +                   (cv_isdigit(d) || d == '.')) || (c == '.' && cv_isalnum(d))) ) // a number
 +                {
 +                    endptr = ptr + (c == '-' || c == '+');
 +                    while( cv_isdigit(*endptr) )
 +                        endptr++;
 +                    if( *endptr == '.' || *endptr == 'e' )
 +                    {
 +                        double fval = fs->strtod( ptr, &endptr );
 +                        elem->setValue(FileNode::REAL, &fval);
 +                    }
 +                    else
 +                    {
 +                        int ival = (int)strtol( ptr, &endptr, 0 );
 +                        elem->setValue(FileNode::INT, &ival);
 +                    }
  
 -    if( fs->write_stack->total == 0 )
 -        CV_Error( CV_StsError, "An extra closing tag" );
 +                    if( endptr == ptr )
 +                        CV_PARSE_ERROR_CPP( "Invalid numeric value (inconsistent explicit type specification?)" );
  
 -    icvXMLWriteTag( fs, fs->struct_tag.ptr, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
 -    cvSeqPop( fs->write_stack, &parent );
 +                    ptr = endptr;
 +                    CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
 +                }
 +                else
 +                {
 +                    // string
 +                    int i = 0, len, is_quoted = 0;
 +                    if( c == '\"' )
 +                        is_quoted = 1;
 +                    else
 +                        --ptr;
 +                    strbuf[0] = '\0';
 +
 +                    for( ;; )
 +                    {
 +                        c = *++ptr;
 +                        CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
  
 -    fs->struct_indent = parent.struct_indent;
 -    fs->struct_flags = parent.struct_flags;
 -    fs->struct_tag = parent.struct_tag;
 -    cvRestoreMemStoragePos( fs->strstorage, &parent.pos );
 -}
 +                        if( !cv_isalnum(c) )
 +                        {
 +                            if( c == '\"' )
 +                            {
 +                                if( !is_quoted )
 +                                    CV_PARSE_ERROR_CPP( "Literal \" is not allowed within a string. Use &quot;" );
 +                                ++ptr;
 +                                break;
 +                            }
 +                            else if( !cv_isprint(c) || c == '<' || (!is_quoted && cv_isspace(c)))
 +                            {
 +                                if( is_quoted )
 +                                    CV_PARSE_ERROR_CPP( "Closing \" is expected" );
 +                                break;
 +                            }
 +                            else if( c == '\'' || c == '>' )
 +                            {
 +                                CV_PARSE_ERROR_CPP( "Literal \' or > are not allowed. Use &apos; or &gt;" );
 +                            }
 +                            else if( c == '&' )
 +                            {
 +                                if( *++ptr == '#' )
 +                                {
 +                                    int val, base = 10;
 +                                    ptr++;
 +                                    if( *ptr == 'x' )
 +                                    {
 +                                        base = 16;
 +                                        ptr++;
 +                                    }
 +                                    val = (int)strtol( ptr, &endptr, base );
 +                                    if( (unsigned)val > (unsigned)255 ||
 +                                       !endptr || *endptr != ';' )
 +                                        CV_PARSE_ERROR_CPP( "Invalid numeric value in the string" );
 +                                    c = (char)val;
 +                                }
 +                                else
 +                                {
 +                                    endptr = ptr;
 +                                    do c = *++endptr;
 +                                    while( cv_isalnum(c) );
 +                                    if( c != ';' )
 +                                        CV_PARSE_ERROR_CPP( "Invalid character in the symbol entity name" );
 +                                    len = (int)(endptr - ptr);
 +                                    if( len == 2 && memcmp( ptr, "lt", len ) == 0 )
 +                                        c = '<';
 +                                    else if( len == 2 && memcmp( ptr, "gt", len ) == 0 )
 +                                        c = '>';
 +                                    else if( len == 3 && memcmp( ptr, "amp", len ) == 0 )
 +                                        c = '&';
 +                                    else if( len == 4 && memcmp( ptr, "apos", len ) == 0 )
 +                                        c = '\'';
 +                                    else if( len == 4 && memcmp( ptr, "quot", len ) == 0 )
 +                                        c = '\"';
 +                                    else
 +                                    {
 +                                        if (len + 2 + i >= CV_FS_MAX_LEN)
 +                                            CV_PARSE_ERROR_CPP("string is too long");
 +                                        memcpy( strbuf + i, ptr-1, len + 2 );
 +                                        i += len + 2;
 +                                    }
 +                                }
 +                                ptr = endptr;
 +                                CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
 +                            }
 +                        }
 +                        if (i + 1 >= CV_FS_MAX_LEN)
 +                            CV_PARSE_ERROR_CPP("Too long string literal");
 +                        strbuf[i++] = c;
 +                    }
 +                    elem->setValue(FileNode::STRING, strbuf, i);
 +                }
  
 +                if( value_type != FileNode::NONE && value_type != FileNode::SEQ && value_type != FileNode::MAP )
 +                    break;
 +                have_space = false;
 +            }
 +        }
 +        fs->finalizeCollection(node);
  
 -void icvXMLStartNextStream( CvFileStorage* fs )
 -{
 -    if( !fs->is_first )
 -    {
 -        while( fs->write_stack->total > 0 )
 -            icvXMLEndWriteStruct(fs);
 -
 -        fs->struct_indent = 0;
 -        icvXMLFlush(fs);
 -        /* XML does not allow multiple top-level elements,
 -           so we just put a comment and continue
 -           the current (and the only) "stream" */
 -        icvPuts( fs, "\n<!-- next stream -->\n" );
 -        /*fputs( "</opencv_storage>\n", fs->file );
 -        fputs( "<opencv_storage>\n", fs->file );*/
 -        fs->buffer = fs->buffer_start;
 +        return ptr;
      }
 -}
  
 -
 -void icvXMLWriteScalar( CvFileStorage* fs, const char* key, const char* data, int len )
 -{
 -    check_if_write_struct_is_delayed( fs );
 -    if ( fs->state_of_writing_base64 == base64::fs::Uncertain )
 -    {
 -        switch_to_Base64_state( fs, base64::fs::NotUse );
 -    }
 -    else if ( fs->state_of_writing_base64 == base64::fs::InUse )
 +    char* parseTag( char* ptr, std::string& tag_name,
 +                    std::string& type_name, int& tag_type )
      {
 -        CV_Error( CV_StsError, "Currently only Base64 data is allowed." );
 -    }
 +        if (!ptr)
 +            CV_PARSE_ERROR_CPP("Invalid tag input");
  
 -    if( CV_NODE_IS_MAP(fs->struct_flags) ||
 -        (!CV_NODE_IS_COLLECTION(fs->struct_flags) && key) )
 -    {
 -        icvXMLWriteTag( fs, key, CV_XML_OPENING_TAG, cvAttrList(0,0) );
 -        char* ptr = icvFSResizeWriteBuffer( fs, fs->buffer, len );
 -        memcpy( ptr, data, len );
 -        fs->buffer = ptr + len;
 -        icvXMLWriteTag( fs, key, CV_XML_CLOSING_TAG, cvAttrList(0,0) );
 -    }
 -    else
 -    {
 -        char* ptr = fs->buffer;
 -        int new_offset = (int)(ptr - fs->buffer_start) + len;
 +        if( *ptr == '\0' )
 +            CV_PARSE_ERROR_CPP( "Unexpected end of the stream" );
  
 -        if( key && key[0] != '\0' )
 -            CV_Error( CV_StsBadArg, "elements with keys can not be written to sequence" );
 +        if( *ptr != '<' )
 +            CV_PARSE_ERROR_CPP( "Tag should start with \'<\'" );
  
 -        fs->struct_flags = CV_NODE_SEQ;
 +        ptr++;
 +        CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
  
 -        if( (new_offset > fs->wrap_margin && new_offset - fs->struct_indent > 10) ||
 -            (ptr > fs->buffer_start && ptr[-1] == '>' && !CV_NODE_IS_EMPTY(fs->struct_flags)) )
 +        if( cv_isalnum(*ptr) || *ptr == '_' )
 +            tag_type = CV_XML_OPENING_TAG;
 +        else if( *ptr == '/' )
          {
 -            ptr = icvXMLFlush(fs);
 +            tag_type = CV_XML_CLOSING_TAG;
 +            ptr++;
          }
 -        else if( ptr > fs->buffer_start + fs->struct_indent && ptr[-1] != '>' )
 -            *ptr++ = ' ';
 -
 -        memcpy( ptr, data, len );
 -        fs->buffer = ptr + len;
 -    }
 -}
 -
 -
 -void icvXMLWriteInt( CvFileStorage* fs, const char* key, int value )
 -{
 -    char buf[128], *ptr = icv_itoa( value, buf, 10 );
 -    int len = (int)strlen(ptr);
 -    icvXMLWriteScalar( fs, key, ptr, len );
 -}
 -
 -
 -void icvXMLWriteReal( CvFileStorage* fs, const char* key, double value )
 -{
 -    char buf[128];
 -    int len = (int)strlen( icvDoubleToString( buf, value ));
 -    icvXMLWriteScalar( fs, key, buf, len );
 -}
 +        else if( *ptr == '?' )
 +        {
 +            tag_type = CV_XML_HEADER_TAG;
 +            ptr++;
 +        }
 +        else if( *ptr == '!' )
 +        {
 +            tag_type = CV_XML_DIRECTIVE_TAG;
-             assert( ptr[1] != '-' || ptr[2] != '-' );
++            CV_Assert( ptr[1] != '-' || ptr[2] != '-' );
 +            ptr++;
 +        }
 +        else
 +            CV_PARSE_ERROR_CPP( "Unknown tag type" );
  
 +        tag_name.clear();
 +        type_name.clear();
  
 -void icvXMLWriteString( CvFileStorage* fs, const char* key, const char* str, int quote )
 -{
 -    char buf[CV_FS_MAX_LEN*6+16];
 -    char* data = (char*)str;
 -    int i, len;
 +        for(;;)
 +        {
 +            char c, *endptr;
 +            if( !cv_isalpha(*ptr) && *ptr != '_' )
 +                CV_PARSE_ERROR_CPP( "Name should start with a letter or underscore" );
  
 -    if( !str )
 -        CV_Error( CV_StsNullPtr, "Null string pointer" );
 +            endptr = ptr - 1;
 +            do c = *++endptr;
 +            while( cv_isalnum(c) || c == '_' || c == '-' );
  
 -    len = (int)strlen(str);
 -    if( len > CV_FS_MAX_LEN )
 -        CV_Error( CV_StsBadArg, "The written string is too long" );
 +            std::string attrname(ptr, (size_t)(endptr - ptr));
 +            ptr = endptr;
 +            CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG_CPP();
  
 -    if( quote || len == 0 || str[0] != '\"' || str[0] != str[len-1] )
 -    {
 -        int need_quote = quote || len == 0;
 -        data = buf;
 -        *data++ = '\"';
 -        for( i = 0; i < len; i++ )
 -        {
 -            char c = str[i];
 -
 -            if( (uchar)c >= 128 || c == ' ' )
 -            {
 -                *data++ = c;
 -                need_quote = 1;
 -            }
 -            else if( !cv_isprint(c) || c == '<' || c == '>' || c == '&' || c == '\'' || c == '\"' )
 +            if( tag_name.empty() )
 +                tag_name = attrname;
 +            else
              {
 -                *data++ = '&';
 -                if( c == '<' )
 -                {
 -                    memcpy(data, "lt", 2);
 -                    data += 2;
 -                }
 -                else if( c == '>' )
 -                {
 -                    memcpy(data, "gt", 2);
 -                    data += 2;
 -                }
 -                else if( c == '&' )
 +                if( tag_type == CV_XML_CLOSING_TAG )
 +                    CV_PARSE_ERROR_CPP( "Closing tag should not contain any attributes" );
 +
 +                if( *ptr != '=' )
                  {
 -                    memcpy(data, "amp", 3);
 -                    data += 3;
 +                    ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
 +                    if (!ptr)
 +                        CV_PARSE_ERROR_CPP("Invalid attribute");
 +                    if( *ptr != '=' )
 +                        CV_PARSE_ERROR_CPP( "Attribute name should be followed by \'=\'" );
                  }
 -                else if( c == '\'' )
 +
 +                c = *++ptr;
 +                if( c != '\"' && c != '\'' )
                  {
 -                    memcpy(data, "apos", 4);
 -                    data += 4;
 +                    ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
 +                    if( *ptr != '\"' && *ptr != '\'' )
 +                        CV_PARSE_ERROR_CPP( "Attribute value should be put into single or double quotes" );
                  }
 -                else if( c == '\"' )
 +
 +                char quote = *ptr++;
 +                endptr = ptr;
 +                for(;;)
                  {
 -                    memcpy( data, "quot", 4);
 -                    data += 4;
 +                    c = *endptr++;
 +                    if( c == quote )
 +                        break;
 +                    if( c == '\0' )
 +                        CV_PARSE_ERROR_CPP( "Unexpected end of line" );
                  }
 -                else
 +
 +                if( attrname == "type_id" )
                  {
 -                    sprintf( data, "#x%02x", (uchar)c );
 -                    data += 4;
 +                    CV_Assert( type_name.empty() );
 +                    type_name = std::string(ptr, (size_t)(endptr - 1 - ptr));
                  }
 -                *data++ = ';';
 -                need_quote = 1;
 +
 +                ptr = endptr;
              }
 -            else
 -                *data++ = c;
 -        }
 -        if( !need_quote && (cv_isdigit(str[0]) ||
 -            str[0] == '+' || str[0] == '-' || str[0] == '.' ))
 -            need_quote = 1;
  
 -        if( need_quote )
 -            *data++ = '\"';
 -        len = (int)(data - buf) - !need_quote;
 -        *data++ = '\0';
 -        data = buf + !need_quote;
 -    }
 +            c = *ptr;
 +            bool have_space = cv_isspace(c) || c == '\0';
  
 -    icvXMLWriteScalar( fs, key, data, len );
 -}
 +            if( c != '>' )
 +            {
 +                ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
 +                if (!ptr)
 +                    CV_PARSE_ERROR_CPP("Invalid input");
 +                c = *ptr;
 +            }
  
 +            if( c == '>' )
 +            {
 +                if( tag_type == CV_XML_HEADER_TAG )
 +                    CV_PARSE_ERROR_CPP( "Invalid closing tag for <?xml ..." );
 +                ptr++;
 +                break;
 +            }
 +            else if( c == '?' && tag_type == CV_XML_HEADER_TAG )
 +            {
 +                if( ptr[1] != '>'  )  // FIXIT ptr[1] - out of bounds read without check
 +                    CV_PARSE_ERROR_CPP( "Invalid closing tag for <?xml ..." );
 +                ptr += 2;
 +                break;
 +            }
 +            else if( c == '/' && ptr[1] == '>' && tag_type == CV_XML_OPENING_TAG )  // FIXIT ptr[1] - out of bounds read without check
 +            {
 +                tag_type = CV_XML_EMPTY_TAG;
 +                ptr += 2;
 +                break;
 +            }
  
 -void icvXMLWriteComment( CvFileStorage* fs, const char* comment, int eol_comment )
 -{
 -    int len;
 -    int multiline;
 -    const char* eol;
 -    char* ptr;
 +            if( !have_space )
 +                CV_PARSE_ERROR_CPP( "There should be space between attributes" );
 +        }
  
 -    if( !comment )
 -        CV_Error( CV_StsNullPtr, "Null comment" );
 +        return ptr;
 +    }
  
 -    if( strstr(comment, "--") != 0 )
 -        CV_Error( CV_StsBadArg, "Double hyphen \'--\' is not allowed in the comments" );
 +    bool parse(char* ptr)
 +    {
 +        CV_Assert( fs != 0 );
  
 -    len = (int)strlen(comment);
 -    eol = strchr(comment, '\n');
 -    multiline = eol != 0;
 -    ptr = fs->buffer;
 +        std::string key, key2, type_name;
 +        int tag_type = 0;
 +        bool ok = false;
  
 -    if( multiline || !eol_comment || fs->buffer_end - ptr < len + 5 )
 -        ptr = icvXMLFlush( fs );
 -    else if( ptr > fs->buffer_start + fs->struct_indent )
 -        *ptr++ = ' ';
 +        // CV_XML_INSIDE_TAG is used to prohibit leading comments
 +        ptr = skipSpaces( ptr, CV_XML_INSIDE_TAG );
 +        if (!ptr)
 +            CV_PARSE_ERROR_CPP("Invalid input");
  
 -    if( !multiline )
 -    {
 -        ptr = icvFSResizeWriteBuffer( fs, ptr, len + 9 );
 -        sprintf( ptr, "<!-- %s -->", comment );
 -        len = (int)strlen(ptr);
 -    }
 -    else
 -    {
 -        strcpy( ptr, "<!--" );
 -        len = 4;
 -    }
 +        if( memcmp( ptr, "<?xml", 5 ) != 0 )  // FIXIT ptr[1..] - out of bounds read without check
 +            CV_PARSE_ERROR_CPP( "Valid XML should start with \'<?xml ...?>\'" );
  
 -    fs->buffer = ptr + len;
 -    ptr = icvXMLFlush(fs);
 +        ptr = parseTag( ptr, key, type_name, tag_type );
 +        FileNode root_collection(fs->getFS(), 0, 0);
  
 -    if( multiline )
 -    {
 -        while( comment )
 +        while( ptr && *ptr != '\0' )
          {
 -            if( eol )
 -            {
 -                ptr = icvFSResizeWriteBuffer( fs, ptr, (int)(eol - comment) + 1 );
 -                memcpy( ptr, comment, eol - comment + 1 );
 -                ptr += eol - comment;
 -                comment = eol + 1;
 -                eol = strchr( comment, '\n' );
 -            }
 -            else
 +            ptr = skipSpaces( ptr, 0 );
 +            if (!ptr)
 +                CV_PARSE_ERROR_CPP("Invalid input");
 +
 +            if( *ptr != '\0' )
              {
 -                len = (int)strlen(comment);
 -                ptr = icvFSResizeWriteBuffer( fs, ptr, len );
 -                memcpy( ptr, comment, len );
 -                ptr += len;
 -                comment = 0;
 +                ptr = parseTag( ptr, key, type_name, tag_type );
 +                if( tag_type != CV_XML_OPENING_TAG || key != "opencv_storage" )
 +                    CV_PARSE_ERROR_CPP( "<opencv_storage> tag is missing" );
 +                FileNode root = fs->addNode(root_collection, std::string(), FileNode::MAP, 0);
 +                ptr = parseValue( ptr, root );
 +                ptr = parseTag( ptr, key2, type_name, tag_type );
 +                if( tag_type != CV_XML_CLOSING_TAG || key != key2 )
 +                    CV_PARSE_ERROR_CPP( "</opencv_storage> tag is missing" );
 +                ptr = skipSpaces( ptr, 0 );
 +                ok = true;
              }
 -            fs->buffer = ptr;
 -            ptr = icvXMLFlush( fs );
          }
 -        sprintf( ptr, "-->" );
 -        fs->buffer = ptr + 3;
 -        icvXMLFlush( fs );
 +        CV_Assert( fs->eof() );
 +        return ok;
      }
 +
 +    FileStorage_API* fs;
 +    char strbuf[CV_FS_MAX_LEN+16];
 +};
 +
 +Ptr<FileStorageEmitter> createXMLEmitter(FileStorage_API* fs)
 +{
 +    return makePtr<XMLEmitter>(fs);
 +}
 +
 +Ptr<FileStorageParser> createXMLParser(FileStorage_API* fs)
 +{
 +    return makePtr<XMLParser>(fs);
 +}
 +
  }
  #include "precomp.hpp"
  #include "persistence.hpp"
  
 -#define CV_YML_INDENT  3
 -#define CV_YML_INDENT_FLOW  1
 +enum
 +{
 +    CV_YML_INDENT = 3,
 +    CV_YML_INDENT_FLOW = 1
 +};
  
 -/****************************************************************************************\
 -*                                       YAML Parser                                      *
 -\****************************************************************************************/
 +namespace cv
 +{
  
 -static char* icvYMLSkipSpaces( CvFileStorage* fs, char* ptr, int min_indent, int max_comment_indent )
 +class YAMLEmitter : public FileStorageEmitter
  {
 -    for(;;)
 +public:
 +    YAMLEmitter(FileStorage_API* _fs) : fs(_fs)
      {
 -        while( *ptr == ' ' )
 -            ptr++;
 -        if( *ptr == '#' )
 -        {
 -            if( ptr - fs->buffer_start > max_comment_indent )
 -                return ptr;
 -            *ptr = '\0';
 -        }
 -        else if( cv_isprint(*ptr) )
 +    }
 +    virtual ~YAMLEmitter() {}
 +
 +    FStructData startWriteStruct(const FStructData& parent, const char* key,
 +                                 int struct_flags, const char* type_name=0)
 +    {
 +        char buf[CV_FS_MAX_LEN + 1024];
 +        const char* data = 0;
 +
 +        if ( type_name && *type_name == '\0' )
 +            type_name = 0;
 +
 +        struct_flags = (struct_flags & (FileNode::TYPE_MASK|FileNode::FLOW)) | FileNode::EMPTY;
 +        if( !FileNode::isCollection(struct_flags))
 +            CV_Error( cv::Error::StsBadArg,
 +                     "Some collection type - FileNode::SEQ or FileNode::MAP, must be specified" );
 +
 +        if (type_name && memcmp(type_name, "binary", 6) == 0)
          {
 -            if( ptr - fs->buffer_start < min_indent )
 -                CV_PARSE_ERROR( "Incorrect indentation" );
 -            break;
 +            /* reset struct flag. in order not to print ']' */
 +            struct_flags = FileNode::SEQ;
 +            sprintf(buf, "!!binary |");
 +            data = buf;
          }
 -        else if( *ptr == '\0' || *ptr == '\n' || *ptr == '\r' )
 +        else if( FileNode::isFlow(struct_flags))
          {
 -            int max_size = (int)(fs->buffer_end - fs->buffer_start);
 -            ptr = icvGets( fs, fs->buffer_start, max_size );
 -            if( !ptr )
 -            {
 -                // emulate end of stream
 -                ptr = fs->buffer_start;
 -                ptr[0] = ptr[1] = ptr[2] = '.';
 -                ptr[3] = '\0';
 -                fs->dummy_eof = 1;
 -                break;
 -            }
 +            char c = FileNode::isMap(struct_flags) ? '{' : '[';
 +            struct_flags |= FileNode::FLOW;
 +
 +            if( type_name )
 +                sprintf( buf, "!!%s %c", type_name, c );
              else
              {
 -                int l = (int)strlen(ptr);
 -                if( ptr[l-1] != '\n' && ptr[l-1] != '\r' && !icvEof(fs) )
 -                    CV_PARSE_ERROR( "Too long string or a last string w/o newline" );
 +                buf[0] = c;
 +                buf[1] = '\0';
              }
 -
 -            fs->lineno++;  // FIXIT doesn't really work with long lines. It must be counted via '\n' or '\r' symbols, not the number of icvGets() calls.
 +            data = buf;
 +        }
 +        else if( type_name )
 +        {
 +            sprintf( buf, "!!%s", type_name );
 +            data = buf;
          }
 -        else
 -            CV_PARSE_ERROR( *ptr == '\t' ? "Tabs are prohibited in YAML!" : "Invalid character" );
 -    }
 -
 -    return ptr;
 -}
  
 +        writeScalar( key, data );
  
 -static void icvYMLGetMultilineStringContent(CvFileStorage* fs, char* ptr, int indent, char* &beg, char* &end)
 -{
 -    ptr = icvYMLSkipSpaces(fs, ptr, 0, INT_MAX);
 -    beg = ptr;
 -    end = ptr;
 -    if (fs->dummy_eof)
 -        return ; /* end of file */
 -
 -    if (ptr - fs->buffer_start != indent)
 -        return ; /* end of string */
 -
 -    /* find end */
 -    while(cv_isprint(*ptr)) /* no check for base64 string */
 -        ++ ptr;
 -    if (*ptr == '\0')
 -        CV_PARSE_ERROR("Unexpected end of line");
 -
 -    end = ptr;
 -}
 +        FStructData fsd;
 +        fsd.indent = parent.indent;
 +        fsd.flags = struct_flags;
  
 -static char* icvYMLParseBase64(CvFileStorage* fs, char* ptr, int indent, CvFileNode * node)
 -{
 -    char * beg = 0;
 -    char * end = 0;
 +        if( !FileNode::isFlow(parent.flags) )
 +            fsd.indent += CV_YML_INDENT + FileNode::isFlow(struct_flags);
  
 -    icvYMLGetMultilineStringContent(fs, ptr, indent, beg, end);
 -    if (beg >= end)
 -        return end; // CV_PARSE_ERROR("Empty Binary Data");
 +        return fsd;
 +    }
  
 -    /* calc (decoded) total_byte_size from header */
 -    std::string dt;
 +    void endWriteStruct(const FStructData& current_struct)
      {
 -        if (end - beg < static_cast<int>(base64::ENCODED_HEADER_SIZE))
 -            CV_PARSE_ERROR("Unrecognized Base64 header");
 +        char* ptr;
  
 -        std::vector<char> header(base64::HEADER_SIZE + 1, ' ');
 -        base64::base64_decode(beg, header.data(), 0U, base64::ENCODED_HEADER_SIZE);
 -        if ( !base64::read_base64_header(header, dt) || dt.empty() )
 -            CV_PARSE_ERROR("Invalid `dt` in Base64 header");
 +        int struct_flags = current_struct.flags;
  
 -        beg += base64::ENCODED_HEADER_SIZE;
 +        if( FileNode::isFlow(struct_flags) )
 +        {
 +            ptr = fs->bufferPtr();
 +            if( ptr > fs->bufferStart() + current_struct.indent && !FileNode::isEmptyCollection(struct_flags) )
 +                *ptr++ = ' ';
 +            *ptr++ = FileNode::isMap(struct_flags) ? '}' : ']';
 +            fs->setBufferPtr(ptr);
 +        }
 +        else if( FileNode::isEmptyCollection(struct_flags) )
 +        {
 +            ptr = fs->flush();
 +            memcpy( ptr, FileNode::isMap(struct_flags) ? "{}" : "[]", 2 );
 +            fs->setBufferPtr(ptr + 2);
 +        }
 +        /*
 +        if( !FileNode::isFlow(parent_flags) )
 +            fs->struct_indent -= CV_YML_INDENT + FileNode::isFlow(struct_flags);
-         assert( fs->struct_indent >= 0 );*/
++        CV_Assert( fs->struct_indent >= 0 );*/
      }
  
 -    /* get all Base64 data */
 -    std::string base64_buffer;
 -    base64_buffer.reserve( PARSER_BASE64_BUFFER_SIZE );
 -    while( beg < end )
 -    {
 -        base64_buffer.append( beg, end );
 -        beg = end;
 -        icvYMLGetMultilineStringContent( fs, beg, indent, beg, end );
 -    }
 -    if ( base64_buffer.empty() ||
 -         !base64::base64_valid(base64_buffer.data(), 0U, base64_buffer.size()) )
 -        CV_PARSE_ERROR( "Invalid Base64 data." );
 -
 -    /* buffer for decoded data(exclude header) */
 -    std::vector<uchar> binary_buffer( base64::base64_decode_buffer_size(base64_buffer.size()) );
 -    int total_byte_size = static_cast<int>(
 -        base64::base64_decode_buffer_size( base64_buffer.size(), base64_buffer.data(), false )
 -        );
 +    void write(const char* key, int value)
      {
 -        base64::Base64ContextParser parser(binary_buffer.data(), binary_buffer.size() );
 -        const uchar * buffer_beg = reinterpret_cast<const uchar *>( base64_buffer.data() );
 -        const uchar * buffer_end = buffer_beg + base64_buffer.size();
 -        parser.read( buffer_beg, buffer_end );
 -        parser.flush();
 +        char buf[128];
 +        writeScalar( key, fs::itoa( value, buf, 10 ));
      }
  
 -    node->tag = CV_NODE_NONE;
 -    int struct_flags = CV_NODE_FLOW | CV_NODE_SEQ;
 -    /* after icvFSCreateCollection, node->tag == struct_flags */
 -    icvFSCreateCollection(fs, struct_flags, node);
 -    base64::make_seq(fs, binary_buffer.data(), total_byte_size, dt.c_str(), *node->data.seq);
 -
 -    if (fs->dummy_eof) {
 -        /* end of file */
 -        return fs->buffer_start;
 -    } else {
 -        /* end of line */
 -        return end;
 +    void write( const char* key, double value )
 +    {
 +        char buf[128];
 +        writeScalar( key, fs::doubleToString( buf, value, false ));
      }
 -}
 -
 -
 -static char* icvYMLParseKey( CvFileStorage* fs, char* ptr, CvFileNode* map_node, CvFileNode** value_placeholder )
 -{
 -    char c;
 -    char *endptr = ptr - 1, *saveptr;
 -    CvStringHashNode* str_hash_node;
 -
 -    if( *ptr == '-' )
 -        CV_PARSE_ERROR( "Key may not start with \'-\'" );
 -
 -    do c = *++endptr;
 -    while( cv_isprint(c) && c != ':' );
 -
 -    if( c != ':' )
 -        CV_PARSE_ERROR( "Missing \':\'" );
 -
 -    saveptr = endptr + 1;
 -    do c = *--endptr;
 -    while( c == ' ' );
 -
 -    ++endptr;
 -    if( endptr == ptr )
 -        CV_PARSE_ERROR( "An empty key" );
 -
 -    str_hash_node = cvGetHashedKey( fs, ptr, (int)(endptr - ptr), 1 );
 -    *value_placeholder = cvGetFileNode( fs, map_node, str_hash_node, 1 );
 -    ptr = saveptr;
 -
 -    return ptr;
 -}
  
 +    void write(const char* key, const char* str, bool quote)
 +    {
 +        char buf[CV_FS_MAX_LEN*4+16];
 +        char* data = (char*)str;
 +        int i, len;
  
 -static char*
 -icvYMLParseValue( CvFileStorage* fs, char* ptr, CvFileNode* node,
 -                  int parent_flags, int min_indent )
 -{
 -    char buf[CV_FS_MAX_LEN + 1024] = {0};
 -    char* endptr = 0;
 -    char c = ptr[0], d = ptr[1];
 -    int is_parent_flow = CV_NODE_IS_FLOW(parent_flags);
 -    int value_type = CV_NODE_NONE;
 -    int len;
 -    bool is_binary_string = false;
 +        if( !str )
 +            CV_Error( cv::Error::StsNullPtr, "Null string pointer" );
  
 -    memset( node, 0, sizeof(*node) );
 +        len = (int)strlen(str);
 +        if( len > CV_FS_MAX_LEN )
 +            CV_Error( cv::Error::StsBadArg, "The written string is too long" );
  
 -    if( c == '!' ) // handle explicit type specification
 -    {
 -        if( d == '!' || d == '^' )
 +        if( quote || len == 0 || str[0] != str[len-1] || (str[0] != '\"' && str[0] != '\'') )
          {
 -            ptr++;
 -            value_type |= CV_NODE_USER;
 -        }
 -        if ( d == '<') //support of full type heading from YAML 1.2
 -        {
 -            const char* yamlTypeHeading = "<tag:yaml.org,2002:";
 -            const size_t headingLength = strlen(yamlTypeHeading);
 -
 -            char* typeEndPtr = ++ptr;
 +            int need_quote = quote || len == 0 || str[0] == ' ';
 +            data = buf;
 +            *data++ = '\"';
 +            for( i = 0; i < len; i++ )
 +            {
 +                char c = str[i];
  
 -            do d = *++typeEndPtr;
 -            while( cv_isprint(d) && d != ' ' && d != '>' );
 +                if( !need_quote && !cv_isalnum(c) && c != '_' && c != ' ' && c != '-' &&
 +                   c != '(' && c != ')' && c != '/' && c != '+' && c != ';' )
 +                    need_quote = 1;
  
 -            if ( d == '>' && (size_t)(typeEndPtr - ptr) > headingLength )
 -            {
 -                if ( memcmp(ptr, yamlTypeHeading, headingLength) == 0 )
 +                if( !cv_isalnum(c) && (!cv_isprint(c) || c == '\\' || c == '\'' || c == '\"') )
                  {
 -                    value_type |= CV_NODE_USER;
 -                    *typeEndPtr = ' ';
 -                    ptr += headingLength - 1;
 +                    *data++ = '\\';
 +                    if( cv_isprint(c) )
 +                        *data++ = c;
 +                    else if( c == '\n' )
 +                        *data++ = 'n';
 +                    else if( c == '\r' )
 +                        *data++ = 'r';
 +                    else if( c == '\t' )
 +                        *data++ = 't';
 +                    else
 +                    {
 +                        sprintf( data, "x%02x", c );
 +                        data += 3;
 +                    }
                  }
 +                else
 +                    *data++ = c;
              }
 +            if( !need_quote && (cv_isdigit(str[0]) ||
 +                                str[0] == '+' || str[0] == '-' || str[0] == '.' ))
 +                need_quote = 1;
 +
 +            if( need_quote )
 +                *data++ = '\"';
 +            *data++ = '\0';
 +            data = buf + !need_quote;
          }
  
 -        endptr = ptr++;
 -        do d = *++endptr;
 -        while( cv_isprint(d) && d != ' ' );
 -        len = (int)(endptr - ptr);
 -        if( len == 0 )
 -            CV_PARSE_ERROR( "Empty type name" );
 -        d = *endptr;
 -        *endptr = '\0';
 +        writeScalar( key, data);
 +    }
  
 -        if( len == 3 && !CV_NODE_IS_USER(value_type) )
 +    void writeScalar(const char* key, const char* data)
 +    {
 +        fs->check_if_write_struct_is_delayed(false);
 +        if ( fs->get_state_of_writing_base64() == FileStorage_API::Uncertain )
          {
 -            if( memcmp( ptr, "str", 3 ) == 0 )
 -                value_type = CV_NODE_STRING;
 -            else if( memcmp( ptr, "int", 3 ) == 0 )
 -                value_type = CV_NODE_INT;
 -            else if( memcmp( ptr, "seq", 3 ) == 0 )
 -                value_type = CV_NODE_SEQ;
 -            else if( memcmp( ptr, "map", 3 ) == 0 )
 -                value_type = CV_NODE_MAP;
 +            fs->switch_to_Base64_state( FileStorage_API::NotUse );
          }
 -        else if( len == 5 && !CV_NODE_IS_USER(value_type) )
 +        else if ( fs->get_state_of_writing_base64() == FileStorage_API::InUse )
          {
 -            if( memcmp( ptr, "float", 5 ) == 0 )
 -                value_type = CV_NODE_REAL;
 +            CV_Error( cv::Error::StsError, "At present, output Base64 data only." );
          }
 -        else if (len == 6 && CV_NODE_IS_USER(value_type))
 -        {
 -            if( memcmp( ptr, "binary", 6 ) == 0 ) {
 -                value_type = CV_NODE_SEQ;
 -                is_binary_string = true;
  
 -                /* for ignore '|' */
 +        int i, keylen = 0;
 +        int datalen = 0;
 +        char* ptr;
  
 -                /**** operation with endptr ****/
 -                *endptr = d;
 +        FStructData& current_struct = fs->getCurrentStruct();
  
 -                do {
 -                    d = *++endptr;
 -                    if (d == '|')
 -                        break;
 -                } while (d == ' ');
 +        int struct_flags = current_struct.flags;
  
 -                d = *++endptr;
 -                *endptr = '\0';
 -            }
 -        }
 -        else if( CV_NODE_IS_USER(value_type) )
 +        if( key && key[0] == '\0' )
 +            key = 0;
 +
 +        if( FileNode::isCollection(struct_flags) )
          {
 -            node->info = cvFindType( ptr );
 -            if( !node->info )
 -                node->tag &= ~CV_NODE_USER;
 +            if( (FileNode::isMap(struct_flags) ^ (key != 0)) )
 +                CV_Error( cv::Error::StsBadArg, "An attempt to add element without a key to a map, "
 +                         "or add element with key to sequence" );
          }
 -
 -        *endptr = d;
 -        ptr = icvYMLSkipSpaces( fs, endptr, min_indent, INT_MAX );
 -
 -        c = *ptr;
 -
 -        if( !CV_NODE_IS_USER(value_type) )
 +        else
          {
 -            if (value_type == CV_NODE_STRING && c != '\'' && c != '\"')
 -                goto force_string;
 -            if( value_type == CV_NODE_INT )
 -                goto force_int;
 -            if( value_type == CV_NODE_REAL )
 -                goto force_real;
 +            fs->setNonEmpty();
 +            struct_flags = FileNode::EMPTY | (key ? FileNode::MAP : FileNode::SEQ);
          }
 -    }
  
 -    if (is_binary_string)
 -    {
 -        /* for base64 string */
 -        int indent = static_cast<int>(ptr - fs->buffer_start);
 -        ptr = icvYMLParseBase64(fs, ptr, indent, node);
 -    }
 -    else if( cv_isdigit(c) ||
 -        ((c == '-' || c == '+') && (cv_isdigit(d) || d == '.')) ||
 -        (c == '.' && cv_isalnum(d))) // a number
 -    {
 -        double fval;
 -        int ival;
 -        endptr = ptr + (c == '-' || c == '+');
 -        while( cv_isdigit(*endptr) )
 -            endptr++;
 -        if( *endptr == '.' || *endptr == 'e' )
 +        if( key )
          {
 -force_real:
 -            fval = icv_strtod( fs, ptr, &endptr );
 -            /*if( endptr == ptr || cv_isalpha(*endptr) )
 -                icvProcessSpecialDouble( fs, endptr, &fval, &endptr ));*/
 +            keylen = (int)strlen(key);
 +            if( keylen == 0 )
 +                CV_Error( cv::Error::StsBadArg, "The key is an empty" );
  
 -            node->tag = CV_NODE_REAL;
 -            node->data.f = fval;
 -        }
 -        else
 -        {
 -force_int:
 -            ival = (int)strtol( ptr, &endptr, 0 );
 -            node->tag = CV_NODE_INT;
 -            node->data.i = ival;
 +            if( keylen > CV_FS_MAX_LEN )
 +                CV_Error( cv::Error::StsBadArg, "The key is too long" );
          }
  
 -        if( !endptr || endptr == ptr )
 -            CV_PARSE_ERROR( "Invalid numeric value (inconsistent explicit type specification?)" );
 +        if( data )
 +            datalen = (int)strlen(data);
  
 -        ptr = endptr;
 -        CV_PERSISTENCE_CHECK_END_OF_BUFFER_BUG();
 -    }
 -    else if( c == '\'' || c == '\"' ) // an explicit string
 -    {
 -        node->tag = CV_NODE_STRING;
 -        if( c == '\'' )
 -            for( len = 0; len < CV_FS_MAX_LEN; )
 +        if( FileNode::isFlow(struct_flags) )
 +        {
 +            ptr = fs->bufferPtr();
 +            if( !FileNode::isEmptyCollection(struct_flags) )
 +                *ptr++ = ',';
 +            int new_offset = (int)(ptr - fs->bufferStart()) + keylen + datalen;
 +            if( new_offset > fs->wrapMargin() && new_offset - current_struct.indent > 10 )
              {
 -                c = *++ptr;
 -                if( cv_isalnum(c) || (c != '\'' && cv_isprint(c)))
 -                    buf[len++] = c;
 -                else if( c == '\'' )
 -                {
 -                    c = *++ptr;
 -                    if( c != '\'' )
 -                        break;
 -                    buf[len++] = c;
 -                }
 -                else
 -                    CV_PARSE_ERROR( "Invalid character" );
 +                fs->setBufferPtr(ptr);
 +                ptr = fs->flush();
              }
 +            else
 +                *ptr++ = ' ';
 +        }
          else
 -            for( len = 0; len < CV_FS_MAX_LEN; )
 +        {
 +            ptr = fs->flush();
 +            if( !FileNode::isMap(struct_flags) )
              {
 -                c = *++ptr;
 -                if( cv_isalnum(c) || (c != '\\' && c != '\"' && cv_isprint(c)))
 -                    buf[len++] = c;
 -                else if( c == '\"' )
 -                {
 -                    ++ptr;
 -                    break;
 -                }
 -                else if( c == '\\' )
 -                {
 -                    d = *++ptr;
 -                    if( d == '\'' )
 -                        buf[len++] = d;
 -                    else if( d == '\"' || d == '\\' || d == '\'' )
 -                        buf[len++] = d;
 -                    else if( d == 'n' )
 -                        buf[len++] = '\n';
 -                    else if( d == 'r' )
 -                        buf[len++] = '\r';
 -                    else if( d == 't' )
 -                        buf[len++] = '\t';
 -                    else if( d == 'x' || (cv_isdigit(d) && d < '8') )
 -                    {
 -                        int val, is_hex = d == 'x';
 -                        c = ptr[3];
 -                        ptr[3] = '\0';
 -                        val = (int)strtol( ptr + is_hex, &endptr, is_hex ? 8 : 16 );
 -                        ptr[3] = c;
 -                        if( endptr == ptr + is_hex )
 -                            buf[len++] = 'x';
 -                        else
 -                        {
 -                            buf[len++] = (char)val;
 -                            ptr = endptr;
 -                        }
 -                    }
 -                }
 -                else
 -                    CV_PARSE_ERROR( "Invalid character" );
 +                *ptr++ = '-';
 +                if( data )
 +                    *ptr++ = ' ';
              }
 +        }
  
 -        if( len >= CV_FS_MAX_LEN )
 -            CV_PARSE_ERROR( "Too long string literal" );
 -
 -        node->data.str = cvMemStorageAllocString( fs->memstorage, buf, len );
 -    }
 -    else if( c == '[' || c == '{' ) // collection as a flow
 -    {
 -        int new_min_indent = min_indent + !is_parent_flow;
 -        int struct_flags = CV_NODE_FLOW + (c == '{' ? CV_NODE_MAP : CV_NODE_SEQ);
 -        bool is_simple = true;
 -
 -        icvFSCreateCollection( fs, CV_NODE_TYPE(struct_flags) +
 -                                        (node->info ? CV_NODE_USER : 0), node );
 -
 -        d = c == '[' ? ']' : '}';
 -
 -        for( ++ptr ;;)
 +        if( key )
          {
 -            CvFileNode* elem = 0;
 +            if( !cv_isalpha(key[0]) && key[0] != '_' )
 +                CV_Error( cv::Error::StsBadArg, "Key must start with a letter or _" );
  
 -            ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
 -            if( *ptr == '}' || *ptr == ']' )
 -            {
 -                if( *ptr != d )
 -                    CV_PARSE_ERROR( "The wrong closing bracket" );
 -                ptr++;
 -                break;
 -            }
 +            ptr = fs->resizeWriteBuffer( ptr, keylen );
  
 -            if( node->data.seq->total != 0 )
 +            for( i = 0; i < keylen; i++ )
              {
 -                if( *ptr != ',' )
 -                    CV_PARSE_ERROR( "Missing , between the elements" );
 -                ptr = icvYMLSkipSpaces( fs, ptr + 1, new_min_indent, INT_MAX );
 -            }
 +                char c = key[i];
  
 -            if( CV_NODE_IS_MAP(struct_flags) )
 -            {
 -                ptr = icvYMLParseKey( fs, ptr, node, &elem );
 -                ptr = icvYMLSkipSpaces( fs, ptr, new_min_indent, INT_MAX );
 +                ptr[i] = c;
 +                if( !cv_isalnum(c) && c != '-' && c != '_' && c != ' ' )
 +                    CV_Error( cv::Error::StsBadArg, "Key names may only contain alphanumeric characters [a-zA-Z0-9], '-', '_' and ' '" );
              }
 -            else
 -            {
 -                if( *ptr == ']' )
 -                    break;
 -                elem = (CvFileNode*)cvSeqPush( node->data.seq, 0 );
 -            }
 -            CV_Assert(elem);
 -            ptr = icvYMLParseValue( fs, ptr, elem, struct_flags, new_min_indent );
 -            if( CV_NODE_IS_MAP(struct_flags) )
 -                elem->tag |= CV_NODE_NAMED;
 -            is_simple = is_simple && !CV_NODE_IS_COLLECTION(elem->tag);
 +
 +            ptr += keylen;
 +            *ptr++ = ':';
 +            if( !FileNode::isFlow(struct_flags) && data )
 +                *ptr++ = ' ';
          }
 -        node->data.seq->flags |= is_simple ? CV_NODE_SEQ_SIMPLE : 0;
 -    }
 -    else
 -    {
 -        int indent, struct_flags;
 -        bool is_simple;
  
 -        if( is_parent_flow || c != '-' )
 +        if( data )
          {
 -            // implicit (one-line) string or nested block-style collection
 -            if( !is_parent_flow )
 -            {
 -                if( c == '?' )
 -                    CV_PARSE_ERROR( "Complex keys are not supported" );
 -                if( c == '|' || c == '>' )
 -                    CV_PARSE_ERROR( "Multi-line text literals are not supported" );
 -            }
 +            ptr = fs->resizeWriteBuffer( ptr, datalen );
 +            memcpy( ptr, data, datalen );
 +            ptr += datalen;
 +        }
  
 -force_string:
 -            endptr = ptr - 1;
 +        fs->setBufferPtr(ptr);
 +        current_struct.flags &= ~FileNode::EMPTY;
 +    }
  
 -            do c = *++endptr;
 -            while( cv_isprint(c) &&
 -                   (!is_parent_flow || (c != ',' && c != '}' && c != ']')) &&
 -                   (is_parent_flow || c != ':' || value_type == CV_NODE_STRING));
 +    void writeComment(const char* comment, bool eol_comment)
 +    {
 +        if( !comment )
 +            CV_Error( cv::Error::StsNullPtr, "Null comment" );
  
 -            if( endptr == ptr )
 -                CV_PARSE_ERROR( "Invalid character" );
 +        int len = (int)strlen(comment);
 +        const char* eol = strchr(comment, '\n');
 +        bool multiline = eol != 0;
 +        char* ptr = fs->bufferPtr();
  
 -            if( is_parent_flow || c != ':' )
 -            {
 -                char* str_end = endptr;
 -                node->tag = CV_NODE_STRING;
 -                // strip spaces in the end of string
 -                do c = *--str_end;
 -                while( str_end > ptr && c == ' ' );
 -                str_end++;
 -                node->data.str = cvMemStorageAllocString( fs->memstorage, ptr, (int)(str_end - ptr) );
 -                ptr = endptr;
 -                return ptr;
 -            }
 -            struct_flags = CV_NODE_MAP;
 -        }
 +        if( !eol_comment || multiline ||
 +            fs->bufferEnd() - ptr < len || ptr == fs->bufferStart() )
 +            ptr = fs->flush();
          else
 -            struct_flags = CV_NODE_SEQ;
 -
 -        icvFSCreateCollection( fs, struct_flags +
 -                    (node->info ? CV_NODE_USER : 0), node );
 -
 -        indent = (int)(ptr - fs->buffer_start);
 -        is_simple = true;
 +            *ptr++ = ' ';
  
 -        for(;;)
 +        while( comment )
          {
 -            CvFileNode* elem = 0;
 -
 -            if( CV_NODE_IS_MAP(struct_flags) )
 +            *ptr++ = '#';
 +            *ptr++ = ' ';
 +            if( eol )
              {
 -                ptr = icvYMLParseKey( fs, ptr, node, &elem );
 +                ptr = fs->resizeWriteBuffer( ptr, (int)(eol - comment) + 1 );
 +                memcpy( ptr, comment, eol - comment + 1 );
 +                fs->setBufferPtr(ptr + (eol - comment));
 +                comment = eol + 1;
 +                eol = strchr( comment, '\n' );
              }
              else
              {
@@@ -62,7 -58,7 +62,6 @@@
  #include "opencv2/core/ocl.hpp"
  #endif
  
--#include <assert.h>
  #include <ctype.h>
  #include <float.h>
  #include <limits.h>
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -998,16 -752,14 +1001,21 @@@ struct ELUFunctor : public BaseDefaultF
  
      inline float calculate(float x) const
      {
-         return x >= 0.f ? x : exp(x) - 1.f;
+         return x >= 0.f ? x : alpha * (exp(x) - 1.f);
+     }
+     inline void setKernelParams(ocl::Kernel& kernel) const
+     {
+         kernel.set(3, alpha);
      }
  
 +#ifdef HAVE_CUDA
 +    Ptr<BackendNode> initCUDA(int target, csl::Stream stream)
 +    {
 +        return make_cuda_node<cuda4dnn::ELUOp>(target, stream);
 +    }
 +#endif
 +
  #ifdef HAVE_HALIDE
      void attachHalide(const Halide::Expr& input, Halide::Func& top)
      {
@@@ -240,14 -232,9 +240,14 @@@ public
              #endif
              #if CV_TRY_AVX
                  if( useAVX )
-                     opt_AVX::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize);
+                     opt_AVX::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize_aligned);
                  else
              #endif
 +            #if CV_TRY_RVV
 +                if( useRVV )
 +                    opt_RVV::fastGEMM1T( sptr, wptr, wstep, biasptr, dptr, nw, vecsize);
 +                else
 +            #endif
                  {
                      int i = 0;
  
Simple merge
@@@ -768,12 -612,24 +768,25 @@@ void ONNXImporter::handleNode(const ope
      }
  }
  
+ void setCeilMode(LayerParams& layerParams)
+ {
+     // auto_pad attribute is deprecated and uses ceil
+     if (layerParams.has("pad_mode"))
+     {
+         layerParams.set("ceil_mode", true);
+     }
+     else if (!layerParams.has("ceil_mode"))
+     {
+         layerParams.set("ceil_mode", false);
+     }
+ }
  void ONNXImporter::parseMaxPool(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
  {
 -    layerParams.type = "Pooling";
 +    int depth = layerParams.get<int>("depth", CV_32F);
 +    layerParams.type = (depth == CV_8S) ? "PoolingInt8" : "Pooling";
      layerParams.set("pool", "MAX");
-     layerParams.set("ceil_mode", layerParams.has("pad_mode"));
+     setCeilMode(layerParams);
      addLayer(layerParams, node_proto);
  }
  
@@@ -1075,8 -932,8 +1088,9 @@@ void ONNXImporter::parseSplit(LayerPara
      {
          layerParams.set("num_split", node_proto.output_size());
      }
 -    layerParams.type = "Slice";
 +    int depth = layerParams.get<int>("depth", CV_32F);
 +    layerParams.type = (depth == CV_8S) ? "SliceInt8" : "Slice";
+     layerParams.set("axis", layerParams.get<float>("axis", 0));
      addLayer(layerParams, node_proto);
  }
  
@@@ -1872,9 -1664,18 +1894,19 @@@ void ONNXImporter::parseConvTranspose(L
  
  void ONNXImporter::parseTranspose(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto)
  {
 -    layerParams.type = "Permute";
 +    int depth = layerParams.get<int>("depth", CV_32F);
 +    layerParams.type = (depth == CV_8S) ? "PermuteInt8" : "Permute";
      replaceLayerParam(layerParams, "perm", "order");
+     if (!layerParams.has("order")) {
+         MatShape inpShape = outShapes[node_proto.input(0)];
+         size_t dims = inpShape.size();
+         std::vector<int> perm(dims);
+         for (size_t d = 0; d < dims; ++d)
+         {
+             perm[d] = static_cast<int>(dims - 1 - d);
+         }
+         layerParams.set("order", DictValue::arrayInt(perm.data(), perm.size()));
+     }
  
      CV_Assert(node_proto.input_size() == 1);
      if (constBlobs.find(node_proto.input(0)) != constBlobs.end())
Simple merge
Simple merge
@@@ -156,11 -158,11 +158,16 @@@ TEST_P(Test_Caffe_nets, Axpy
          l1 = 2e-4;
          lInf = 1e-3;
      }
-     else if(target == DNN_TARGET_CUDA_FP16)
+     if (target == DNN_TARGET_MYRIAD)
+     {
+         l1 = 0.001;
+         lInf = 0.001;
+     }
++    if(target == DNN_TARGET_CUDA_FP16)
 +    {
 +        l1 = 0.0002;
 +        lInf = 0.0007;
 +    }
      normAssert(ref, out, "", l1, lInf);
  }
  
@@@ -435,9 -436,19 +439,22 @@@ TEST_P(FullyConnected, Accuracy
      Mat input(4, &sz[0], CV_32F);
  
      double l1 = 0.0;
 -    else if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && targetId == DNN_TARGET_OPENCL_FP16)
+     double lInf = 0.0;
+ #if defined(INF_ENGINE_RELEASE)
+     if (targetId == DNN_TARGET_MYRIAD)
+     {
+         l1 = 0.015;
+         lInf = 0.025;
+     }
-     test(lp, input, backendId, targetId, false, true, l1);
++    if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && targetId == DNN_TARGET_OPENCL_FP16)
+     {
+         l1 = 0.01;
+     }
+ #endif
 +    if (targetId == DNN_TARGET_CUDA_FP16)
 +        l1 = 0.015;
++
+     test(lp, input, backendId, targetId, false, l1, lInf);
  }
  
  INSTANTIATE_TEST_CASE_P(Layer_Test_Halide, FullyConnected, Combine(
Simple merge
Simple merge
@@@ -317,16 -348,14 +366,14 @@@ TEST_P(Test_ONNX_layers, Scale
  
  TEST_P(Test_ONNX_layers, ReduceMean3D)
  {
-     if (backend == DNN_BACKEND_CUDA)
-     {
-         // ok
-     }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
  
      testONNXModels("reduce_mean3d");
  }
@@@ -443,13 -396,12 +490,12 @@@ TEST_P(Test_ONNX_layers, Concatenation
  
  TEST_P(Test_ONNX_layers, Eltwise3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
      if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
--    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
++    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
+ #endif
      testONNXModels("eltwise3d");
  }
  
@@@ -460,55 -412,56 +506,56 @@@ TEST_P(Test_ONNX_layers, AveragePooling
  
  TEST_P(Test_ONNX_layers, MaxPooling3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
      {
-         // ok
+         // accuracy
+         if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+             applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
+                 CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
+             );
+         // IE exception: [ GENERAL_ERROR ]  AssertionFailed: !expired()
+         if (target == DNN_TARGET_MYRIAD)
+             applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
      }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
      testONNXModels("max_pool3d", npy, 0, 0, false, false);
  }
  
  TEST_P(Test_ONNX_layers, AvePooling3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
-     {
-         // ok
-     }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
      testONNXModels("ave_pool3d");
  }
  
  TEST_P(Test_ONNX_layers, PoolConv3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
-     {
-         // ok
-     }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
      testONNXModels("pool_conv_3d");
  }
  
@@@ -1544,19 -1379,22 +1617,22 @@@ TEST_P(Test_ONNX_nets, Shufflenet
  
  TEST_P(Test_ONNX_nets, Resnet34_kinetics)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
-     {
-         // ok
-     }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
+     {
+         // IE exception: Function contains several inputs and outputs with one friendly name!
+         if (target == DNN_TARGET_MYRIAD)
+             applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
+     }
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
  
      String onnxmodel = findDataFile("dnn/resnet-34_kinetics.onnx", false);
      Mat image0 = imread(findDataFile("dnn/dog416.png"));
      net.setPreferableTarget(target);
  
      // output range [-5, 11]
-     float l1 = 0.0013, lInf = 0.009;
+     float l1 = 0.0013;
+     float lInf = 0.009;
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
+     {
+         l1 = 0.02;
+         lInf = 0.07;
+     }
 +    if (target == DNN_TARGET_CUDA_FP16)
 +    {
 +        l1 = 0.01;
 +        lInf = 0.06;
 +    }
  
      checkBackend(&input0, &ref0);
      net.setInput(input0);
@@@ -441,11 -444,13 +445,18 @@@ TEST_P(Test_TensorFlow_layers, slim_bat
          l1 = 0.041;
          lInf = 0.33;
      }
+ #if defined(INF_ENGINE_RELEASE)
+     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_CPU)
+     {
+         lInf = 0.0002;
+     }
+ #endif
 +    else if (target == DNN_TARGET_CUDA_FP16)
 +    {
 +        l1 = 0.005;
 +        lInf = 0.33;
 +    }
      runTensorFlowNet("slim_batch_norm", false, l1, lInf);
  }
  
@@@ -586,38 -591,41 +597,41 @@@ TEST_P(Test_TensorFlow_layers, ave_pool
  
  TEST_P(Test_TensorFlow_layers, MaxPooling3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
      {
-         // ok
+         // accuracy
+         if (target == DNN_TARGET_OPENCL || target == DNN_TARGET_OPENCL_FP16)
+             applyTestTag(target == DNN_TARGET_OPENCL ? CV_TEST_TAG_DNN_SKIP_IE_OPENCL : CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16,
+                 CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION
+             );
+         // IE exception: [ GENERAL_ERROR ]  AssertionFailed: !expired()
+         if (target == DNN_TARGET_MYRIAD)
+             applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
      }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #endif
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
  
      runTensorFlowNet("max_pool3d");
  }
  
  TEST_P(Test_TensorFlow_layers, AvePooling3D)
  {
- #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2019010000)
-     applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_VERSION);
- #endif
-     if (backend == DNN_BACKEND_CUDA)
-     {
-         // ok
-     }
-     else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
+     if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);  // Only CPU on DLIE backend is supported
 -    if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
 +    else if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target != DNN_TARGET_CPU)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);  // Only CPU on DLIE backend is supported
-     else if (target != DNN_TARGET_CPU)
-         throw SkipTestException("Only CPU is supported");
+ #endif
+     if (backend == DNN_BACKEND_OPENCV && target != DNN_TARGET_CPU)
+         throw SkipTestException("Only CPU is supported");  // FIXIT use tags
  
      runTensorFlowNet("ave_pool3d");
  }
@@@ -1317,8 -1218,7 +1333,9 @@@ TEST_P(Test_TensorFlow_layers, quantize
  
  TEST_P(Test_TensorFlow_layers, lstm)
  {
 +    if(backend == DNN_BACKEND_CUDA)
 +        applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); /* not supported */
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
      if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
      if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
@@@ -1500,6 -1418,7 +1535,9 @@@ TEST_P(Test_TensorFlow_layers, clip_by_
  
  TEST_P(Test_TensorFlow_layers, tf2_prelu)
  {
++    if (backend == DNN_BACKEND_CUDA)
++        applyTestTag(CV_TEST_TAG_DNN_SKIP_CUDA); // not supported; only across channels is supported
+ #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_LT(2021040000)
      if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
          applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
      if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
@@@ -253,11 -232,11 +257,16 @@@ TEST_P(Test_Torch_layers, net_conv_gemm
          l1 = 0.046;
          lInf = 0.023;
      }
+     else if (target == DNN_TARGET_MYRIAD)
+     {
+         l1 = 0.02;
+         lInf = 0.05;
+     }
 +    else if (target == DNN_TARGET_CUDA_FP16)
 +    {
 +        l1 = 0.0042;
 +        lInf = 0.021;
 +    }
      // The OpenCL kernels use the native_ math functions which have
      // implementation defined accuracy, so we use relaxed thresholds. See
      // https://github.com/opencv/opencv/issues/9821 for more details.
@@@ -119,7 -119,7 +119,7 @@@ CvSeq* icvApproximateChainTC89( CvChain
          }
      }
  
--    //assert( pt.x == chain->origin.x && pt.y == chain->origin.y );
++    //CV_Assert( pt.x == chain->origin.x && pt.y == chain->origin.y );
  
      if( method <= CV_CHAIN_APPROX_SIMPLE )
          return cvEndWriteSeq( &writer );
Simple merge
@@@ -270,7 -270,7 +270,7 @@@ distanceTransformEx_5x5( const Mat& _sr
              if( !s[j] )
              {
                  tmp[j] = 0;
--                //assert( lls[j] != 0 );
++                //CV_Assert( lls[j] != 0 );
              }
              else
              {
@@@ -648,7 -630,7 +648,7 @@@ Line2( Mat& img, Point2l pt1, Point2l p
      size_t step = img.step;
      Size size = img.size();
  
--    //assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
++    //CV_Assert( img && (nch == 1 || nch == 3) && img.depth() == CV_8U );
  
      Size2l sizeScaled(((int64)size.width) << XY_SHIFT, ((int64)size.height) << XY_SHIFT);
      if( !clipLine( sizeScaled, pt1, pt2 ))
Simple merge
Simple merge
Simple merge
@@@ -1501,7 -1501,7 +1501,7 @@@ void CV_ColorRGBTest::convert_forward( 
      int g_rshift = dst_bits == 16 ? 2 : 3;
      int r_lshift = dst_bits == 16 ? 11 : 10;
  
--    //assert( (cn == 3 || cn == 4) && (dst_cn == 3 || (dst_cn == 2 && depth == CV_8U)) );
++    //CV_Assert( (cn == 3 || cn == 4) && (dst_cn == 3 || (dst_cn == 2 && depth == CV_8U)) );
  
      for( i = 0; i < src.rows; i++ )
      {
@@@ -1587,7 -1587,7 +1587,7 @@@ void CV_ColorRGBTest::convert_backward
      int g_lshift = dst_bits == 16 ? 2 : 3;
      int r_rshift = dst_bits == 16 ? 11 : 10;
  
--    //assert( (cn == 3 || cn == 4) && (src_cn == 3 || (src_cn == 2 && depth == CV_8U)) );
++    //CV_Assert( (cn == 3 || cn == 4) && (src_cn == 3 || (src_cn == 2 && depth == CV_8U)) );
  
      for( i = 0; i < src.rows; i++ )
      {
Simple merge
@@@ -187,7 -187,7 +187,7 @@@ int CV_ImgWarpBaseTest::prepare_test_ca
                  ((float*)ptr)[j] = (float)buffer[j];
              break;
          default:
--            assert(0);
++            CV_Assert(0);
          }*/
          cv::Mat src(1, cols*cn, CV_32F, &buffer[0]);
          cv::Mat dst(1, cols*cn, depth, ptr);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -2212,13 -2163,8 +2211,13 @@@ bool CvVideoWriter_FFMPEG::writeFrame( 
          step = aligned_step;
      }
  
 -    if ( c->pix_fmt != input_pix_fmt ) {
 +    AVPixelFormat sw_pix_fmt = c->pix_fmt;
 +#if USE_AV_HW_CODECS
 +    if (c->hw_frames_ctx)
 +        sw_pix_fmt = ((AVHWFramesContext*)c->hw_frames_ctx->data)->sw_format;
 +#endif
 +    if ( sw_pix_fmt != input_pix_fmt ) {
-         assert( input_picture );
+         CV_Assert( input_picture );
          // let input_picture point to the raw data buffer of 'image'
          _opencv_ffmpeg_av_image_fill_arrays(input_picture, (uint8_t *) data,
                         (AVPixelFormat)input_pix_fmt, width, height);
@@@ -2589,10 -2432,15 +2588,10 @@@ bool CvVideoWriter_FFMPEG::open( const 
              fourcc = supported_tag;
          }
      }
 -#endif
  
      // alloc memory for context
 -#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(53, 2, 0)
      oc = avformat_alloc_context();
-     assert (oc);
 -#else
 -    oc = av_alloc_format_context();
 -#endif
 -    CV_Assert (oc);
++    CV_Assert(oc);
  
      /* set file name */
      oc->oformat = fmt;
Simple merge
Simple merge