|
Packit |
01d647 |
// ***************************************************************** -*- C++ -*-
|
|
Packit |
01d647 |
/*
|
|
Packit |
01d647 |
* Copyright (C) 2004-2018 Exiv2 authors
|
|
Packit |
01d647 |
* This program is part of the Exiv2 distribution.
|
|
Packit |
01d647 |
*
|
|
Packit |
01d647 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
01d647 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
01d647 |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
01d647 |
* of the License, or (at your option) any later version.
|
|
Packit |
01d647 |
*
|
|
Packit |
01d647 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
01d647 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
01d647 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
01d647 |
* GNU General Public License for more details.
|
|
Packit |
01d647 |
*
|
|
Packit |
01d647 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
01d647 |
* along with this program; if not, write to the Free Software
|
|
Packit |
01d647 |
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
/*
|
|
Packit |
01d647 |
File: types.cpp
|
|
Packit |
01d647 |
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
|
Packit |
01d647 |
History: 26-Jan-04, ahu: created
|
|
Packit |
01d647 |
11-Feb-04, ahu: isolated as a component
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
// included header files
|
|
Packit |
01d647 |
#include "types.hpp"
|
|
Packit |
01d647 |
#include "enforce.hpp"
|
|
Packit |
01d647 |
#include "futils.hpp"
|
|
Packit |
01d647 |
#include "i18n.h" // for _exvGettext
|
|
Packit |
01d647 |
#include "safe_op.hpp"
|
|
Packit |
01d647 |
#include "unused.h"
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// + standard includes
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
# include <windows.h> // for MultiByteToWideChar etc
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
#include <string>
|
|
Packit |
01d647 |
#include <iostream>
|
|
Packit |
01d647 |
#include <iomanip>
|
|
Packit |
01d647 |
#include <sstream>
|
|
Packit |
01d647 |
#include <utility>
|
|
Packit |
01d647 |
#include <cctype>
|
|
Packit |
01d647 |
#include <ctime>
|
|
Packit |
01d647 |
#include <cstdio>
|
|
Packit |
01d647 |
#include <cstdlib>
|
|
Packit |
01d647 |
#include <cassert>
|
|
Packit |
01d647 |
#include <cstring>
|
|
Packit |
01d647 |
#include <cmath>
|
|
Packit |
01d647 |
#include <math.h>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
namespace {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Information pertaining to the defined %Exiv2 value type identifiers.
|
|
Packit |
01d647 |
struct TypeInfoTable {
|
|
Packit |
01d647 |
Exiv2::TypeId typeId_; //!< Type id
|
|
Packit |
01d647 |
const char* name_; //!< Name of the type
|
|
Packit |
01d647 |
long size_; //!< Bytes per data entry
|
|
Packit |
01d647 |
//! Comparison operator for \em typeId
|
|
Packit |
01d647 |
bool operator==(Exiv2::TypeId typeId) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return typeId_ == typeId;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
//! Comparison operator for \em name
|
|
Packit |
01d647 |
bool operator==(const std::string& name) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return 0 == strcmp(name_, name.c_str());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}; // struct TypeInfoTable
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Lookup list with information of Exiv2 types
|
|
Packit |
01d647 |
const TypeInfoTable typeInfoTable[] = {
|
|
Packit |
01d647 |
{ Exiv2::invalidTypeId, "Invalid", 0 },
|
|
Packit |
01d647 |
{ Exiv2::unsignedByte, "Byte", 1 },
|
|
Packit |
01d647 |
{ Exiv2::asciiString, "Ascii", 1 },
|
|
Packit |
01d647 |
{ Exiv2::unsignedShort, "Short", 2 },
|
|
Packit |
01d647 |
{ Exiv2::unsignedLong, "Long", 4 },
|
|
Packit |
01d647 |
{ Exiv2::unsignedRational, "Rational", 8 },
|
|
Packit |
01d647 |
{ Exiv2::signedByte, "SByte", 1 },
|
|
Packit |
01d647 |
{ Exiv2::undefined, "Undefined", 1 },
|
|
Packit |
01d647 |
{ Exiv2::signedShort, "SShort", 2 },
|
|
Packit |
01d647 |
{ Exiv2::signedLong, "SLong", 4 },
|
|
Packit |
01d647 |
{ Exiv2::signedRational, "SRational", 8 },
|
|
Packit |
01d647 |
{ Exiv2::tiffFloat, "Float", 4 },
|
|
Packit |
01d647 |
{ Exiv2::tiffDouble, "Double", 8 },
|
|
Packit |
01d647 |
{ Exiv2::tiffIfd, "Ifd", 4 },
|
|
Packit |
01d647 |
{ Exiv2::string, "String", 1 },
|
|
Packit |
01d647 |
{ Exiv2::date, "Date", 8 },
|
|
Packit |
01d647 |
{ Exiv2::time, "Time", 11 },
|
|
Packit |
01d647 |
{ Exiv2::comment, "Comment", 1 },
|
|
Packit |
01d647 |
{ Exiv2::directory, "Directory", 1 },
|
|
Packit |
01d647 |
{ Exiv2::xmpText, "XmpText", 1 },
|
|
Packit |
01d647 |
{ Exiv2::xmpAlt, "XmpAlt", 1 },
|
|
Packit |
01d647 |
{ Exiv2::xmpBag, "XmpBag", 1 },
|
|
Packit |
01d647 |
{ Exiv2::xmpSeq, "XmpSeq", 1 },
|
|
Packit |
01d647 |
{ Exiv2::langAlt, "LangAlt", 1 }
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
// class member definitions
|
|
Packit |
01d647 |
namespace Exiv2 {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* TypeInfo::typeName(TypeId typeId)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const TypeInfoTable* tit = find(typeInfoTable, typeId);
|
|
Packit |
01d647 |
if (!tit) return 0;
|
|
Packit |
01d647 |
return tit->name_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
TypeId TypeInfo::typeId(const std::string& typeName)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const TypeInfoTable* tit = find(typeInfoTable, typeName);
|
|
Packit |
01d647 |
if (!tit) return invalidTypeId;
|
|
Packit |
01d647 |
return tit->typeId_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long TypeInfo::typeSize(TypeId typeId)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const TypeInfoTable* tit = find(typeInfoTable, typeId);
|
|
Packit |
01d647 |
if (!tit) return 0;
|
|
Packit |
01d647 |
return tit->size_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::DataBuf(DataBuf& rhs)
|
|
Packit |
01d647 |
: pData_(rhs.pData_), size_(rhs.size_)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::pair<byte*, long> ret = rhs.release();
|
|
Packit |
01d647 |
UNUSED(ret);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::~DataBuf()
|
|
Packit |
01d647 |
{ delete[] pData_; }
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::DataBuf() : pData_(0), size_(0)
|
|
Packit |
01d647 |
{}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::DataBuf(long size) : pData_(new byte[size]()), size_(size)
|
|
Packit |
01d647 |
{}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::DataBuf(const byte* pData, long size)
|
|
Packit |
01d647 |
: pData_(0), size_(0)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (size > 0) {
|
|
Packit |
01d647 |
pData_ = new byte[size];
|
|
Packit |
01d647 |
std::memcpy(pData_, pData, size);
|
|
Packit |
01d647 |
size_ = size;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf& DataBuf::operator=(DataBuf& rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (this == &rhs) return *this;
|
|
Packit |
01d647 |
reset(rhs.release());
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void DataBuf::alloc(long size)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (size > size_) {
|
|
Packit |
01d647 |
delete[] pData_;
|
|
Packit |
01d647 |
pData_ = 0;
|
|
Packit |
01d647 |
size_ = 0;
|
|
Packit |
01d647 |
pData_ = new byte[size];
|
|
Packit |
01d647 |
size_ = size;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
EXV_WARN_UNUSED_RESULT std::pair<byte*, long> DataBuf::release()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::pair<byte*, long> p = std::make_pair(pData_, size_);
|
|
Packit |
01d647 |
pData_ = 0;
|
|
Packit |
01d647 |
size_ = 0;
|
|
Packit |
01d647 |
return p;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void DataBuf::free()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
delete[] pData_;
|
|
Packit |
01d647 |
pData_ = 0;
|
|
Packit |
01d647 |
size_ = 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void DataBuf::reset(std::pair<byte*, long> p)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (pData_ != p.first) {
|
|
Packit |
01d647 |
delete[] pData_;
|
|
Packit |
01d647 |
pData_ = p.first;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
size_ = p.second;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf::DataBuf(const DataBufRef &rhs) : pData_(rhs.p.first), size_(rhs.p.second) {}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf &DataBuf::operator=(DataBufRef rhs) { reset(rhs.p); return *this; }
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exiv2::DataBuf::operator DataBufRef() { return DataBufRef(release()); }
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *************************************************************************
|
|
Packit |
01d647 |
// free functions
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
static void checkDataBufBounds(const DataBuf& buf, size_t end) {
|
|
Packit |
01d647 |
enforce<std::invalid_argument>(end <= static_cast<size_t>(std::numeric_limits<long>::max()),
|
|
Packit |
01d647 |
"end of slice too large to be compared with DataBuf bounds.");
|
|
Packit |
01d647 |
enforce<std::out_of_range>(static_cast<long>(end) <= buf.size_, "Invalid slice bounds specified");
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Slice<byte*> makeSlice(DataBuf& buf, size_t begin, size_t end)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
checkDataBufBounds(buf, end);
|
|
Packit |
01d647 |
return Slice<byte*>(buf.pData_, begin, end);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Slice<const byte*> makeSlice(const DataBuf& buf, size_t begin, size_t end)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
checkDataBufBounds(buf, end);
|
|
Packit |
01d647 |
return Slice<const byte*>(buf.pData_, begin, end);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::ostream& operator<<(std::ostream& os, const Rational& r)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return os << r.first << "/" << r.second;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::istream& operator>>(std::istream& is, Rational& r)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// http://dev.exiv2.org/boards/3/topics/1912?r=1915
|
|
Packit |
01d647 |
if ( std::tolower(is.peek()) == 'f' ) {
|
|
Packit |
01d647 |
char F = 0;
|
|
Packit |
01d647 |
float f = 0.f;
|
|
Packit |
01d647 |
is >> F >> f ;
|
|
Packit |
01d647 |
f = 2.0f * std::log(f) / std::log(2.0f) ;
|
|
Packit |
01d647 |
r = Exiv2::floatToRationalCast(f);
|
|
Packit |
01d647 |
} else {
|
|
Packit |
01d647 |
int32_t nominator = 0;
|
|
Packit |
01d647 |
int32_t denominator = 0;
|
|
Packit |
01d647 |
char c('\0');
|
|
Packit |
01d647 |
is >> nominator >> c >> denominator;
|
|
Packit |
01d647 |
if (c != '/')
|
|
Packit |
01d647 |
is.setstate(std::ios::failbit);
|
|
Packit |
01d647 |
if (is)
|
|
Packit |
01d647 |
r = std::make_pair(nominator, denominator);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return is;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::ostream& operator<<(std::ostream& os, const URational& r)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return os << r.first << "/" << r.second;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::istream& operator>>(std::istream& is, URational& r)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// http://dev.exiv2.org/boards/3/topics/1912?r=1915
|
|
Packit |
01d647 |
/// \todo This implementation seems to be duplicated for the Rational type. Try to remove duplication
|
|
Packit |
01d647 |
if ( std::tolower(is.peek()) == 'f' ) {
|
|
Packit |
01d647 |
char F = 0;
|
|
Packit |
01d647 |
float f = 0.f;
|
|
Packit |
01d647 |
is >> F >> f ;
|
|
Packit |
01d647 |
f = 2.0f * std::log(f) / std::log(2.0f) ;
|
|
Packit |
01d647 |
r = Exiv2::floatToRationalCast(f);
|
|
Packit |
01d647 |
} else {
|
|
Packit |
01d647 |
uint32_t nominator = 0;
|
|
Packit |
01d647 |
uint32_t denominator = 0;
|
|
Packit |
01d647 |
char c('\0');
|
|
Packit |
01d647 |
is >> nominator >> c >> denominator;
|
|
Packit |
01d647 |
if (c != '/')
|
|
Packit |
01d647 |
is.setstate(std::ios::failbit);
|
|
Packit |
01d647 |
if (is)
|
|
Packit |
01d647 |
r = std::make_pair(nominator, denominator);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return is;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
uint16_t getUShort(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return getUShort(makeSliceUntil(buf, 2), byteOrder);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
uint32_t getULong(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
return (byte)buf[3] << 24 | (byte)buf[2] << 16
|
|
Packit |
01d647 |
| (byte)buf[1] << 8 | (byte)buf[0];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
return (byte)buf[0] << 24 | (byte)buf[1] << 16
|
|
Packit |
01d647 |
| (byte)buf[2] << 8 | (byte)buf[3];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
uint64_t getULongLong(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
return (uint64_t)buf[7] << 56 | (uint64_t)buf[6] << 48
|
|
Packit |
01d647 |
| (uint64_t)buf[5] << 40 | (uint64_t)buf[4] << 32
|
|
Packit |
01d647 |
| (uint64_t)buf[3] << 24 | (uint64_t)buf[2] << 16
|
|
Packit |
01d647 |
| (uint64_t)buf[1] << 8 | (uint64_t)buf[0];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
return (uint64_t)buf[0] << 56 | (uint64_t)buf[1] << 48
|
|
Packit |
01d647 |
| (uint64_t)buf[2] << 40 | (uint64_t)buf[3] << 32
|
|
Packit |
01d647 |
| (uint64_t)buf[4] << 24 | (uint64_t)buf[5] << 16
|
|
Packit |
01d647 |
| (uint64_t)buf[6] << 8 | (uint64_t)buf[7];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
URational getURational(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
uint32_t nominator = getULong(buf, byteOrder);
|
|
Packit |
01d647 |
uint32_t denominator = getULong(buf + 4, byteOrder);
|
|
Packit |
01d647 |
return std::make_pair(nominator, denominator);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int16_t getShort(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
return (byte)buf[1] << 8 | (byte)buf[0];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
return (byte)buf[0] << 8 | (byte)buf[1];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int32_t getLong(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
return (byte)buf[3] << 24 | (byte)buf[2] << 16
|
|
Packit |
01d647 |
| (byte)buf[1] << 8 | (byte)buf[0];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
return (byte)buf[0] << 24 | (byte)buf[1] << 16
|
|
Packit |
01d647 |
| (byte)buf[2] << 8 | (byte)buf[3];
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational getRational(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int32_t nominator = getLong(buf, byteOrder);
|
|
Packit |
01d647 |
int32_t denominator = getLong(buf + 4, byteOrder);
|
|
Packit |
01d647 |
return std::make_pair(nominator, denominator);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
float getFloat(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// This algorithm assumes that the internal representation of the float
|
|
Packit |
01d647 |
// type is the 4-byte IEEE 754 binary32 format, which is common but not
|
|
Packit |
01d647 |
// required by the C++ standard.
|
|
Packit |
01d647 |
assert(sizeof(float) == 4);
|
|
Packit |
01d647 |
union {
|
|
Packit |
01d647 |
uint32_t ul_;
|
|
Packit |
01d647 |
float f_;
|
|
Packit |
01d647 |
} u;
|
|
Packit |
01d647 |
u.ul_ = getULong(buf, byteOrder);
|
|
Packit |
01d647 |
return u.f_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
double getDouble(const byte* buf, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// This algorithm assumes that the internal representation of the double
|
|
Packit |
01d647 |
// type is the 8-byte IEEE 754 binary64 format, which is common but not
|
|
Packit |
01d647 |
// required by the C++ standard.
|
|
Packit |
01d647 |
assert(sizeof(double) == 8);
|
|
Packit |
01d647 |
union {
|
|
Packit |
01d647 |
uint64_t ull_;
|
|
Packit |
01d647 |
double d_;
|
|
Packit |
01d647 |
} u;
|
|
Packit |
01d647 |
u.ull_ = 0;
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
u.ull_ = static_cast<uint64_t>(buf[7]) << 56
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[6]) << 48
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[5]) << 40
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[4]) << 32
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[3]) << 24
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[2]) << 16
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[1]) << 8
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[0]);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
u.ull_ = static_cast<uint64_t>(buf[0]) << 56
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[1]) << 48
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[2]) << 40
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[3]) << 32
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[4]) << 24
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[5]) << 16
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[6]) << 8
|
|
Packit |
01d647 |
| static_cast<uint64_t>(buf[7]);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return u.d_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long us2Data(byte* buf, uint16_t s, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
buf[0] = (byte) (s & 0x00ff);
|
|
Packit |
01d647 |
buf[1] = (byte)((s & 0xff00) >> 8);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
buf[0] = (byte)((s & 0xff00) >> 8);
|
|
Packit |
01d647 |
buf[1] = (byte) (s & 0x00ff);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return 2;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long ul2Data(byte* buf, uint32_t l, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
buf[0] = (byte) (l & 0x000000ff);
|
|
Packit |
01d647 |
buf[1] = (byte)((l & 0x0000ff00) >> 8);
|
|
Packit |
01d647 |
buf[2] = (byte)((l & 0x00ff0000) >> 16);
|
|
Packit |
01d647 |
buf[3] = (byte)((l & 0xff000000) >> 24);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
buf[0] = (byte)((l & 0xff000000) >> 24);
|
|
Packit |
01d647 |
buf[1] = (byte)((l & 0x00ff0000) >> 16);
|
|
Packit |
01d647 |
buf[2] = (byte)((l & 0x0000ff00) >> 8);
|
|
Packit |
01d647 |
buf[3] = (byte) (l & 0x000000ff);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return 4;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long ur2Data(byte* buf, URational l, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
long o = ul2Data(buf, l.first, byteOrder);
|
|
Packit |
01d647 |
o += ul2Data(buf+o, l.second, byteOrder);
|
|
Packit |
01d647 |
return o;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long s2Data(byte* buf, int16_t s, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
buf[0] = (byte)(s & 0x00ff);
|
|
Packit |
01d647 |
buf[1] = (byte)((s & 0xff00) >> 8);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
buf[0] = (byte)((s & 0xff00) >> 8);
|
|
Packit |
01d647 |
buf[1] = (byte)(s & 0x00ff);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return 2;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long l2Data(byte* buf, int32_t l, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
buf[0] = (byte)(l & 0x000000ff);
|
|
Packit |
01d647 |
buf[1] = (byte)((l & 0x0000ff00) >> 8);
|
|
Packit |
01d647 |
buf[2] = (byte)((l & 0x00ff0000) >> 16);
|
|
Packit |
01d647 |
buf[3] = (byte)((l & 0xff000000) >> 24);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
buf[0] = (byte)((l & 0xff000000) >> 24);
|
|
Packit |
01d647 |
buf[1] = (byte)((l & 0x00ff0000) >> 16);
|
|
Packit |
01d647 |
buf[2] = (byte)((l & 0x0000ff00) >> 8);
|
|
Packit |
01d647 |
buf[3] = (byte)(l & 0x000000ff);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return 4;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long r2Data(byte* buf, Rational l, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
long o = l2Data(buf, l.first, byteOrder);
|
|
Packit |
01d647 |
o += l2Data(buf+o, l.second, byteOrder);
|
|
Packit |
01d647 |
return o;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long f2Data(byte* buf, float f, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// This algorithm assumes that the internal representation of the float
|
|
Packit |
01d647 |
// type is the 4-byte IEEE 754 binary32 format, which is common but not
|
|
Packit |
01d647 |
// required by the C++ standard.
|
|
Packit |
01d647 |
assert(sizeof(float) == 4);
|
|
Packit |
01d647 |
union {
|
|
Packit |
01d647 |
uint32_t ul_;
|
|
Packit |
01d647 |
float f_;
|
|
Packit |
01d647 |
} u;
|
|
Packit |
01d647 |
u.f_ = f;
|
|
Packit |
01d647 |
return ul2Data(buf, u.ul_, byteOrder);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long d2Data(byte* buf, double d, ByteOrder byteOrder)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// This algorithm assumes that the internal representation of the double
|
|
Packit |
01d647 |
// type is the 8-byte IEEE 754 binary64 format, which is common but not
|
|
Packit |
01d647 |
// required by the C++ standard.
|
|
Packit |
01d647 |
assert(sizeof(double) == 8);
|
|
Packit |
01d647 |
union {
|
|
Packit |
01d647 |
uint64_t ull_;
|
|
Packit |
01d647 |
double d_;
|
|
Packit |
01d647 |
} u;
|
|
Packit |
01d647 |
u.d_ = d;
|
|
Packit |
01d647 |
uint64_t m = 0xff;
|
|
Packit |
01d647 |
if (byteOrder == littleEndian) {
|
|
Packit |
01d647 |
buf[0] = (byte)(u.ull_ & m);
|
|
Packit |
01d647 |
buf[1] = (byte)((u.ull_ & (m << 8)) >> 8);
|
|
Packit |
01d647 |
buf[2] = (byte)((u.ull_ & (m << 16)) >> 16);
|
|
Packit |
01d647 |
buf[3] = (byte)((u.ull_ & (m << 24)) >> 24);
|
|
Packit |
01d647 |
buf[4] = (byte)((u.ull_ & (m << 32)) >> 32);
|
|
Packit |
01d647 |
buf[5] = (byte)((u.ull_ & (m << 40)) >> 40);
|
|
Packit |
01d647 |
buf[6] = (byte)((u.ull_ & (m << 48)) >> 48);
|
|
Packit |
01d647 |
buf[7] = (byte)((u.ull_ & (m << 56)) >> 56);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
buf[0] = (byte)((u.ull_ & (m << 56)) >> 56);
|
|
Packit |
01d647 |
buf[1] = (byte)((u.ull_ & (m << 48)) >> 48);
|
|
Packit |
01d647 |
buf[2] = (byte)((u.ull_ & (m << 40)) >> 40);
|
|
Packit |
01d647 |
buf[3] = (byte)((u.ull_ & (m << 32)) >> 32);
|
|
Packit |
01d647 |
buf[4] = (byte)((u.ull_ & (m << 24)) >> 24);
|
|
Packit |
01d647 |
buf[5] = (byte)((u.ull_ & (m << 16)) >> 16);
|
|
Packit |
01d647 |
buf[6] = (byte)((u.ull_ & (m << 8)) >> 8);
|
|
Packit |
01d647 |
buf[7] = (byte)(u.ull_ & m);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return 8;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void hexdump(std::ostream& os, const byte* buf, long len, long offset)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
const std::string::size_type pos = 8 + 16 * 3 + 2;
|
|
Packit |
01d647 |
const std::string align(pos, ' ');
|
|
Packit |
01d647 |
std::ios::fmtflags f( os.flags() );
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long i = 0;
|
|
Packit |
01d647 |
while (i < len) {
|
|
Packit |
01d647 |
os << " "
|
|
Packit |
01d647 |
<< std::setw(4) << std::setfill('0') << std::hex
|
|
Packit |
01d647 |
<< i + offset << " ";
|
|
Packit |
01d647 |
std::ostringstream ss;
|
|
Packit |
01d647 |
do {
|
|
Packit |
01d647 |
byte c = buf[i];
|
|
Packit |
01d647 |
os << std::setw(2) << std::setfill('0') << std::right
|
|
Packit |
01d647 |
<< std::hex << (int)c << " ";
|
|
Packit |
01d647 |
ss << ((int)c >= 31 && (int)c < 127 ? char(buf[i]) : '.');
|
|
Packit |
01d647 |
} while (++i < len && i%16 != 0);
|
|
Packit |
01d647 |
std::string::size_type width = 9 + ((i-1)%16 + 1) * 3;
|
|
Packit |
01d647 |
os << (width > pos ? "" : align.substr(width)) << ss.str() << "\n";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
os << std::dec << std::setfill(' ');
|
|
Packit |
01d647 |
os.flags(f);
|
|
Packit |
01d647 |
} // hexdump
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool isHex(const std::string& str, size_t size, const std::string& prefix)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if ( str.size() <= prefix.size()
|
|
Packit |
01d647 |
|| str.substr(0, prefix.size()) != prefix) return false;
|
|
Packit |
01d647 |
if ( size > 0
|
|
Packit |
01d647 |
&& str.size() != size + prefix.size()) return false;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
for (size_t i = prefix.size(); i < str.size(); ++i) {
|
|
Packit |
01d647 |
if (!isxdigit(str[i])) return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
} // isHex
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int exifTime(const char* buf, struct tm* tm)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
assert(buf != 0);
|
|
Packit |
01d647 |
assert(tm != 0);
|
|
Packit |
01d647 |
int rc = 1;
|
|
Packit |
01d647 |
int year, mon, mday, hour, min, sec;
|
|
Packit |
01d647 |
int scanned = std::sscanf(buf, "%4d:%2d:%2d %2d:%2d:%2d",
|
|
Packit |
01d647 |
&year, &mon, &mday, &hour, &min, &sec);
|
|
Packit |
01d647 |
if (scanned == 6) {
|
|
Packit |
01d647 |
tm->tm_year = year - 1900;
|
|
Packit |
01d647 |
tm->tm_mon = mon - 1;
|
|
Packit |
01d647 |
tm->tm_mday = mday;
|
|
Packit |
01d647 |
tm->tm_hour = hour;
|
|
Packit |
01d647 |
tm->tm_min = min;
|
|
Packit |
01d647 |
tm->tm_sec = sec;
|
|
Packit |
01d647 |
rc = 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return rc;
|
|
Packit |
01d647 |
} // exifTime
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* exvGettext(const char* str)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
#ifdef EXV_ENABLE_NLS
|
|
Packit |
01d647 |
return _exvGettext(str);
|
|
Packit |
01d647 |
#else
|
|
Packit |
01d647 |
return str;
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
std::string ws2s(const std::wstring& s)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int len;
|
|
Packit |
01d647 |
int slength = (int)s.length() + 1;
|
|
Packit |
01d647 |
len = WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, 0, 0, 0, 0);
|
|
Packit |
01d647 |
char* buf = new char[len];
|
|
Packit |
01d647 |
WideCharToMultiByte(CP_ACP, 0, s.c_str(), slength, buf, len, 0, 0);
|
|
Packit |
01d647 |
std::string r(buf);
|
|
Packit |
01d647 |
delete[] buf;
|
|
Packit |
01d647 |
return r;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::wstring s2ws(const std::string& s)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
int len;
|
|
Packit |
01d647 |
int slength = (int)s.length() + 1;
|
|
Packit |
01d647 |
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
|
Packit |
01d647 |
wchar_t* buf = new wchar_t[len];
|
|
Packit |
01d647 |
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
|
|
Packit |
01d647 |
std::wstring r(buf);
|
|
Packit |
01d647 |
delete[] buf;
|
|
Packit |
01d647 |
return r;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif // EXV_UNICODE_PATH
|
|
Packit |
01d647 |
template<>
|
|
Packit |
01d647 |
bool stringTo<bool>(const std::string& s, bool& ok)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::string lcs(s); /* lowercase string */
|
|
Packit |
01d647 |
for(unsigned i = 0; i < lcs.length(); i++) {
|
|
Packit |
01d647 |
lcs[i] = std::tolower(s[i]);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
/* handle the same values as xmp sdk */
|
|
Packit |
01d647 |
if (lcs == "false" || lcs == "f" || lcs == "0") {
|
|
Packit |
01d647 |
ok = true;
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (lcs == "true" || lcs == "t" || lcs == "1") {
|
|
Packit |
01d647 |
ok = true;
|
|
Packit |
01d647 |
return true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
ok = false;
|
|
Packit |
01d647 |
return false;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long parseLong(const std::string& s, bool& ok)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
long ret = stringTo<long>(s, ok);
|
|
Packit |
01d647 |
if (ok) return ret;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
float f = stringTo<float>(s, ok);
|
|
Packit |
01d647 |
if (ok) return static_cast<long>(f);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational r = stringTo<Rational>(s, ok);
|
|
Packit |
01d647 |
if (ok) {
|
|
Packit |
01d647 |
if (r.second == 0) {
|
|
Packit |
01d647 |
ok = false;
|
|
Packit |
01d647 |
return 0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return static_cast<long>(static_cast<float>(r.first) / r.second);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool b = stringTo<bool>(s, ok);
|
|
Packit |
01d647 |
if (ok) return b ? 1 : 0;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// everything failed, return from stringTo<long> is probably the best fit
|
|
Packit |
01d647 |
return ret;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
float parseFloat(const std::string& s, bool& ok)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
float ret = stringTo<float>(s, ok);
|
|
Packit |
01d647 |
if (ok) return ret;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational r = stringTo<Rational>(s, ok);
|
|
Packit |
01d647 |
if (ok) {
|
|
Packit |
01d647 |
if (r.second == 0) {
|
|
Packit |
01d647 |
ok = false;
|
|
Packit |
01d647 |
return 0.0;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return static_cast<float>(r.first) / r.second;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool b = stringTo<bool>(s, ok);
|
|
Packit |
01d647 |
if (ok) return b ? 1.0f : 0.0f;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// everything failed, return from stringTo<float> is probably the best fit
|
|
Packit |
01d647 |
return ret;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational parseRational(const std::string& s, bool& ok)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Rational ret = stringTo<Rational>(s, ok);
|
|
Packit |
01d647 |
if (ok) return ret;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long l = stringTo<long>(s, ok);
|
|
Packit |
01d647 |
if (ok) return Rational(l, 1);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
float f = stringTo<float>(s, ok);
|
|
Packit |
01d647 |
if (ok) return floatToRationalCast(f);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
bool b = stringTo<bool>(s, ok);
|
|
Packit |
01d647 |
if (ok) return b ? Rational(1, 1) : Rational(0, 1);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// everything failed, return from stringTo<Rational> is probably the best fit
|
|
Packit |
01d647 |
return ret;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational floatToRationalCast(float f)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
#if defined(_MSC_VER) && _MSC_VER < 1800
|
|
Packit |
01d647 |
if (!_finite(f)) {
|
|
Packit |
01d647 |
#else
|
|
Packit |
01d647 |
if (!std::isfinite(f)) {
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
return Rational(f > 0 ? 1 : -1, 0);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
// Beware: primitive conversion algorithm
|
|
Packit |
01d647 |
int32_t den = 1000000;
|
|
Packit |
01d647 |
const long f_as_long = static_cast<long>(f);
|
|
Packit |
01d647 |
if (Safe::abs(f_as_long) > 2147) {
|
|
Packit |
01d647 |
den = 10000;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (Safe::abs(f_as_long) > 214748) {
|
|
Packit |
01d647 |
den = 100;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (Safe::abs(f_as_long) > 21474836) {
|
|
Packit |
01d647 |
den = 1;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
const float rnd = f >= 0 ? 0.5f : -0.5f;
|
|
Packit |
01d647 |
const int32_t nom = static_cast<int32_t>(f * den + rnd);
|
|
Packit |
01d647 |
const int32_t g = gcd(nom, den);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return Rational(nom / g, den / g);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
} // namespace Exiv2
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_ENABLE_NLS
|
|
Packit |
01d647 |
// Declaration is in i18n.h
|
|
Packit |
01d647 |
const char* _exvGettext(const char* str)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
static bool exvGettextInitialized = false;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
if (!exvGettextInitialized) {
|
|
Packit |
01d647 |
//bindtextdomain(EXV_PACKAGE_NAME, EXV_LOCALEDIR);
|
|
Packit |
01d647 |
const std::string localeDir = Exiv2::getProcessPath() + EXV_LOCALEDIR;
|
|
Packit |
01d647 |
bindtextdomain(EXV_PACKAGE_NAME, localeDir.c_str());
|
|
Packit |
01d647 |
# ifdef EXV_HAVE_BIND_TEXTDOMAIN_CODESET
|
|
Packit |
01d647 |
bind_textdomain_codeset (EXV_PACKAGE_NAME, "UTF-8");
|
|
Packit |
01d647 |
# endif
|
|
Packit |
01d647 |
exvGettextInitialized = true;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return dgettext(EXV_PACKAGE_NAME, str);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#endif // EXV_ENABLE_NLS
|