Changed Value::read() to return an int indicating success instead of throwing. Added Support for HHMMSS and H:M:S formats to TimeValue (assumes timezone is UTC). Fixes bug #440.

v0.27.3
Andreas Huggel 20 years ago
parent 06e5c0719e
commit c32e706c36

@ -1065,12 +1065,13 @@ namespace Action {
<< ")" << std::endl;
}
Exiv2::Value::AutoPtr value = Exiv2::Value::create(modifyCmd.typeId_);
value->read(modifyCmd.value_);
if (modifyCmd.metadataId_ == exif) {
image_->exifData().add(Exiv2::ExifKey(modifyCmd.key_), value.get());
}
if (modifyCmd.metadataId_ == iptc) {
image_->iptcData().add(Exiv2::IptcKey(modifyCmd.key_), value.get());
if (0 == value->read(modifyCmd.value_)) {
if (modifyCmd.metadataId_ == exif) {
image_->exifData().add(Exiv2::ExifKey(modifyCmd.key_), value.get());
}
if (modifyCmd.metadataId_ == iptc) {
image_->iptcData().add(Exiv2::IptcKey(modifyCmd.key_), value.get());
}
}
}
@ -1100,8 +1101,9 @@ namespace Action {
if (modifyCmd.explicitType_ || value.get() == 0) {
value = Exiv2::Value::create(modifyCmd.typeId_);
}
value->read(modifyCmd.value_);
metadatum->setValue(value.get());
if (0 == value->read(modifyCmd.value_)) {
metadatum->setValue(value.get());
}
}
void Modify::delMetadatum(const ModifyCmd& modifyCmd)

