TYPEMAP

StringWrapper* T_OPENCV_STRING
vector_DMatchWrapper* T_OPENCV_VECTOR
vector_KeyPointWrapper* T_OPENCV_VECTOR
vector_MatWrapper* T_OPENCV_VECTOR
vector_StringWrapper* T_OPENCV_VECTOR
vector_vector_charWrapper* T_OPENCV_VECTOR
vector_vector_ucharWrapper* T_OPENCV_VECTOR
vector_vector_Point2fWrapper* T_OPENCV_VECTOR
vector_vector_DMatchWrapper* T_OPENCV_VECTOR2
vector_vector_KeyPointWrapper* T_OPENCV_VECTOR2
RotatedRectWrapper* T_PTROBJ_SPECIAL
RNGWrapper* T_PTROBJ_SPECIAL
TermCriteriaWrapper* T_PTROBJ_SPECIAL
KeyPointWrapper* T_PTROBJ_SPECIAL
DMatchWrapper* T_PTROBJ_SPECIAL
FileStorageWrapper* T_PTROBJ_SPECIAL
FileNodeWrapper* T_PTROBJ_SPECIAL

uint64_t T_IV

INPUT
T_PTROBJ_SPECIAL
  if (!SvOK($arg)) {
    $var = NULL;
  } else if (sv_derived_from($arg, \"${(my $ntt=$type)=~s/(.*?)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\")) {
    IV tmp = SvIV((SV*)SvRV($arg));
    $var = INT2PTR($type, tmp);
  } else
    croak(\"$var is not of type ${(my $ntt=$type)=~s/(.*?)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\")

T_OPENCV_STRING
  {
  cw_error CW_err = cw_String_new(&$var, NULL, SvOK($arg) ? SvPV_nolen($arg) : NULL);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  }

T_OPENCV_VECTOR
  {
  if (!SvOK($arg)) {
    cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_new(&$var, NULL);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  } else {
    if (!SvROK($arg)) PDL_CORE_(pdl_barf)(\"$var not a reference\");
    if(SvTYPE(SvRV($arg)) != SVt_PVAV) PDL_CORE_(pdl_barf)(\"$var not an array-ref\");
    AV *av = (AV *)SvRV($arg);
    PDL_Indx count = av_len(av) + 1, i = 0, dim0 = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_dim0();
    for (i = 0; i < count; i++)
      if (!av_fetch(av, i, 0)) PDL_CORE_(pdl_barf)(\"$var index %td not a valid SV\", i);
    ${(my $novec=$type)=~s/^vector_//; \$novec} wrappers[count];
    for (i = 0; i < count; i++) {
      SV **sp = av_fetch(av, i, 0);
      ${ $type =~ /String/ ? \qq{
      cw_error CW_err = cw_String_new(&wrappers[i], NULL, SvOK(*sp) ? SvPV_nolen(*sp) : NULL);
      PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
      } : $type =~ /DMatch|KeyPoint/ ? \qq{
      cw_error CW_err = {0,NULL,0};
      if (sv_derived_from(*sp, \"${(my $ntt=$type)=~s/^vector_(.*)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\")){
        IV tmp = SvIV((SV*)SvRV(*sp));
        wrappers[i] = INT2PTR(${(my $novec=$type)=~s/^vector_//; \$novec}, tmp);
      } else {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(pdl_barf)(\"$var is not of type ${(my $ntt=$type)=~s/(.*?)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\");
      }
      } : $type =~ /Mat/ ? \qq{
      pdl *p = PDL_CORE_(SvPDLV)(*sp);
      if (!p) {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(pdl_barf)(\"$var index %td not a valid ndarray\", i);
      }
      pdl_error PDL_err = PDL_CORE_(make_physical)(p);
      if (PDL_err.error) {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(barf_if_error)(PDL_err);
      }
      cw_error CW_err = cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_newWithDims(&wrappers[i], p->ndims > 0 ? p->dims[0] : 1, p->ndims > 1 ? p->dims[1] : 1, p->ndims > 2 ? p->dims[2] : 1, p->datatype, p->data);
      } : $type =~ /vector_vector/ ? \qq{
      pdl *p = PDL_CORE_(SvPDLV)(*sp);
      if (!p) {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(pdl_barf)(\"$var index %td not a valid ndarray\", i);
      }
      if (dim0 && (p->ndims < 1 || p->dims[0] != dim0)) {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(pdl_barf)(\"$var index %td did not have dim 0 of %td, had %td\", i, dim0, p->ndims < 1 ? -1 : p->dims[0]);
      }
      pdl_error PDL_err = PDL_CORE_(make_physical)(p);
      if (PDL_err.error) {
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
        PDL_CORE_(barf_if_error)(PDL_err);
      }
      cw_error CW_err = cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_newWithVals(&wrappers[i], p->data, p->dims[dim0 ? 1 : 0]);
      } : die qq{Can't handle $type}}
      if (CW_err.error)
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
      PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    }
    cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_newWithVals(&$var, wrappers, count);
    for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  }
  }

T_OPENCV_VECTOR2
  {
  if (!SvOK($arg)) {
    cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_new(&$var, NULL);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  } else {
    if (!SvROK($arg)) PDL_CORE_(pdl_barf)(\"$var not a reference\");
    if(SvTYPE(SvRV($arg)) != SVt_PVAV) PDL_CORE_(pdl_barf)(\"$var not an array-ref\");
    AV *av = (AV *)SvRV($arg);
    PDL_Indx count = av_len(av) + 1, i = 0;
    for (i = 0; i < count; i++) {
      SV **sp = av_fetch(av, i, 0);
      if (!sp) PDL_CORE_(pdl_barf)(\"$var index %td not a valid SV\", i);
      if (!SvROK(*sp)) PDL_CORE_(pdl_barf)(\"$var index %td not a reference\", i);
      if(SvTYPE(SvRV(*sp)) != SVt_PVAV) PDL_CORE_(pdl_barf)(\"$var index %td not an array-ref\", i);
      AV *av2 = (AV *)SvRV(*sp);
      PDL_Indx count2 = av_len(av2) + 1, i2 = 0;
      for (i2 = 0; i2 < count2; i2++) {
        SV **sp2 = av_fetch(av2, i2, 0);
        if (!sp2) PDL_CORE_(pdl_barf)(\"$var index %td/%td not a valid SV\", i, i2);
        if (!SvOK(*sp2)) PDL_CORE_(pdl_barf)(\"$var index %td/%td not defined\", i, i2);
        if (!SvROK(*sp2)) PDL_CORE_(pdl_barf)(\"$var index %td/%td not a reference\", i, i2);
        if (!sv_derived_from(*sp2, \"${(my $novecstar=$type)=~s/^(?:vector_){2}(.*)Wrapper\s*\**$/PDL::OpenCV::$1/; \$novecstar}\"))
          PDL_CORE_(pdl_barf)(\"$var index %td/%td not a ${(my $novecstar=$type)=~s/^(?:vector_){2}(.*)Wrapper\s*\**$/PDL::OpenCV::$1/; \$novecstar}\", i, i2);
      }
    }
    ${(my $novec=$type)=~s/^vector_//; \$novec} wrappers[count];
    for (i = 0; i < count; i++) {
      SV **sp = av_fetch(av, i, 0);
      AV *av2 = (AV *)SvRV(*sp);
      PDL_Indx count2 = av_len(av2) + 1, i2 = 0;
      ${(my $novec=$type)=~s/^(?:vector_){2}//; \$novec} wrap2[count2];
      for (i2 = 0; i2 < count2; i2++) {
        SV **sp2 = av_fetch(av2, i2, 0);
        IV tmp = SvIV((SV*)SvRV(*sp2));
        wrap2[i2] = INT2PTR(${(my $novec=$type)=~s/^(?:vector_){2}//; \$novec}, tmp);
      }
      cw_error CW_err = cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_newWithVals(&wrappers[i], wrap2, count2);
      if (CW_err.error)
        for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
      PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    }
    cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_newWithVals(&$var, wrappers, count);
    for (i--; i >= 0; i--) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrappers[i]);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  }
  }

OUTPUT
T_PTROBJ_SPECIAL
  sv_setref_pv($arg, \"${(my $ntt=$type)=~s/(.*?)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\",
               (void*)$var);

T_OPENCV_STRING
  {
  const char *cptr;
  cw_error CW_err = cw_String_c_str(&cptr, $var);
  if (CW_err.error) cw_String_DESTROY($var);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  sv_setpv((SV*)$arg, cptr);
  cw_String_DESTROY($var);
  }

T_OPENCV_VECTOR
  {
  PDL_Indx sz, i, dim0 = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_dim0();
  cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_size(&sz, $var);
  if (CW_err.error)
    cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  ${(my $novec=$type)=~s/^vector_//; \$novec} wrap2[sz];
  CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_copyDataTo($var, wrap2);
  if (CW_err.error)
    cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  AV *av = newAV(); av_extend(av, sz);
  for (i = 0; i < sz; i++) {
    SV* pxsv = newSV(0);
    if (!pxsv) {
      for (; i < sz; i++) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i]);
      PDL_CORE_(pdl_barf)(\"Failed to create SV\");
    }
    ${ $type =~ /String/ ? \qq{
    const char *cptr;
    CW_err = cw_String_c_str(&cptr, wrap2[i]);
    if (CW_err.error)
      for (; i < sz; i++) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i]);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    sv_setpv(pxsv, cptr);
    } : $type =~ /DMatch|KeyPoint/ ? \qq{
    sv_setref_pv(pxsv, \"${(my $ntt=$type)=~s/^vector_(.*)Wrapper\s*\**$/PDL::OpenCV::$1/;\$ntt}\",
                 wrap2[i]);
    } : $type =~ /Mat/ ? \qq{
    PDL_Indx d1, d2, d3; pdl_datatypes dt;
    cw_Mat_pdlDims(wrap2[i], &dt, &d1, &d2, &d3);
    pdl* px = PDL_CORE_(pdlnew)();
    if (!px) PDL_CORE_(pdl_barf)(\"Failed to create pdl\");
    PDL_CORE_(SetSV_PDL)(pxsv, px);
    PDL_Indx pdims[] = { d1, d2, d3 };
    PDL_CORE_(barf_if_error)(PDL_CORE_(setdims)(px,pdims,3));
    px->datatype = dt;
    PDL_CORE_(barf_if_error)(PDL_CORE_(make_physical)(px));
    CW_err = cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_copyDataTo(wrap2[i], px->data, px->nbytes);
    if (CW_err.error)
      for (; i < sz; i++) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i]);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    } : $type =~ /vector_vector/ ? \qq{
    PDL_Indx d1; pdl_datatypes dt = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_pdltype();
    cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_size(&d1, wrap2[i]);
    pdl* px = PDL_CORE_(pdlnew)();
    if (!px) PDL_CORE_(pdl_barf)(\"Failed to create pdl\");
    PDL_CORE_(SetSV_PDL)(pxsv, px);
    if (dim0) {
      PDL_Indx pdims[] = { dim0, d1 };
      PDL_CORE_(barf_if_error)(PDL_CORE_(setdims)(px,pdims,2));
    } else {
      PDL_Indx pdims[] = { d1 };
      PDL_CORE_(barf_if_error)(PDL_CORE_(setdims)(px,pdims,1));
    }
    px->datatype = dt;
    PDL_CORE_(barf_if_error)(PDL_CORE_(make_physical)(px));
    CW_err = cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_copyDataTo(wrap2[i], px->data, px->nbytes);
    if (CW_err.error)
      for (; i < sz; i++) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i]);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    } : die qq{Can't handle $type}}
    if (!av_store(av, i, pxsv)) PDL_CORE_(pdl_barf)(\"Failed to push SV\");
    cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i]);
  }
  cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  sv_setsv($arg, newRV_noinc((SV*)av));
  }

T_OPENCV_VECTOR2
  {
  PDL_Indx count, i;
  cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_size(&count, $var);
  if (CW_err.error)
    cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  ${(my $novec=$type)=~s/^vector_//; \$novec} wrapper[count];
  CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_copyDataTo($var, wrapper);
  if (CW_err.error)
    cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
  AV *av = newAV(); av_extend(av, count);
  for (i = 0; i < count; i++) {
    PDL_Indx count2, i2;
    cw_error CW_err = cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_size(&count2, $var);
    if (CW_err.error)
      cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
    PDL_CORE_(barf_if_error)(*(pdl_error *)&CW_err);
    AV *av2 = newAV(); av_extend(av2, count);
    ${(my $novec=$type)=~s/^(?:vector_){2}//; \$novec} wrap2[count2];
    for (i2 = 0; i2 < count2; i2++) {
      SV* pxsv = newSV(0);
      if (!pxsv) {
        for (; i < count; i++) cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrapper[i]);
        for (; i2 < count2; i2++) cw_${(my $novecstar=$type)=~s/^(?:vector_){2}(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrap2[i2]);
        PDL_CORE_(pdl_barf)(\"Failed to create SV\");
      }
      sv_setref_pv(pxsv, \"${(my $novecstar=$type)=~s/^(?:vector_){2}(.*)Wrapper\s*\**$/$1/; \$novecstar}\",
                   wrap2[i2]);
      if (!av_store(av2, i2, pxsv)) PDL_CORE_(pdl_barf)(\"Failed to push SV\");
    }
    if (!av_store(av, i, newRV_noinc((SV*)av2))) PDL_CORE_(pdl_barf)(\"Failed to push AVref\");
    cw_${(my $novecstar=$type)=~s/^vector_(.*)Wrapper\s*\**$/$1/; \$novecstar}_DESTROY(wrapper[i]);
  }
  cw_${(my $nostar=$type)=~s/Wrapper\s*\**$//; \$nostar}_DESTROY($var);
  sv_setsv($arg, newRV_noinc((SV*)av));
  }
