1 // ***************************************************************** -*- C++ -*- 2 /* 3 * Copyright (C) 2004-2017 Andreas Huggel <ahuggel@gmx.net> 4 * 5 * This program is part of the Exiv2 distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. 20 */ 21 /* 22 File: datasets.cpp 23 Version: $Rev: 4719 $ 24 Author(s): Brad Schick (brad) <brad@robotbattle.com> 25 Gilles Caulier (gc) <caulier dot gilles at gmail dot com> 26 History: 24-Jul-04, brad: created 27 */ 28 // ***************************************************************************** 29 #include "rcsid_int.hpp" 30 EXIV2_RCSID("@(#) $Id: datasets.cpp 4719 2017-03-08 20:42:28Z robinwmills $") 31 32 // ***************************************************************************** 33 // included header files 34 #include "datasets.hpp" 35 #include "error.hpp" 36 #include "types.hpp" 37 #include "value.hpp" 38 #include "metadatum.hpp" 39 #include "i18n.h" // NLS support. 40 41 #include <iostream> 42 #include <iomanip> 43 #include <sstream> 44 45 // ***************************************************************************** 46 // class member definitions 47 namespace Exiv2 { 48 DataSet(uint16_t number,const char * name,const char * title,const char * desc,bool mandatory,bool repeatable,uint32_t minbytes,uint32_t maxbytes,TypeId type,uint16_t recordId,const char * photoshop)49 DataSet::DataSet( 50 uint16_t number, 51 const char* name, 52 const char* title, 53 const char* desc, 54 bool mandatory, 55 bool repeatable, 56 uint32_t minbytes, 57 uint32_t maxbytes, 58 TypeId type, 59 uint16_t recordId, 60 const char* photoshop 61 ) 62 : number_(number), name_(name), title_(title), desc_(desc), 63 mandatory_(mandatory), repeatable_(repeatable), minbytes_(minbytes), 64 maxbytes_(maxbytes), type_(type), recordId_(recordId), 65 photoshop_(photoshop) 66 { 67 } 68 RecordInfo(uint16_t recordId,const char * name,const char * desc)69 RecordInfo::RecordInfo( 70 uint16_t recordId, 71 const char* name, 72 const char* desc 73 ) 74 : recordId_(recordId), name_(name), desc_(desc) 75 { 76 } 77 78 const RecordInfo IptcDataSets::recordInfo_[] = { 79 RecordInfo(IptcDataSets::invalidRecord, "(invalid)", N_("(invalid)")), 80 RecordInfo(IptcDataSets::envelope, "Envelope", N_("IIM envelope record")), 81 RecordInfo(IptcDataSets::application2, "Application2", N_("IIM application record 2")), 82 }; 83 84 static const DataSet envelopeRecord[] = { 85 DataSet(IptcDataSets::ModelVersion, "ModelVersion", N_("Model Version"), 86 N_("A binary number identifying the version of the Information " 87 "Interchange Model, Part I, utilised by the provider. Version " 88 "numbers are assigned by IPTC and NAA organizations."), 89 true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), 90 DataSet(IptcDataSets::Destination, "Destination", N_("Destination"), 91 N_("This DataSet is to accommodate some providers who require " 92 "routing information above the appropriate OSI layers."), 93 false, true, 0, 1024, Exiv2::string, IptcDataSets::envelope, ""), 94 DataSet(IptcDataSets::FileFormat, "FileFormat", N_("File Format"), 95 N_("A binary number representing the file format. The file format " 96 "must be registered with IPTC or NAA with a unique number " 97 "assigned to it. The information is used to route " 98 "the data to the appropriate system and to allow the receiving " 99 "system to perform the appropriate actions there to."), 100 true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), 101 DataSet(IptcDataSets::FileVersion, "FileVersion", N_("File Version"), 102 N_("A binary number representing the particular version of the File " 103 "Format specified by <FileFormat> tag."), 104 true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), 105 DataSet(IptcDataSets::ServiceId, "ServiceId", N_("Service Id"), 106 N_("Identifies the provider and product"), 107 true, false, 0, 10, Exiv2::string, IptcDataSets::envelope, ""), 108 DataSet(IptcDataSets::EnvelopeNumber, "EnvelopeNumber", N_("Envelope Number"), 109 N_("The characters form a number that will be unique for the date " 110 "specified in <DateSent> tag and for the Service Identifier " 111 "specified by <ServiceIdentifier> tag. " 112 "If identical envelope numbers appear with the same date and " 113 "with the same Service Identifier, records 2-9 must be unchanged " 114 "from the original. This is not intended to be a sequential serial " 115 "number reception check."), 116 true, false, 8, 8, Exiv2::string, IptcDataSets::envelope, ""), 117 DataSet(IptcDataSets::ProductId, "ProductId", N_("Product Id"), 118 N_("Allows a provider to identify subsets of its overall service. Used " 119 "to provide receiving organisation data on which to select, route, " 120 "or otherwise handle data."), 121 false, true, 0, 32, Exiv2::string, IptcDataSets::envelope, ""), 122 DataSet(IptcDataSets::EnvelopePriority, "EnvelopePriority", N_("Envelope Priority"), 123 N_("Specifies the envelope handling priority and not the editorial " 124 "urgency (see <Urgency> tag). \"1\" indicates the most urgent, \"5\" " 125 "the normal urgency, and \"8\" the least urgent copy. The numeral " 126 "\"9\" indicates a User Defined Priority. The numeral \"0\" is reserved " 127 "for future use."), 128 false, false, 1, 1, Exiv2::string, IptcDataSets::envelope, ""), 129 DataSet(IptcDataSets::DateSent, "DateSent", N_("Date Sent"), 130 N_("Uses the format CCYYMMDD (century, year, month, day) as de-fined " 131 "in ISO 8601 to indicate year, month and day the service sent the material."), 132 true, false, 8, 8, Exiv2::date, IptcDataSets::envelope, ""), 133 DataSet(IptcDataSets::TimeSent, "TimeSent", N_("Time Sent"), 134 N_("Uses the format HHMMSS:HHMM where HHMMSS refers to " 135 "local hour, minute and seconds and HHMM refers to hours and " 136 "minutes ahead (+) or behind (-) Universal Coordinated Time as " 137 "described in ISO 8601. This is the time the service sent the material."), 138 false, false, 11, 11, Exiv2::time, IptcDataSets::envelope, ""), 139 DataSet(IptcDataSets::CharacterSet, "CharacterSet", N_("Character Set"), 140 N_("This tag consisting of one or more control functions used for the announcement, " 141 "invocation or designation of coded character sets. The control functions follow " 142 "the ISO 2022 standard and may consist of the escape control " 143 "character and one or more graphic characters."), 144 false, false, 0, 32, Exiv2::string, IptcDataSets::envelope, ""), 145 DataSet(IptcDataSets::UNO, "UNO", N_("Unique Name Object"), 146 N_("This tag provide a globally unique " 147 "identification for objects as specified in the IIM, independent of " 148 "provider and for any media form. The provider must ensure the " 149 "UNO is unique. Objects with the same UNO are identical."), 150 false, false, 14, 80, Exiv2::string, IptcDataSets::envelope, ""), 151 DataSet(IptcDataSets::ARMId, "ARMId", N_("ARM Identifier"), 152 N_("The DataSet identifies the Abstract Relationship Method identifier (ARM) " 153 "which is described in a document registered by the originator of " 154 "the ARM with the IPTC and NAA organizations."), 155 false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), 156 DataSet(IptcDataSets::ARMVersion, "ARMVersion", N_("ARM Version"), 157 N_("This tag consisting of a binary number representing the particular " 158 "version of the ARM specified by tag <ARMId>."), 159 false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), 160 DataSet(0xffff, "(Invalid)", "(Invalid)", 161 "(Invalid)", false, false, 0, 0, Exiv2::unsignedShort, IptcDataSets::envelope, "") 162 }; 163 envelopeRecordList()164 const DataSet* IptcDataSets::envelopeRecordList() 165 { 166 return envelopeRecord; 167 } 168 169 static const DataSet application2Record[] = { 170 DataSet(IptcDataSets::RecordVersion, "RecordVersion", N_("Record Version"), 171 N_("A binary number identifying the version of the Information " 172 "Interchange Model, Part II, utilised by the provider. " 173 "Version numbers are assigned by IPTC and NAA organizations."), 174 true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), 175 DataSet(IptcDataSets::ObjectType, "ObjectType", N_("Object Type"), 176 N_("The Object Type is used to distinguish between different types " 177 "of objects within the IIM. The first part is a number representing " 178 "a language independent international reference to an Object Type " 179 "followed by a colon separator. The second part, if used, is a text " 180 "representation of the Object Type Number consisting of graphic " 181 "characters plus spaces either in English or in the language of the " 182 "service as indicated in tag <LanguageIdentifier>"), 183 false, false, 3, 67, Exiv2::string, IptcDataSets::application2, ""), 184 DataSet(IptcDataSets::ObjectAttribute, "ObjectAttribute", N_("Object Attribute"), 185 N_("The Object Attribute defines the nature of the object " 186 "independent of the Subject. The first part is a number representing " 187 "a language independent international reference to an Object Attribute " 188 "followed by a colon separator. The second part, if used, is a text " 189 "representation of the Object Attribute Number consisting of graphic " 190 "characters plus spaces either in English, or in the language of the " 191 "service as indicated in tag <LanguageIdentifier>"), 192 false, true, 4, 68, Exiv2::string, IptcDataSets::application2, ""), 193 DataSet(IptcDataSets::ObjectName, "ObjectName", N_("Object Name"), 194 N_("Used as a shorthand reference for the object. Changes to exist-ing " 195 "data, such as updated stories or new crops on photos, should be " 196 "identified in tag <EditStatus>."), 197 false, false, 0, 64, Exiv2::string, IptcDataSets::application2, 198 N_("Document Title")), 199 DataSet(IptcDataSets::EditStatus, "EditStatus", N_("Edit Status"), 200 N_("Status of the object data, according to the practice of the provider."), 201 false, false, 0, 64, Exiv2::string, IptcDataSets::application2, ""), 202 DataSet(IptcDataSets::EditorialUpdate, "EditorialUpdate", N_("Editorial Update"), 203 N_("Indicates the type of update that this object provides to a " 204 "previous object. The link to the previous object is made using " 205 "the tags <ARMIdentifier> and <ARMVersion>, according to the practices of the provider."), 206 false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), 207 DataSet(IptcDataSets::Urgency, "Urgency", N_("Urgency"), 208 N_("Specifies the editorial urgency of content and not necessarily the " 209 "envelope handling priority (see tag <EnvelopePriority>). The \"1\" " 210 "is most urgent, \"5\" normal and \"8\" denotes the least-urgent copy."), 211 false, false, 1, 1, Exiv2::string, IptcDataSets::application2, 212 N_("Urgency")), 213 DataSet(IptcDataSets::Subject, "Subject", N_("Subject"), 214 N_("The Subject Reference is a structured definition of the subject matter."), 215 false, true, 13, 236, Exiv2::string, IptcDataSets::application2, ""), 216 DataSet(IptcDataSets::Category, "Category", N_("Category"), 217 N_("Identifies the subject of the object data in the opinion of the provider. " 218 "A list of categories will be maintained by a regional registry, " 219 "where available, otherwise by the provider."), 220 false, false, 0, 3, Exiv2::string, IptcDataSets::application2, 221 N_("Category")), 222 DataSet(IptcDataSets::SuppCategory, "SuppCategory", N_("Supplemental Category"), 223 N_("Supplemental categories further refine the subject of an " 224 "object data. A supplemental category may include " 225 "any of the recognised categories as used in tag <Category>. Otherwise, " 226 "selection of supplemental categories are left to the provider."), 227 false, true, 0, 32, Exiv2::string, IptcDataSets::application2, 228 N_("Supplemental Categories")), 229 DataSet(IptcDataSets::FixtureId, "FixtureId", N_("Fixture Id"), 230 N_("Identifies object data that recurs often and predictably. Enables " 231 "users to immediately find or recall such an object."), 232 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), 233 DataSet(IptcDataSets::Keywords, "Keywords", N_("Keywords"), 234 N_("Used to indicate specific information retrieval words. " 235 "It is expected that a provider of various types of data that are related " 236 "in subject matter uses the same keyword, enabling the receiving system " 237 "or subsystems to search across all types of data for related material."), 238 false, true, 0, 64, Exiv2::string, IptcDataSets::application2, 239 N_("Keywords")), 240 DataSet(IptcDataSets::LocationCode, "LocationCode", N_("Location Code"), 241 N_("Indicates the code of a country/geographical location referenced " 242 "by the content of the object. Where ISO has established an appropriate " 243 "country code under ISO 3166, that code will be used. When ISO 3166 does not " 244 "adequately provide for identification of a location or a country, " 245 "e.g. ships at sea, space, IPTC will assign an appropriate three-character " 246 "code under the provisions of ISO 3166 to avoid conflicts."), 247 false, true, 3, 3, Exiv2::string, IptcDataSets::application2, ""), 248 DataSet(IptcDataSets::LocationName, "LocationName", N_("Location Name"), 249 N_("Provides a full, publishable name of a country/geographical " 250 "location referenced by the content of the object, according to " 251 "guidelines of the provider."), 252 false, true, 0, 64, Exiv2::string, IptcDataSets::application2, ""), 253 DataSet(IptcDataSets::ReleaseDate, "ReleaseDate", N_("Release Date"), 254 N_("Designates in the form CCYYMMDD the earliest date the " 255 "provider intends the object to be used. Follows ISO 8601 standard."), 256 false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), 257 DataSet(IptcDataSets::ReleaseTime, "ReleaseTime", N_("Release Time"), 258 N_("Designates in the form HHMMSS:HHMM the earliest time the " 259 "provider intends the object to be used. Follows ISO 8601 standard."), 260 false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), 261 DataSet(IptcDataSets::ExpirationDate, "ExpirationDate", N_("Expiration Date"), 262 N_("Designates in the form CCYYMMDD the latest date the provider " 263 "or owner intends the object data to be used. Follows ISO 8601 standard."), 264 false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), 265 DataSet(IptcDataSets::ExpirationTime, "ExpirationTime", N_("ExpirationTime"), 266 N_("Designates in the form HHMMSS:HHMM the latest time the " 267 "provider or owner intends the object data to be used. Follows ISO 8601 standard."), 268 false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), 269 DataSet(IptcDataSets::SpecialInstructions, "SpecialInstructions", N_("Special Instructions"), 270 N_("Other editorial instructions concerning the use of the object data, " 271 "such as embargoes and warnings."), 272 false, false, 0, 256, Exiv2::string, IptcDataSets::application2, 273 N_("Instructions")), 274 DataSet(IptcDataSets::ActionAdvised, "ActionAdvised", N_("Action Advised"), 275 N_("Indicates the type of action that this object provides to a " 276 "previous object. The link to the previous object is made using " 277 "tags <ARMIdentifier> and <ARMVersion>, according to the practices of the provider."), 278 false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), 279 DataSet(IptcDataSets::ReferenceService, "ReferenceService", N_("Reference Service"), 280 N_("Identifies the Service Identifier of a prior envelope to which the " 281 "current object refers."), 282 false, true, 0, 10, Exiv2::string, IptcDataSets::application2, ""), 283 DataSet(IptcDataSets::ReferenceDate, "ReferenceDate", N_("Reference Date"), 284 N_("Identifies the date of a prior envelope to which the current object refers."), 285 false, true, 8, 8, Exiv2::date, IptcDataSets::application2, ""), 286 DataSet(IptcDataSets::ReferenceNumber, "ReferenceNumber", N_("Reference Number"), 287 N_("Identifies the Envelope Number of a prior envelope to which the current object refers."), 288 false, true, 8, 8, Exiv2::string, IptcDataSets::application2, ""), 289 DataSet(IptcDataSets::DateCreated, "DateCreated", N_("Date Created"), 290 N_("Represented in the form CCYYMMDD to designate the date the " 291 "intellectual content of the object data was created rather than the " 292 "date of the creation of the physical representation. Follows ISO 8601 standard."), 293 false, false, 8, 8, Exiv2::date, IptcDataSets::application2, 294 N_("Date Created")), 295 DataSet(IptcDataSets::TimeCreated, "TimeCreated", N_("Time Created"), 296 N_("Represented in the form HHMMSS:HHMM to designate the " 297 "time the intellectual content of the object data current source " 298 "material was created rather than the creation of the physical " 299 "representation. Follows ISO 8601 standard."), 300 false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), 301 DataSet(IptcDataSets::DigitizationDate, "DigitizationDate", N_("Digitization Date"), 302 N_("Represented in the form CCYYMMDD to designate the date the " 303 "digital representation of the object data was created. Follows ISO 8601 standard."), 304 false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), 305 DataSet(IptcDataSets::DigitizationTime, "DigitizationTime", N_("Digitization Time"), 306 N_("Represented in the form HHMMSS:HHMM to designate the " 307 "time the digital representation of the object data was created. " 308 "Follows ISO 8601 standard."), 309 false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), 310 DataSet(IptcDataSets::Program, "Program", N_("Program"), 311 N_("Identifies the type of program used to originate the object data."), 312 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), 313 DataSet(IptcDataSets::ProgramVersion, "ProgramVersion", N_("Program Version"), 314 N_("Used to identify the version of the program mentioned in tag <Program>."), 315 false, false, 0, 10, Exiv2::string, IptcDataSets::application2, ""), 316 DataSet(IptcDataSets::ObjectCycle, "ObjectCycle", N_("Object Cycle"), 317 N_("Used to identify the editorial cycle of object data."), 318 false, false, 1, 1, Exiv2::string, IptcDataSets::application2, ""), 319 DataSet(IptcDataSets::Byline, "Byline", N_("By-line"), 320 N_("Contains name of the creator of the object data, e.g. writer, photographer " 321 "or graphic artist."), 322 false, true, 0, 32, Exiv2::string, IptcDataSets::application2, 323 N_("Author")), 324 DataSet(IptcDataSets::BylineTitle, "BylineTitle", N_("By-line Title"), 325 N_("A by-line title is the title of the creator or creators of an " 326 "object data. Where used, a by-line title should follow the by-line it modifies."), 327 false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Authors Position"), 328 DataSet(IptcDataSets::City, "City", N_("City"), 329 N_("Identifies city of object data origin according to guidelines established " 330 "by the provider."), 331 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, 332 N_("City")), 333 DataSet(IptcDataSets::SubLocation, "SubLocation", N_("Sub Location"), 334 N_("Identifies the location within a city from which the object data " 335 "originates, according to guidelines established by the provider."), 336 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), 337 DataSet(IptcDataSets::ProvinceState, "ProvinceState", N_("Province State"), 338 N_("Identifies Province/State of origin according to guidelines " 339 "established by the provider."), 340 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, 341 N_("State/Province")), 342 DataSet(IptcDataSets::CountryCode, "CountryCode", N_("Country Code"), 343 N_("Indicates the code of the country/primary location where the " 344 "intellectual property of the object data was created, e.g. a photo " 345 "was taken, an event occurred. Where ISO has established an appropriate " 346 "country code under ISO 3166, that code will be used. When ISO 3166 does not " 347 "adequately provide for identification of a location or a new " 348 "country, e.g. ships at sea, space, IPTC will assign an " 349 "appropriate three-character code under the provisions of " 350 "ISO 3166 to avoid conflicts."), 351 false, false, 3, 3, Exiv2::string, IptcDataSets::application2, ""), 352 DataSet(IptcDataSets::CountryName, "CountryName", N_("Country Name"), 353 N_("Provides full, publishable, name of the country/primary location " 354 "where the intellectual property of the object data was created, " 355 "according to guidelines of the provider."), 356 false, false, 0, 64, Exiv2::string, IptcDataSets::application2, 357 N_("Country")), 358 DataSet(IptcDataSets::TransmissionReference, "TransmissionReference", N_("Transmission Reference"), 359 N_("A code representing the location of original transmission according " 360 "to practices of the provider."), 361 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, 362 N_("Transmission Reference")), 363 DataSet(IptcDataSets::Headline, "Headline", N_("Headline"), 364 N_("A publishable entry providing a synopsis of the contents of the object data."), 365 false, false, 0, 256, Exiv2::string, IptcDataSets::application2, 366 N_("Headline")), 367 DataSet(IptcDataSets::Credit, "Credit", N_("Credit"), 368 N_("Identifies the provider of the object data, not necessarily the owner/creator."), 369 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, 370 N_("Credit")), 371 DataSet(IptcDataSets::Source, "Source", N_("Source"), 372 N_("Identifies the original owner of the intellectual content of the " 373 "object data. This could be an agency, a member of an agency or an individual."), 374 false, false, 0, 32, Exiv2::string, IptcDataSets::application2, 375 N_("Source")), 376 DataSet(IptcDataSets::Copyright, "Copyright", N_("Copyright"), 377 N_("Contains any necessary copyright notice."), 378 false, false, 0, 128, Exiv2::string, IptcDataSets::application2, 379 N_("Copyright Notice")), 380 DataSet(IptcDataSets::Contact, "Contact", N_("Contact"), 381 N_("Identifies the person or organisation which can provide further " 382 "background information on the object data."), 383 false, true, 0, 128, Exiv2::string, IptcDataSets::application2, ""), 384 DataSet(IptcDataSets::Caption, "Caption", N_("Caption"), 385 N_("A textual description of the object data."), 386 false, false, 0, 2000, Exiv2::string, IptcDataSets::application2, 387 N_("Description")), 388 DataSet(IptcDataSets::Writer, "Writer", N_("Writer"), 389 N_("Identification of the name of the person involved in the writing, " 390 "editing or correcting the object data or caption/abstract."), 391 false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Description writer"), 392 DataSet(IptcDataSets::RasterizedCaption, "RasterizedCaption", N_("Rasterized Caption"), 393 N_("Contains the rasterized object data description and is used " 394 "where characters that have not been coded are required for the caption."), 395 false, false, 7360, 7360, Exiv2::undefined, IptcDataSets::application2, ""), 396 DataSet(IptcDataSets::ImageType, "ImageType", N_("Image Type"), 397 N_("Indicates the color components of an image."), 398 false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), 399 DataSet(IptcDataSets::ImageOrientation, "ImageOrientation", N_("Image Orientation"), 400 N_("Indicates the layout of an image."), 401 false, false, 1, 1, Exiv2::string, IptcDataSets::application2, ""), 402 DataSet(IptcDataSets::Language, "Language", N_("Language"), 403 N_("Describes the major national language of the object, according " 404 "to the 2-letter codes of ISO 639:1988. Does not define or imply " 405 "any coded character set, but is used for internal routing, e.g. to " 406 "various editorial desks."), 407 false, false, 2, 3, Exiv2::string, IptcDataSets::application2, ""), 408 DataSet(IptcDataSets::AudioType, "AudioType", N_("Audio Type"), 409 N_("Indicates the type of an audio content."), 410 false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), 411 DataSet(IptcDataSets::AudioRate, "AudioRate", N_("Audio Rate"), 412 N_("Indicates the sampling rate in Hertz of an audio content."), 413 false, false, 6, 6, Exiv2::string, IptcDataSets::application2, ""), 414 DataSet(IptcDataSets::AudioResolution, "AudioResolution", N_("Audio Resolution"), 415 N_("Indicates the sampling resolution of an audio content."), 416 false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), 417 DataSet(IptcDataSets::AudioDuration, "AudioDuration", N_("Audio Duration"), 418 N_("Indicates the duration of an audio content."), 419 false, false, 6, 6, Exiv2::string, IptcDataSets::application2, ""), 420 DataSet(IptcDataSets::AudioOutcue, "AudioOutcue", N_("Audio Outcue"), 421 N_("Identifies the content of the end of an audio object data, " 422 "according to guidelines established by the provider."), 423 false, false, 0, 64, Exiv2::string, IptcDataSets::application2, ""), 424 DataSet(IptcDataSets::PreviewFormat, "PreviewFormat", N_("Preview Format"), 425 N_("A binary number representing the file format of the object data " 426 "preview. The file format must be registered with IPTC or NAA organizations " 427 "with a unique number assigned to it."), 428 false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), 429 DataSet(IptcDataSets::PreviewVersion, "PreviewVersion", N_("Preview Version"), 430 N_("A binary number representing the particular version of the " 431 "object data preview file format specified in tag <PreviewFormat>."), 432 false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), 433 DataSet(IptcDataSets::Preview, "Preview", N_("Preview Data"), 434 N_("Binary image preview data."), 435 false, false, 0, 256000, Exiv2::undefined, IptcDataSets::application2, ""), 436 DataSet(0xffff, "(Invalid)", N_("(Invalid)"), 437 N_("(Invalid)"), 438 false, false, 0, 0, Exiv2::unsignedShort, IptcDataSets::application2, "") 439 }; 440 application2RecordList()441 const DataSet* IptcDataSets::application2RecordList() 442 { 443 return application2Record; 444 } 445 446 static const DataSet unknownDataSet(0xffff, "Unknown dataset", N_("Unknown dataset"), 447 N_("Unknown dataset"), 448 false, true, 0, 0xffffffff, Exiv2::string, 449 IptcDataSets::invalidRecord, 450 N_("Unknown dataset")); 451 452 // Dataset lookup lists.This is an array with pointers to one list per IIM4 Record. 453 // The record id is used as the index into the array. 454 const DataSet* IptcDataSets::records_[] = { 455 0, 456 envelopeRecord, application2Record, 457 0 458 }; 459 dataSetIdx(uint16_t number,uint16_t recordId)460 int IptcDataSets::dataSetIdx(uint16_t number, uint16_t recordId) 461 { 462 if( recordId != envelope && recordId != application2 ) return -1; 463 const DataSet* dataSet = records_[recordId]; 464 if (dataSet == 0) return -1; 465 int idx; 466 for (idx = 0; dataSet[idx].number_ != number; ++idx) { 467 if (dataSet[idx].number_ == 0xffff) return -1; 468 } 469 return idx; 470 } 471 dataSetIdx(const std::string & dataSetName,uint16_t recordId)472 int IptcDataSets::dataSetIdx(const std::string& dataSetName, uint16_t recordId) 473 { 474 if( recordId != envelope && recordId != application2 ) return -1; 475 const DataSet* dataSet = records_[recordId]; 476 if (dataSet == 0) return -1; 477 int idx; 478 for (idx = 0; dataSet[idx].name_ != dataSetName; ++idx) { 479 if (dataSet[idx].number_ == 0xffff) return -1; 480 } 481 return idx; 482 } 483 dataSetType(uint16_t number,uint16_t recordId)484 TypeId IptcDataSets::dataSetType(uint16_t number, uint16_t recordId) 485 { 486 int idx = dataSetIdx(number, recordId); 487 if (idx == -1) return unknownDataSet.type_; 488 return records_[recordId][idx].type_; 489 } 490 dataSetName(uint16_t number,uint16_t recordId)491 std::string IptcDataSets::dataSetName(uint16_t number, uint16_t recordId) 492 { 493 int idx = dataSetIdx(number, recordId); 494 if (idx != -1) return records_[recordId][idx].name_; 495 496 std::ostringstream os; 497 os << "0x" << std::setw(4) << std::setfill('0') << std::right 498 << std::hex << number; 499 return os.str(); 500 } 501 dataSetTitle(uint16_t number,uint16_t recordId)502 const char* IptcDataSets::dataSetTitle(uint16_t number, uint16_t recordId) 503 { 504 int idx = dataSetIdx(number, recordId); 505 if (idx == -1) return unknownDataSet.title_; 506 return records_[recordId][idx].title_; 507 } 508 dataSetDesc(uint16_t number,uint16_t recordId)509 const char* IptcDataSets::dataSetDesc(uint16_t number, uint16_t recordId) 510 { 511 int idx = dataSetIdx(number, recordId); 512 if (idx == -1) return unknownDataSet.desc_; 513 return records_[recordId][idx].desc_; 514 } 515 dataSetPsName(uint16_t number,uint16_t recordId)516 const char* IptcDataSets::dataSetPsName(uint16_t number, uint16_t recordId) 517 { 518 int idx = dataSetIdx(number, recordId); 519 if (idx == -1) return unknownDataSet.photoshop_; 520 return records_[recordId][idx].photoshop_; 521 } 522 dataSetRepeatable(uint16_t number,uint16_t recordId)523 bool IptcDataSets::dataSetRepeatable(uint16_t number, uint16_t recordId) 524 { 525 int idx = dataSetIdx(number, recordId); 526 if (idx == -1) return unknownDataSet.repeatable_; 527 return records_[recordId][idx].repeatable_; 528 } 529 dataSet(const std::string & dataSetName,uint16_t recordId)530 uint16_t IptcDataSets::dataSet(const std::string& dataSetName, 531 uint16_t recordId) 532 { 533 uint16_t dataSet; 534 int idx = dataSetIdx(dataSetName, recordId); 535 if (idx != -1) { 536 // dataSetIdx checks the range of recordId 537 dataSet = records_[recordId][idx].number_; 538 } 539 else { 540 if (!isHex(dataSetName, 4, "0x")) throw Error(4, dataSetName); 541 std::istringstream is(dataSetName); 542 is >> std::hex >> dataSet; 543 } 544 return dataSet; 545 } 546 recordName(uint16_t recordId)547 std::string IptcDataSets::recordName(uint16_t recordId) 548 { 549 if (recordId == envelope || recordId == application2) { 550 return recordInfo_[recordId].name_; 551 } 552 553 std::ostringstream os; 554 os << "0x" << std::setw(4) << std::setfill('0') << std::right 555 << std::hex << recordId; 556 return os.str(); 557 } 558 recordDesc(uint16_t recordId)559 const char* IptcDataSets::recordDesc(uint16_t recordId) 560 { 561 if (recordId != envelope && recordId != application2) { 562 return unknownDataSet.desc_; 563 } 564 return recordInfo_[recordId].desc_; 565 } 566 recordId(const std::string & recordName)567 uint16_t IptcDataSets::recordId(const std::string& recordName) 568 { 569 uint16_t i; 570 for (i = application2; i > 0; --i) { 571 if (recordInfo_[i].name_ == recordName) break; 572 } 573 if (i == 0) { 574 if (!isHex(recordName, 4, "0x")) throw Error(5, recordName); 575 std::istringstream is(recordName); 576 is >> std::hex >> i; 577 } 578 return i; 579 } 580 dataSetList(std::ostream & os)581 void IptcDataSets::dataSetList(std::ostream& os) 582 { 583 const int count = sizeof(records_)/sizeof(records_[0]); 584 for (int i=0; i < count; ++i) { 585 const DataSet *record = records_[i]; 586 for (int j=0; record != 0 && record[j].number_ != 0xffff; ++j) { 587 os << record[j] << "\n"; 588 } 589 } 590 } // IptcDataSets::dataSetList 591 592 const char* IptcKey::familyName_ = "Iptc"; 593 IptcKey(const std::string & key)594 IptcKey::IptcKey(const std::string& key) 595 : key_(key) 596 { 597 decomposeKey(); 598 } 599 IptcKey(uint16_t tag,uint16_t record)600 IptcKey::IptcKey(uint16_t tag, uint16_t record) 601 : tag_(tag), record_(record) 602 { 603 makeKey(); 604 } 605 IptcKey(const IptcKey & rhs)606 IptcKey::IptcKey(const IptcKey& rhs) 607 : Key(rhs), tag_(rhs.tag_), record_(rhs.record_), key_(rhs.key_) 608 { 609 } 610 ~IptcKey()611 IptcKey::~IptcKey() 612 { 613 } 614 operator =(const IptcKey & rhs)615 IptcKey& IptcKey::operator=(const IptcKey& rhs) 616 { 617 if (this == &rhs) return *this; 618 Key::operator=(rhs); 619 tag_ = rhs.tag_; 620 record_ = rhs.record_; 621 key_ = rhs.key_; 622 return *this; 623 } 624 key() const625 std::string IptcKey::key() const 626 { 627 return key_; 628 } 629 familyName() const630 const char* IptcKey::familyName() const 631 { 632 return familyName_; 633 } 634 groupName() const635 std::string IptcKey::groupName() const 636 { 637 return recordName(); 638 } 639 tagName() const640 std::string IptcKey::tagName() const 641 { 642 return IptcDataSets::dataSetName(tag_, record_); 643 } 644 tagLabel() const645 std::string IptcKey::tagLabel() const 646 { 647 return IptcDataSets::dataSetTitle(tag_, record_); 648 } 649 tag() const650 uint16_t IptcKey::tag() const 651 { 652 return tag_; 653 } 654 recordName() const655 std::string IptcKey::recordName() const 656 { 657 return IptcDataSets::recordName(record_); 658 } 659 record() const660 uint16_t IptcKey::record() const 661 { 662 return record_; 663 } 664 clone() const665 IptcKey::AutoPtr IptcKey::clone() const 666 { 667 return AutoPtr(clone_()); 668 } 669 clone_() const670 IptcKey* IptcKey::clone_() const 671 { 672 return new IptcKey(*this); 673 } 674 decomposeKey()675 void IptcKey::decomposeKey() 676 { 677 // Get the family name, record name and dataSet name parts of the key 678 std::string::size_type pos1 = key_.find('.'); 679 if (pos1 == std::string::npos) throw Error(6, key_); 680 std::string familyName = key_.substr(0, pos1); 681 if (0 != strcmp(familyName.c_str(), familyName_)) { 682 throw Error(6, key_); 683 } 684 std::string::size_type pos0 = pos1 + 1; 685 pos1 = key_.find('.', pos0); 686 if (pos1 == std::string::npos) throw Error(6, key_); 687 std::string recordName = key_.substr(pos0, pos1 - pos0); 688 if (recordName == "") throw Error(6, key_); 689 std::string dataSetName = key_.substr(pos1 + 1); 690 if (dataSetName == "") throw Error(6, key_); 691 692 // Use the parts of the key to find dataSet and recordId 693 uint16_t recId = IptcDataSets::recordId(recordName); 694 uint16_t dataSet = IptcDataSets::dataSet(dataSetName, recId); 695 696 // Possibly translate hex name parts (0xabcd) to real names 697 recordName = IptcDataSets::recordName(recId); 698 dataSetName = IptcDataSets::dataSetName(dataSet, recId); 699 700 tag_ = dataSet; 701 record_ = recId; 702 key_ = familyName + "." + recordName + "." + dataSetName; 703 } // IptcKey::decomposeKey 704 makeKey()705 void IptcKey::makeKey() 706 { 707 key_ = std::string(familyName_) 708 + "." + IptcDataSets::recordName(record_) 709 + "." + IptcDataSets::dataSetName(tag_, record_); 710 } 711 712 // ************************************************************************* 713 // free functions 714 operator <<(std::ostream & os,const DataSet & dataSet)715 std::ostream& operator<<(std::ostream& os, const DataSet& dataSet) 716 { 717 std::ios::fmtflags f( os.flags() ); 718 IptcKey iptcKey(dataSet.number_, dataSet.recordId_); 719 os << dataSet.name_ << ", " 720 << std::dec << dataSet.number_ << ", " 721 << "0x" << std::setw(4) << std::setfill('0') 722 << std::right << std::hex << dataSet.number_ << ", " 723 << IptcDataSets::recordName(dataSet.recordId_) << ", " 724 << std::boolalpha << dataSet.mandatory_ << ", " 725 << dataSet.repeatable_ << ", " 726 << std::dec << dataSet.minbytes_ << ", " 727 << dataSet.maxbytes_ << ", " 728 << iptcKey.key() << ", " 729 << TypeInfo::typeName( 730 IptcDataSets::dataSetType(dataSet.number_, 731 dataSet.recordId_)) << ", " 732 << dataSet.desc_; 733 os.flags(f); 734 return os; 735 } 736 737 } // namespace Exiv2 738