@ -136,7 +136,6 @@ namespace Exiv2 {
const byte* pRead = buf;
iptcMetadata_.clear();
int rc = 0;
uint16_t record = 0;
uint16_t dataSet = 0;
uint32_t sizeData = 0;
@ -166,12 +165,11 @@ namespace Exiv2 {
sizeData = getUShort(pRead, bigEndian);
pRead += 2;
}
rc = readData(dataSet, record, pRead, sizeData);
if( rc ) return rc;
readData(dataSet, record, pRead, sizeData);
pRead += sizeData;
}
return rc;
return 0;
} // IptcData::read
int IptcData::readData(uint16_t dataSet, uint16_t record,
@ -180,10 +178,12 @@ namespace Exiv2 {
Value::AutoPtr value;
TypeId type = IptcDataSets::dataSetType(dataSet, record);
value = Value::create(type);
value->read(data, sizeData, bigEndian);
IptcKey key(dataSet, record);
add(key, value.get());
return 0;
int rc = value->read(data, sizeData, bigEndian);
if (0 == rc) {
IptcKey key(dataSet, record);
add(key, value.get());
}
return rc;
}
DataBuf IptcData::copy()

@ -130,13 +130,14 @@ namespace Exiv2 {
return *this;
}
void DataValue::read(const byte* buf, long len, ByteOrder byteOrder)
int DataValue::read(const byte* buf, long len, ByteOrder byteOrder)
{
// byteOrder not needed
value_.assign(buf, buf + len);
return 0;
}
void DataValue::read(const std::string& buf)
int DataValue::read(const std::string& buf)
{
std::istringstream is(buf);
int tmp;
@ -144,6 +145,7 @@ namespace Exiv2 {
while (is >> tmp) {
value_.push_back(static_cast<byte>(tmp));
}
return 0;
}
long DataValue::copy(byte* buf, ByteOrder byteOrder) const
@ -181,15 +183,17 @@ namespace Exiv2 {
return *this;
}
void StringValueBase::read(const std::string& buf)
int StringValueBase::read(const std::string& buf)
{
value_ = buf;
return 0;
}
void StringValueBase::read(const byte* buf, long len, ByteOrder byteOrder)
int StringValueBase::read(const byte* buf, long len, ByteOrder byteOrder)
{
// byteOrder not needed
value_ = std::string(reinterpret_cast<const char*>(buf), len);
return 0;
}
long StringValueBase::copy(byte* buf, ByteOrder byteOrder) const
@ -229,10 +233,11 @@ namespace Exiv2 {
return *this;
}
void AsciiValue::read(const std::string& buf)
int AsciiValue::read(const std::string& buf)
{
value_ = buf;
if (value_[value_.size()-1] != '\0') value_ += '\0';
return 0;
}
AsciiValue* AsciiValue::clone_() const
@ -307,23 +312,28 @@ namespace Exiv2 {
return *this;
}
void CommentValue::read(const std::string& comment)
int CommentValue::read(const std::string& comment)
{
std::string c = comment;
CharsetId charsetId = undefined;
if (comment.length() > 8 && comment.substr(0, 8) == "charset=") {
std::string::size_type pos = comment.find_first_of(' ');
std::string name = comment.substr(8, pos-8);
// Strip quotes (so you can also to specify the charset without quotes)
// Strip quotes (so you can also specify the charset without quotes)
if (name[0] == '"') name = name.substr(1);
if (name[name.length()-1] == '"') name = name.substr(0, name.length()-1);
charsetId = CharsetInfo::charsetIdByName(name);
if (charsetId == invalidCharsetId) throw Error(28, name);
if (charsetId == invalidCharsetId) {
#ifndef SUPPRESS_WARNINGS
std::cerr << Error(28, name) << "\n";
#endif
return 1;
}
c.clear();
if (pos != std::string::npos) c = comment.substr(pos+1);
}
const std::string code(CharsetInfo::code(charsetId), 8);
StringValueBase::read(code + c);
return StringValueBase::read(code + c);
}
std::ostream& CommentValue::write(std::ostream& os) const
@ -374,43 +384,62 @@ namespace Exiv2 {
return *this;
}
void DateValue::read(const byte* buf, long len, ByteOrder byteOrder)
int DateValue::read(const byte* buf, long len, ByteOrder /*byteOrder*/)
{
// byteOrder not needed
// Hard coded to read Iptc style dates
if (len != 8) throw Error(29);
if (len != 8) {
#ifndef SUPPRESS_WARNINGS
std::cerr << Error(29) << "\n";
#endif
return 1;
}
int scanned = sscanf(reinterpret_cast<const char*>(buf),
"%4d%2d%2d",
&date_.year, &date_.month, &date_.day);
if (scanned != 3) throw Error(29);
if (scanned != 3) {
#ifndef SUPPRESS_WARNINGS
std::cerr << Error(29) << "\n";
#endif
return 1;
}
return 0;
}
void DateValue::read(const std::string& buf)
int DateValue::read(const std::string& buf)
{
// byteOrder not needed
// Hard coded to read Iptc style dates
if (buf.length() < 8) throw Error(29);
if (buf.length() < 8) {
#ifndef SUPPRESS_WARNINGS
std::cerr << Error(29) << "\n";
#endif
return 1;
}
int scanned = sscanf(buf.data(),
"%4d-%d-%d",
&date_.year, &date_.month, &date_.day);
if (scanned != 3) throw Error(29);
if (scanned != 3) {
#ifndef SUPPRESS_WARNINGS
std::cerr << Error(29) << "\n";
#endif
return 1;
}
return 0;
}
void DateValue::setDate( const Date& src )
void DateValue::setDate(const Date& src)
{
date_.year = src.year;
date_.month = src.month;
date_.day = src.day;
}
long DateValue::copy(byte* buf, ByteOrder byteOrder) const
long DateValue::copy(byte* buf, ByteOrder /*byteOrder*/) const
{
// byteOrder not needed
// sprintf wants to add the null terminator, so use oversized buffer
char temp[9];
int wrote = sprintf( temp, "%04d%02d%02d",
date_.year, date_.month, date_.day);
int wrote = sprintf(temp, "%04d%02d%02d",
date_.year, date_.month, date_.day);
assert(wrote == 8);
memcpy(buf, temp, 8);
return 8;
@ -465,40 +494,82 @@ namespace Exiv2 {
return *this;
}
void TimeValue::read(const byte* buf, long len, ByteOrder byteOrder)
int TimeValue::read(const byte* buf, long len, ByteOrder /*byteOrder*/)
{
// byteOrder not needed
// Hard coded to read Iptc style times
if (len != 11) throw Error(30);
char plusMinus;
int scanned = sscanf(reinterpret_cast<const char*>(buf),
"%2d%2d%2d%1c%2d%2d",
&time_.hour, &time_.minute, &time_.second,
&plusMinus, &time_.tzHour, &time_.tzMinute );
if (scanned != 6) throw Error(30);
if (plusMinus == '-') {
time_.tzHour *= -1;
time_.tzMinute *= -1;
// Hard coded to read HHMMSS or Iptc style times
int rc = 1;
if (len == 6) {
// Try to read (non-standard) HHMMSS format
rc = scanTime3(reinterpret_cast<const char*>(buf),
"%2d%2d%2d");
}
if (len == 11) {
rc = scanTime6(reinterpret_cast<const char*>(buf),
"%2d%2d%2d%1c%2d%2d");
}
#ifndef SUPPRESS_WARNINGS
if (rc) {
std::cerr << Error(30) << "\n";
}
#endif
return rc;
}
void TimeValue::read(const std::string& buf)
int TimeValue::read(const std::string& buf)
{
// byteOrder not needed
// Hard coded to read Iptc style times
if (buf.length() < 9) throw Error(30);
// Hard coded to read H:M:S or Iptc style times
int rc = 1;
if (buf.length() < 9) {
// Try to read (non-standard) H:M:S format
rc = scanTime3(buf.data(), "%d:%d:%d");
}
else {
rc = scanTime6(buf.data(), "%d:%d:%d%1c%d:%d");
}
#ifndef SUPPRESS_WARNINGS
if (rc) {
std::cerr << Error(30) << "\n";
}
#endif
return rc;
}
int TimeValue::scanTime3(const char* buf, const char* format)
{
int rc = 1;
Time t;
int scanned = sscanf(buf, format, &t.hour, &t.minute, &t.second);
if ( scanned == 3
&& t.hour >= 0 && t.hour < 24
&& t.minute >= 0 && t.minute < 60
&& t.second >= 0 && t.second < 60) {
time_ = t;
rc = 0;
}
return rc;
}
int TimeValue::scanTime6(const char* buf, const char* format)
{
int rc = 1;
Time t;
char plusMinus;
int scanned = sscanf(buf.data(),
"%d:%d:%d%1c%d:%d",
&time_.hour, &time_.minute, &time_.second,
&plusMinus, &time_.tzHour, &time_.tzMinute );
if (scanned != 6) throw Error(30);
if (plusMinus == '-') {
time_.tzHour *= -1;
time_.tzMinute *= -1;
int scanned = sscanf(buf, format, &t.hour, &t.minute, &t.second,
&plusMinus, &t.tzHour, &t.tzMinute);
if ( scanned == 6
&& t.hour >= 0 && t.hour < 24
&& t.minute >= 0 && t.minute < 60
&& t.second >= 0 && t.second < 60
&& t.tzHour >= 0 && t.tzHour < 24
&& t.tzMinute >= 0 && t.tzMinute < 60) {
time_ = t;
if (plusMinus == '-') {
time_.tzHour *= -1;
time_.tzMinute *= -1;
}
rc = 0;
}
return rc;
}
void TimeValue::setTime( const Time& src )
@ -506,9 +577,8 @@ namespace Exiv2 {
memcpy(&time_, &src, sizeof(time_));
}
long TimeValue::copy(byte* buf, ByteOrder byteOrder) const
long TimeValue::copy(byte* buf, ByteOrder /*byteOrder*/) const
{
// byteOrder not needed
// sprintf wants to add the null terminator, so use oversized buffer
char temp[12];
char plusMinus = '+';

@ -83,8 +83,10 @@ namespace Exiv2 {
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Applicable byte order (little or big endian).
@return 0 if successful.
*/
virtual void read(const byte* buf, long len, ByteOrder byteOrder) =0;
virtual int read(const byte* buf, long len, ByteOrder byteOrder) =0;
/*!
@brief Set the value from a string buffer. The format of the string
corresponds to that of the write() method, i.e., a string
@ -92,8 +94,10 @@ namespace Exiv2 {
function.
@param buf The string to read from.
@return 0 if successful.
*/
virtual void read(const std::string& buf) =0;
virtual int read(const std::string& buf) =0;
/*!
@brief Set the data area, if the value has one by copying (cloning)
the buffer pointed to by buf.
@ -270,12 +274,14 @@ namespace Exiv2 {
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful.
*/
virtual void read(const byte* buf,
virtual int read(const byte* buf,
long len,
ByteOrder byteOrder =invalidByteOrder);
//! Set the data from a string of integer values (e.g., "0 1 2 3")
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
//@}
//! @name Accessors
@ -344,7 +350,7 @@ namespace Exiv2 {
//! Assignment operator.
StringValueBase& operator=(const StringValueBase& rhs);
//! Read the value from buf. This default implementation uses buf as it is.
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
/*!
@brief Read the value from a character buffer.
@ -354,8 +360,10 @@ namespace Exiv2 {
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@return 0 if successful.
*/
virtual void read(const byte* buf,
virtual int read(const byte* buf,
long len,
ByteOrder byteOrder =invalidByteOrder);
//@}
@ -472,7 +480,7 @@ namespace Exiv2 {
to append a terminating '\\0' character if buf doesn't end
with '\\0'.
*/
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
//@}
//! @name Accessors
@ -568,9 +576,10 @@ namespace Exiv2 {
<BR>
The default charset is Undefined.
@throw Error if an invalid character set is encountered
@return 0 if successful<BR>
1 if an invalid character set is encountered
*/
void read(const std::string& comment);
int read(const std::string& comment);
//@}
//! @name Accessors
@ -636,9 +645,10 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@throw Error in case of an unsupported date format
@return 0 if successful<BR>
1 in case of an unsupported date format
*/
virtual void read(const byte* buf,
virtual int read(const byte* buf,
long len,
ByteOrder byteOrder =invalidByteOrder);
/*!
@ -646,9 +656,10 @@ namespace Exiv2 {
@param buf String containing the date
@throw Error in case of an unsupported date format
@return 0 if successful<BR>
1 in case of an unsupported date format
*/
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
//! Set the date
void setDate(const Date& src);
//@}
@ -721,6 +732,8 @@ namespace Exiv2 {
//! Simple Time helper structure
struct Time
{
Time() : hour(0), minute(0), second(0), tzHour(0), tzMinute(0) {}
int hour; //!< Hour
int minute; //!< Minute
int second; //!< Second
@ -742,19 +755,21 @@ namespace Exiv2 {
@param len Number of bytes in the data buffer
@param byteOrder Byte order. Not needed.
@throw Error in case of an unsupported time format
@return 0 if successful<BR>
1 in case of an unsupported time format
*/
virtual void read(const byte* buf,
long len,
ByteOrder byteOrder =invalidByteOrder);
virtual int read(const byte* buf,
long len,
ByteOrder byteOrder =invalidByteOrder);
/*!
@brief Set the value to that of the string buf.
@param buf String containing the time.
@throw Error in case of an unsupported time format
@return 0 if successful<BR>
1 in case of an unsupported time format
*/
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
//! Set the time
void setTime(const Time& src);
//@}
@ -780,9 +795,7 @@ namespace Exiv2 {
virtual const Time& getTime() const { return time_; }
virtual long count() const { return size(); }
virtual long size() const;
/*!
@brief Write the value to an output stream. .
*/
//! Write the value to an output stream. .
virtual std::ostream& write(std::ostream& os) const;
virtual long toLong(long n =0) const;
virtual float toFloat(long n =0) const
@ -792,8 +805,20 @@ namespace Exiv2 {
//@}
private:
//! @name Manipulators
//@{
//! Set time from \em buf if it conforms to \em format (3 input items)
int scanTime3(const char* buf, const char* format);
//! Set time from \em buf if it conforms to \em format (6 input items)
int scanTime6(const char* buf, const char* format);
//@}
//! @name Accessors
//@{
//! Internal virtual copy constructor.
virtual TimeValue* clone_() const;
//@}
// DATA
Time time_;
@ -845,14 +870,14 @@ namespace Exiv2 {
//@{
//! Assignment operator.
ValueType<T>& operator=(const ValueType<T>& rhs);
virtual void read(const byte* buf, long len, ByteOrder byteOrder);
virtual int read(const byte* buf, long len, ByteOrder byteOrder);
/*!
@brief Set the data from a string of values of type T (e.g.,
"0 1 2 3" or "1/2 1/3 1/4" depending on what T is).
Generally, the accepted input format is the same as that
produced by the write() method.
*/
virtual void read(const std::string& buf);
virtual int read(const std::string& buf);
/*!
@brief Set the data area. This method copies (clones) the buffer
pointed to by buf.
@ -1092,16 +1117,17 @@ namespace Exiv2 {
}
template<typename T>
void ValueType<T>::read(const byte* buf, long len, ByteOrder byteOrder)
int ValueType<T>::read(const byte* buf, long len, ByteOrder byteOrder)
{
value_.clear();
for (long i = 0; i < len; i += TypeInfo::typeSize(typeId())) {
value_.push_back(getValue<T>(buf + i, byteOrder));
}
return 0;
}
template<typename T>
void ValueType<T>::read(const std::string& buf)
int ValueType<T>::read(const std::string& buf)
{
std::istringstream is(buf);
T tmp;
@ -1109,6 +1135,7 @@ namespace Exiv2 {
while (is >> tmp) {
value_.push_back(tmp);
}
return 0;
}
template<typename T>

Loading…
Cancel
Save