/* checks if TIF with tag and type ASCII */
ret_t check_tag_has_valid_asciivalue(ctiff_t * ctif, tag_t tag) {
  tifp_check( ctif);
    TIFFDataType datatype =  TIFFGetRawTagType( ctif, tag );
#ifdef DEBUG
  printf("### datatype=%i \n", datatype);
#endif
  char *string=NULL;
  uint32 count=0;
  int r = 0;
  if (datatype == TIFF_ASCII) {
    //printf("check if tag %u (%s) has valid asciivalue\n", tag, TIFFTagName(tif, tag));
    tif_rules_tag(tag, "has valid asciivalue");

    int found=TIFFGetField(ctif->tif, tag, &string, &count);
    if (1==found) { /* there exists a tag */
      for (int i=0; i<count; i++) {
        if (string[i] == '\0') {
          r = i+1;
          break;
        }
      }
    }
  }
  if (0 != r) {
    char array[VALUESTRLEN];
    snprintf(array, sizeof(array), "incorrect asciivalue (\\0 at position %i in %i-len String)", r, count);
    return tif_fails_tag( tag, "", array);
  } else {
    ret_t res;
    res.returnmsg=NULL;
    res.returncode=0;
    return res;
  }
}
ret_t check_tag_has_value(ctiff_t * ctif, tag_t tag, unsigned int value) {
  // printf("check if tag %u (%s) has value %u\n", tag, TIFFTagName( tag), value);
  tifp_check( ctif);
  tif_rules_tag(tag, "has value");
  ret_t ret;
  ret = check_tag_has_valid_type( ctif, tag);
  if (ret.returncode == 0) {
    ret =  check_tag_has_value_quiet( ctif, tag, value);
    if (ret.returncode == 0) {
      return ret;
    }
  }
  return tif_fails_by_returns( ret );
}
/* check if offsets are greater zero */
ret_t check_all_offsets_are_greater_zero(ctiff_t * ctif) {
  GET_EMPTY_RET(ret)
  tifp_check( ctif);
  int count = get_ifd0_count( ctif);
  int tagidx;
  for (tagidx = 0; tagidx< count; tagidx++) {
    ifd_entry_t ifd_entry = TIFFGetRawTagIFDListEntry( ctif, tagidx );
    uint32 tag = TIFFGetRawTagListEntry( ctif, tagidx);
    if (ifd_entry.value_or_offset==is_offset || tag == TIFFTAG_EXIFIFD) {
      uint32 offset=0;
      if (ifd_entry.value_or_offset==is_offset) offset = ifd_entry.data32offset;
      else if (tag == TIFFTAG_EXIFIFD) {
        if (ifd_entry.count > 1) {
          ret = set_value_found_ret(&ret, int2str(ifd_entry.count));
          ret.returncode = tagerror_expected_count_isgreaterone;
          return ret;
        }
        switch (ifd_entry.datatype) {
          case TIFF_LONG: { /*  correct type */
                            offset = ifd_entry.data32;
                            break;
                          }
          default: { /*  incorrect type for EXIF IFD */
                     ret = set_value_found_ret(&ret, TIFFTypeName(ifd_entry.datatype));
                     ret.returncode = tagerror_unexpected_type_found;
                     return ret;
                     /* break; */
                   };

        }
      } /*  end else if tag == TIFFTAG_EXIFIFD */
      if ( 0 == offset) {
        // FIXME: tif_fails?
        char array[TIFFAILSTRLEN];
        snprintf(array, sizeof(array), "tag %u pointing to 0x%08x", tag, offset);
        ret = set_value_found_ret (&ret, array);
        ret.returncode = tagerror_offset_is_zero;
        return ret;
      }
    }
  }
  ret.returncode=is_valid;
  return ret;
}
/* checks if TIF has a specified tag */
ret_t check_tag_has_valid_type(ctiff_t * ctif, tag_t tag) {
  //printf("check if tag %u (%s) has valid type\n", tag, TIFFTagName(tif, tag));
  tifp_check( ctif);
  tif_rules_tag(tag, "has valid type");
  TIFFDataType datatype =  TIFFGetRawTagType( ctif, tag );
#ifdef DEBUG
  printf("### datatype=%i \n", datatype);
#endif
  int res = 0;
  switch (tag) {
    case TIFFTAG_ARTIST:            res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_BADFAXLINES:       res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_BITSPERSAMPLE:     res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_CELLLENGTH:        res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_CELLWIDTH:         res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_COLORMAP:          res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_COMPRESSION:       res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_COPYRIGHT:         res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_DATETIME:          res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_DOCUMENTNAME:      res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_DOTRANGE:          res=(datatype  ==  TIFF_BYTE) || (datatype ==  TIFF_SHORT);; break;
    case TIFFTAG_EXTRASAMPLES:      res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_FILLORDER:         res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_FREEBYTECOUNTS:    res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_FREEOFFSETS:       res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_GRAYRESPONSECURVE: res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_GRAYRESPONSEUNIT:  res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_HALFTONEHINTS:     res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_HOSTCOMPUTER:      res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_ICCPROFILE:        res=(datatype  ==  TIFF_UNDEFINED); break;
    case TIFFTAG_IMAGEDEPTH:        res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_IMAGEDESCRIPTION:  res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_IMAGELENGTH:       res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT);; break;
    case TIFFTAG_IMAGEWIDTH:        res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT);; break;
    case TIFFTAG_INKNAMES:          res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_INKSET:            res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_JPEGPROC:          res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_MAKE:              res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_MAXSAMPLEVALUE:    res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_MINSAMPLEVALUE:    res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_MODEL:             res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_NUMBEROFINKS:      res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_ORIENTATION:       res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_OSUBFILETYPE:      res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_PAGENUMBER:        res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_PHOTOMETRIC:       res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_PLANARCONFIG:      res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_PREDICTOR:         res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_PRIMARYCHROMATICITIES:  res=(datatype  ==  TIFF_RATIONAL); break;
    case TIFFTAG_REFERENCEBLACKWHITE:    res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_RESOLUTIONUNIT:    res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_ROWSPERSTRIP:      res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_SAMPLEFORMAT:      res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_SAMPLESPERPIXEL:   res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_SMAXSAMPLEVALUE:   res=(datatype  == TIFF_ANY); break;
    case TIFFTAG_SMINSAMPLEVALUE:   res=(datatype  == TIFF_ANY); break;
    case TIFFTAG_SOFTWARE:          res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_STRIPBYTECOUNTS:   res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_STRIPOFFSETS:      res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_SUBFILETYPE:       res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_T4OPTIONS:         res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_T6OPTIONS:         res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_TARGETPRINTER:     res=(datatype  ==  TIFF_ASCII); break;
    case TIFFTAG_THRESHHOLDING:     res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_TILEBYTECOUNTS:    res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_TILELENGTH:        res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_TILEOFFSETS:       res=(datatype  ==  TIFF_LONG); break;
    case TIFFTAG_TILEWIDTH:         res=(datatype  ==  TIFF_LONG) || (datatype ==  TIFF_SHORT); break;
    case TIFFTAG_TRANSFERFUNCTION:  res=(datatype  ==  TIFF_SHORT); break;
    case TIFFTAG_WHITEPOINT:        res=(datatype  ==  TIFF_RATIONAL); break;
    case TIFFTAG_XRESOLUTION:       res=(datatype  ==  TIFF_RATIONAL); break;
    case TIFFTAG_YRESOLUTION:       res=(datatype  ==  TIFF_RATIONAL); break;
    default: res = 1;
  }
  if (!res) {
    char array[VALUESTRLEN];
    snprintf(array, sizeof(array), "with incorrect type: %i", datatype);
    return tif_returns( tag, "", array);
  } else {
    ret_t tmp_res;
    tmp_res.returnmsg=NULL;
    tmp_res.returncode=0;
    return tmp_res;
  }
  /* we check only count, because we evaluate only int-values */
}