/*
------------------------------------------------------------------------------
MetaCam - Extract EXIF information from digital camera files, with
support for Vendor specific blocks.
Copyright (C) 2000 Daniel Stephens (daniel@cheeseplant.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
------------------------------------------------------------------------------
*/

#include <iostream>

#include "datatiff.h"

static const char *rcsid __attribute__((unused))="$Id: dataifdentry.cc,v 1.3 2002/09/02 19:20:01 daniel Exp $";

_DataIFDEntry::_DataIFDEntry(const TIFFDataSource &src, long ofs,
			     long t, short typ, long vals) 
    : _IFDEntry(t, typ), source(src), value_count(vals), offset(ofs)
{
}

_DataIFDEntry::~_DataIFDEntry()
{
}

unsigned long
_DataIFDEntry::values() const
{
    return value_count;
}

vector<tiffUNSIGNED>
_DataIFDEntry::getUVALUE() const 
{
    vector<tiffUNSIGNED> v;
    if (getRawType() == tBYTE) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
	    v.push_back(source.getUByte());
    } else if (getRawType() == tSHORT) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
	    v.push_back(source.getUShort());
    } else if (getRawType() == tLONG) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
	    v.push_back(source.getULong());
    } 
    return v;
}

vector<tiffSIGNED> 
_DataIFDEntry::getSVALUE() const 
{
    vector<tiffSIGNED> v;
    if (getRawType() == tSBYTE) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
 	    v.push_back(source.getSByte());
    } else if (getRawType() == tSSHORT) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
	    v.push_back(source.getSShort());
    } else if (getRawType() == tSLONG) {
	source.seek(offset);
	for (unsigned int i=0; i<value_count; ++i)
	    v.push_back(source.getSLong());
    } 
    return v;
}

vector<tiffRATIONAL> 
_DataIFDEntry::getRATIONAL() const 
{
    vector<tiffRATIONAL> v;
    if (getRawType() != tRATIONAL) {return v;}
    source.seek(offset);
    for (unsigned int i=0; i<value_count; ++i) {
	tiffUNSIGNED n = source.getULong();
	tiffUNSIGNED d = source.getULong();
	v.push_back(tiffRATIONAL(n,d));
    }
    return v;
}

vector<tiffSRATIONAL> 
_DataIFDEntry::getSRATIONAL() const 
{
    vector<tiffSRATIONAL> v;
    if (getRawType() != tSRATIONAL) {return v;}
    source.seek(offset);
    for (unsigned int i=0; i<value_count; ++i) {
	tiffSIGNED n = source.getSLong();
	tiffSIGNED d = source.getSLong();
	v.push_back(tiffSRATIONAL(n,d));
    }
    return v;
}

vector<string> 
_DataIFDEntry::getSTRING() const 
{
    vector<string> v;
    if (getRawType() != tASCII) {return v;}
    char tmpbuf[1024];
    source.seek(offset);
    source.getData((unsigned char *)tmpbuf, value_count);
    tmpbuf[value_count] = 0;
    v.push_back(string(tmpbuf));
    return v;
}

vector<unsigned char> 
_DataIFDEntry::getOPAQUE() const 
{
    vector<unsigned char> v;
    if (getRawType() != tUNDEFINED) {return v;}
    int toget=value_count;
    source.seek(offset);
    while (toget > 0) {
	unsigned char tmpbuf[1024];
	int g = toget;
	if (g>1024) g=1024;
	source.getData((unsigned char *)tmpbuf, g);
	for (int i=0; i<g; ++i) {
	    v.push_back(tmpbuf[i]);
	}
	toget -= g;
    }
    return v;
}

TIFFDataSource
_DataIFDEntry::getSource() const
{
    return source;
}


unsigned long
_DataIFDEntry::getSourceOffset() const
{
    return offset;
}

static const char *hexdigit="0123456789ABCDEF";

void
_DataIFDEntry::outputValue(ostream &os) const
{
    switch (getRawType()) {
    case 2:
    {
	vector<string> v = getSTRING();
	vector<string>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << "\"" << (*iter) << "\",";
	}
	return;
    }
    case 1:
    case 3:
    case 4:
    {
	vector<tiffUNSIGNED> v = getUVALUE();
	vector<tiffUNSIGNED>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 5:
    {
	vector<tiffRATIONAL> v = getRATIONAL();
	vector<tiffRATIONAL>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 7:
    {
	vector<unsigned char> v = getOPAQUE();
	vector<unsigned char>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    unsigned char c=(*iter);
	    os << hexdigit[(c >> 4) & 0x0f] << hexdigit[c&0x0F] << " ";
	}
	return;
    }
    case 6:
    case 8:
    case 9:
    {
	vector<tiffSIGNED> v = getSVALUE();
	vector<tiffSIGNED>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    case 10:
    {
	vector<tiffSRATIONAL> v = getSRATIONAL();
	vector<tiffSRATIONAL>::iterator iter;
	for (iter=v.begin(); iter != v.end(); ++iter) {
	    os << (*iter) << ",";
	}
	return;
    }
    }
    // 11 FLOAT
    // 12 DOUBLE
}

