You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
7.7 KiB
C++

// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* 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.
*/
/*
File: types.cpp
Version: $Name: $ $Revision: 1.1 $
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 26-Jan-04, ahu: created
11-Feb-04, ahu: isolated as a component
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Name: $ $Revision: 1.1 $ $RCSfile: types.cpp,v $")
// *****************************************************************************
// included header files
#include "types.hpp"
// + standard includes
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <utility>
// *****************************************************************************
// class member definitions
namespace Exif {
TypeInfoTable::TypeInfoTable(TypeId typeId, const char* name, long size)
: typeId_(typeId), name_(name), size_(size)
{
}
//! Lookup list of supported IFD type information
const TypeInfoTable TypeInfo::typeInfoTable_[] = {
TypeInfoTable(invalid, "invalid", 0),
TypeInfoTable(unsignedByte, "unsigned byte", 1),
TypeInfoTable(asciiString, "ascii strings", 1),
TypeInfoTable(unsignedShort, "unsigned short", 2),
TypeInfoTable(unsignedLong, "unsigned long", 4),
TypeInfoTable(unsignedRational, "unsigned rational", 8),
TypeInfoTable(invalid6, "invalid (6)", 1),
TypeInfoTable(undefined, "undefined", 1),
TypeInfoTable(signedShort, "signed short", 2),
TypeInfoTable(signedLong, "signed long", 4),
TypeInfoTable(signedRational, "signed rational", 8)
};
const char* TypeInfo::typeName(TypeId typeId)
{
return typeInfoTable_[typeId].name_;
}
long TypeInfo::typeSize(TypeId typeId)
{
return typeInfoTable_[typeId].size_;
}
// *************************************************************************
// free functions
uint16 getUShort(const char* buf, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
return (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
}
else {
return (unsigned char)buf[0] << 8 | (unsigned char)buf[1];
}
}
uint32 getULong(const char* buf, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16
| (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
}
else {
return (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16
| (unsigned char)buf[2] << 8 | (unsigned char)buf[3];
}
}
URational getURational(const char* buf, ByteOrder byteOrder)
{
uint32 nominator = getULong(buf, byteOrder);
uint32 denominator = getULong(buf + 4, byteOrder);
return std::make_pair(nominator, denominator);
}
int16 getShort(const char* buf, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
return (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
}
else {
return (unsigned char)buf[0] << 8 | (unsigned char)buf[1];
}
}
int32 getLong(const char* buf, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16
| (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
}
else {
return (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16
| (unsigned char)buf[2] << 8 | (unsigned char)buf[3];
}
}
Rational getRational(const char* buf, ByteOrder byteOrder)
{
int32 nominator = getLong(buf, byteOrder);
int32 denominator = getLong(buf + 4, byteOrder);
return std::make_pair(nominator, denominator);
}
long us2Data(char* buf, uint16 s, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = s & 0x00ff;
buf[1] = (s & 0xff00) >> 8;
}
else {
buf[0] = (s & 0xff00) >> 8;
buf[1] = s & 0x00ff;
}
return 2;
}
long ul2Data(char* buf, uint32 l, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = l & 0x000000ff;
buf[1] = (l & 0x0000ff00) >> 8;
buf[2] = (l & 0x00ff0000) >> 16;
buf[3] = (l & 0xff000000) >> 24;
}
else {
buf[0] = (l & 0xff000000) >> 24;
buf[1] = (l & 0x00ff0000) >> 16;
buf[2] = (l & 0x0000ff00) >> 8;
buf[3] = l & 0x000000ff;
}
return 4;
}
long ur2Data(char* buf, URational l, ByteOrder byteOrder)
{
long o = ul2Data(buf, l.first, byteOrder);
o += ul2Data(buf+o, l.second, byteOrder);
return o;
}
long s2Data(char* buf, int16 s, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = s & 0x00ff;
buf[1] = (s & 0xff00) >> 8;
}
else {
buf[0] = (s & 0xff00) >> 8;
buf[1] = s & 0x00ff;
}
return 2;
}
long l2Data(char* buf, int32 l, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = l & 0x000000ff;
buf[1] = (l & 0x0000ff00) >> 8;
buf[2] = (l & 0x00ff0000) >> 16;
buf[3] = (l & 0xff000000) >> 24;
}
else {
buf[0] = (l & 0xff000000) >> 24;
buf[1] = (l & 0x00ff0000) >> 16;
buf[2] = (l & 0x0000ff00) >> 8;
buf[3] = l & 0x000000ff;
}
return 4;
}
long r2Data(char* buf, Rational l, ByteOrder byteOrder)
{
long o = l2Data(buf, l.first, byteOrder);
o += l2Data(buf+o, l.second, byteOrder);
return o;
}
void hexdump(std::ostream& os, const char* buf, long len)
{
const std::string::size_type pos = 9 + 16 * 3;
const std::string align(pos, ' ');
long i = 0;
while (i < len) {
os << " "
<< std::setw(4) << std::setfill('0') << std::hex
<< i << " ";
std::ostringstream ss;
do {
unsigned char c = buf[i];
os << std::setw(2) << std::setfill('0')
<< std::hex << (int)c << " ";
ss << ((int)c >= 31 && (int)c < 127 ? buf[i] : '.');
} while (++i < len && i%16 != 0);
std::string::size_type width = 9 + ((i-1)%16 + 1) * 3;
os << (width > pos ? "" : align.substr(width)) << ss.str() << "\n";
}
os << std::dec << std::setfill(' ');
} // hexdump
} // namespace Exif