1 #ifndef __TXMPUtils_hpp__ 2 #define __TXMPUtils_hpp__ 1 3 4 #if ( ! __XMP_hpp__ ) 5 #error "Do not directly include, use XMP.hpp" 6 #endif 7 8 // ================================================================================================= 9 // ADOBE SYSTEMS INCORPORATED 10 // Copyright 2002-2008 Adobe Systems Incorporated 11 // All Rights Reserved 12 // 13 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 14 // of the Adobe license agreement accompanying it. 15 // ================================================================================================= 16 17 // ================================================================================================= 18 /// \file TXMPUtils.hpp 19 /// \brief API for access to the XMP Toolkit utility services. 20 /// 21 /// \c TXMPUtils is the template class providing utility services for the XMP Toolkit. It must be 22 /// instantiated with a string class such as \c std::string. See the instructions in XMP.hpp, and 23 /// the Overview for a discussion of the overall architecture of the XMP API. 24 // ================================================================================================= 25 26 // ================================================================================================= 27 /// \class TXMPUtils TXMPUtils.hpp 28 /// @brief API for access to the XMP Toolkit utility services. 29 /// 30 /// \c TXMPUtils is a template class which must be instantiated with a string class such as 31 /// \c std::string. See the instructions in XMP.hpp, and the Overview for a discussion of the overall 32 /// architecture of the XMP API. 33 /// 34 /// This class defines helper functions that support the basic metadata manipulation provided by 35 /// \c TXMPMeta. All of the functions are static; that is, you call them directly from the concrete 36 /// class (\c SXMPUtils), which is never itself instantiated. 37 /// 38 /// General categories of utilities include: 39 /// 40 /// \li Composing complex path expressions, which you can then pass to the property access 41 /// functions in \c TXMPMeta 42 /// \li Converting between binary and string forms of property values 43 /// \li Manipulating date/time values 44 /// \li Encoding and decoding base-64 strings 45 /// \li JPEG file handling 46 /// \li Editing aids for creating a user interface for the XMP Toolkit 47 // ================================================================================================= 48 49 template <class tStringObj> class TXMPUtils { 50 51 public: 52 53 // ============================================================================================= 54 // No constructors or destructor declared or needed 55 // ================================================ 56 57 // ============================================================================================ 58 /// \name Path composition 59 /// @{ 60 /// 61 /// These functions provide support for composing path expressions to deeply nested properties. 62 /// The functions in \c TXMPMeta such as \c TXMPMeta::GetProperty(), 63 /// \c TXMPMeta::GetArrayItem(), and \c TXMPMeta::GetStructField() provide easy access to top level 64 /// simple properties, items in top level arrays, and fields of top level structs. They are 65 /// not as convenient for more complex things, such as fields several levels deep in a complex 66 /// struct, or fields within an array of structs, or items of an array that is a field of a 67 /// struct. You can use these utility functions to compose these paths, which you can then pass 68 /// to the property access functions. You can also compose paths to top-level array items or 69 /// struct fields so that you can use the binary accessors such as 70 /// \c TXMPMeta::GetProperty_Int(). 71 /// 72 /// You can use these functions is to compose a complete path expression, or all but the last 73 /// component. For example, suppose you have a property that is an array of integers within a 74 /// struct. You can access one of the array items like this: 75 /// 76 /// <pre> 77 /// SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path ); 78 /// SXMPUtils::ComposeArrayItemPath ( schemaNS, path, index, &path ); 79 /// exists = xmpObj.GetProperty_Int ( schemaNS, path, &value, &options ); 80 /// </pre> 81 /// 82 /// You could also use this code if you want the string form of the integer: 83 /// 84 /// <pre> 85 /// SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path ); 86 /// xmpObj.GetArrayItem ( schemaNS, path, index, &value, &options ); 87 /// </pre> 88 /// 89 /// \note It might look confusing that the \c schemaNS is passed in all of the calls above. This 90 /// is because the XMP Toolkit keeps the top-level "schema" namespace separate from the rest of 91 /// the path expression. 92 93 // --------------------------------------------------------------------------------------------- 94 /// @brief \c ComposeArrayItemPath() composes the path expression for an item in an array. 95 /// 96 /// The returned string is in the form <tt>ns:arrayName[i]</tt>, where "ns" is the prefix for 97 /// the specified namespace, and "i" is the decimal representation of specified item index. 98 /// If the last item was specified, the path is <tt>ns:arrayName[last()]</tt>. 99 /// 100 /// @param schemaNS The namespace URI for the array; see \c GetProperty(). 101 /// 102 /// @param arrayName The name of the array. Can be a general path expression, must not be null 103 /// or the empty string; see \c GetProperty() for namespace prefix usage. 104 /// 105 /// @param itemIndex The 1-based index of the desired item. Use the macro 106 /// \c #kXMP_ArrayLastItem to specify the last existing array item. 107 /// 108 /// @param fullPath [out] A string in which to return the composed path. 109 110 static void ComposeArrayItemPath ( XMP_StringPtr schemaNS, 111 XMP_StringPtr arrayName, 112 XMP_Index itemIndex, 113 tStringObj * fullPath ); 114 115 // --------------------------------------------------------------------------------------------- 116 /// @brief \c ComposeStructFieldPath() composes the path expression for a field in a struct. 117 /// 118 /// The returned string is in the form <tt>ns:structName/fNS:fieldName</tt>, where "ns" is the 119 /// prefix for the schema namespace, and "fNS" is the prefix for field namespace. 120 /// 121 /// @param schemaNS The namespace URI for the struct; see \c GetProperty(). 122 /// 123 /// @param structName The name of the struct. Can be a general path expression, must not be null 124 /// or the empty string; see \c GetProperty() for namespace prefix usage. 125 /// 126 /// @param fieldNS The namespace URI for the field. Same URI and prefix usage as the 127 /// \c schemaNS and \c structName parameters. 128 /// 129 /// @param fieldName The name of the field. Must be a single XML name, must not be null or the 130 /// empty string. Same URI and prefix usage as the \c schemaNS and \c structName parameters. 131 /// 132 /// @param fullPath [out] A string in which to return the composed path. 133 134 static void ComposeStructFieldPath ( XMP_StringPtr schemaNS, 135 XMP_StringPtr structName, 136 XMP_StringPtr fieldNS, 137 XMP_StringPtr fieldName, 138 tStringObj * fullPath ); 139 140 // --------------------------------------------------------------------------------------------- 141 /// @brief \c ComposeQualifierPath() composes the path expression for a qualifier. 142 /// 143 /// The returned string is in the form <tt>ns:propName/?qNS:qualName</tt>, where "ns" is the 144 /// prefix for the schema namespace, and "qNS" is the prefix for the qualifier namespace. 145 /// 146 /// @param schemaNS The namespace URI; see \c GetProperty(). 147 /// 148 /// @param propName The name of the property to which the qualifier is attached. Can be a 149 /// general path expression, must not be null or the empty string; see \c GetProperty() for 150 /// namespace prefix usage. 151 /// 152 /// @param qualNS The namespace URI for the qualifier. Same URI and prefix usage as the 153 /// \c schemaNS and \c propName parameters. 154 /// 155 /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or the 156 /// empty string. Same URI and prefix usage as the \c schemaNS and \c propName parameters. 157 /// 158 /// @param fullPath [out] A string in which to return the composed path. 159 160 static void ComposeQualifierPath ( XMP_StringPtr schemaNS, 161 XMP_StringPtr propName, 162 XMP_StringPtr qualNS, 163 XMP_StringPtr qualName, 164 tStringObj * fullPath ); 165 166 // --------------------------------------------------------------------------------------------- 167 /// @brief \c ComposeLangSelector() composes the path expression to select an alternate item by language. 168 /// 169 /// Path syntax allows two forms of "content addressing" to select an item in an array of 170 /// alternatives. The form used in this function lets you select an item in an alt-text array 171 /// based on the value of its \c xml:lang qualifier. The other form of content addressing is 172 /// shown in \c ComposeFieldSelector(). 173 /// 174 /// The returned string is in the form <tt>ns:arrayName[\@xml:lang='langName']</tt>, where 175 /// "ns" is the prefix for the schema namespace 176 /// 177 /// This function provides a path expression that is explicitly and only for a specific 178 /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText() 179 /// are preferred, because they provide extra logic to choose the appropriate language and 180 /// maintain consistency with the 'x-default' value. 181 /// 182 /// @param schemaNS The namespace URI for the array; see \c GetProperty(). 183 /// 184 /// @param arrayName The name of the array. Can be a general path expression, must not be null 185 /// or the empty string; see \c GetProperty() for namespace prefix usage. 186 /// 187 /// @param langName The RFC 3066 code for the desired language, as a null-terminated UTF-8 string. 188 /// 189 /// @param fullPath [out] A string in which to return the composed path. 190 191 static void ComposeLangSelector ( XMP_StringPtr schemaNS, 192 XMP_StringPtr arrayName, 193 XMP_StringPtr langName, 194 tStringObj * fullPath ); 195 196 // --------------------------------------------------------------------------------------------- 197 /// @brief \c ComposeLangSelector() composes a path expression to select an alternate item by language. 198 /// 199 /// Path syntax allows two forms of "content addressing" to select an item in an array of 200 /// alternatives. The form used in this function lets you select an item in an alt-text array 201 /// based on the value of its \c xml:lang qualifier. The other form of content addressing is 202 /// shown in \c ComposeFieldSelector(). 203 /// 204 /// The returned string is in the form <tt>ns:arrayName[\@xml:lang='langName']</tt>, where 205 /// "ns" is the prefix for the schema namespace 206 /// 207 /// This function provides a path expression that is explicitly and only for a specific 208 /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText() 209 /// are preferred, because they provide extra logic to choose the appropriate language and 210 /// maintain consistency with the 'x-default' value. 211 /// 212 /// @param schemaNS The namespace URI for the array; see \c GetProperty(). 213 /// 214 /// @param arrayName The name of the array. Can be a general path expression, must not be null 215 /// or the empty string; see \c GetProperty() for namespace prefix usage. 216 /// 217 /// @param langName The RFC 3066 code for the desired language, as a string object. 218 /// 219 /// @param fullPath [out] A string in which to return the composed path. 220 221 static void ComposeLangSelector ( XMP_StringPtr schemaNS, 222 XMP_StringPtr arrayName, 223 const tStringObj & langName, 224 tStringObj * fullPath ); 225 226 // --------------------------------------------------------------------------------------------- 227 /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value. 228 /// 229 /// Path syntax allows two forms of "content addressing" to select an item in an array of 230 /// alternatives. The form used in this function lets you select an item in an array of structs 231 /// based on the value of one of the fields in the structs. The other form of content addressing 232 /// is shown in \c ComposeLangSelector(). 233 /// 234 /// For example, consider a simple struct that has two fields, the name of a city and the URI of 235 /// an FTP site in that city. Use this to create an array of download alternatives. You can show 236 /// the user a popup built from the values of the city fields, then get the corresponding URI as 237 /// follows: 238 /// <pre> 239 /// ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path ); 240 /// exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri ); 241 /// </pre> 242 /// 243 /// The returned string is in the form <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where 244 /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace. 245 /// 246 /// @param schemaNS The namespace URI for the array; see \c GetProperty(). 247 /// 248 /// @param arrayName The name of the array. Can be a general path expression, must not be null 249 /// or the empty string; see \c GetProperty() for namespace prefix usage. 250 /// 251 /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix 252 /// usage as the \c schemaNS and \c arrayName parameters. 253 /// 254 /// @param fieldName The name of the field used as the selector. Must be a single XML name, must 255 /// not be null or the empty string. It must be the name of a field that is itself simple. 256 /// 257 /// @param fieldValue The desired value of the field, specified as a null-terminated UTF-8 string. 258 /// 259 /// @param fullPath [out] A string in which to return the composed path. 260 261 static void ComposeFieldSelector ( XMP_StringPtr schemaNS, 262 XMP_StringPtr arrayName, 263 XMP_StringPtr fieldNS, 264 XMP_StringPtr fieldName, 265 XMP_StringPtr fieldValue, 266 tStringObj * fullPath ); 267 268 // --------------------------------------------------------------------------------------------- 269 /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value. 270 /// 271 /// Path syntax allows two forms of "content addressing" to select an item in an array of 272 /// alternatives. The form used in this function lets you select an item in an array of structs 273 /// based on the value of one of the fields in the structs. The other form of content addressing 274 /// is shown in \c ComposeLangSelector(). 275 /// 276 /// For example, consider a simple struct that has two fields, the name of a city and the URI of 277 /// an FTP site in that city. Use this to create an array of download alternatives. You can show 278 /// the user a popup built from the values of the city fields, then get the corresponding URI as 279 /// follows: 280 /// <pre> 281 /// ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path ); 282 /// exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri ); 283 /// </pre> 284 /// 285 /// The returned string is in the form <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where 286 /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace. 287 /// 288 /// @param schemaNS The namespace URI for the array; see \c GetProperty(). 289 /// 290 /// @param arrayName The name of the array. Can be a general path expression, must not be null 291 /// or the empty string; see \c GetProperty() for namespace prefix usage. 292 /// 293 /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix 294 /// usage as the \c schemaNS and \c arrayName parameters. 295 /// 296 /// @param fieldName The name of the field used as the selector. Must be a single XML name, must 297 /// not be null or the empty string. It must be the name of a field that is itself simple. 298 /// 299 /// @param fieldValue The desired value of the field, specified as a string object. 300 /// 301 /// @param fullPath [out] A string in which to return the composed path. 302 303 static void ComposeFieldSelector ( XMP_StringPtr schemaNS, 304 XMP_StringPtr arrayName, 305 XMP_StringPtr fieldNS, 306 XMP_StringPtr fieldName, 307 const tStringObj & fieldValue, 308 tStringObj * fullPath ); 309 310 /// @} 311 312 // ============================================================================================= 313 /// \name Conversion between binary types and strings 314 /// @{ 315 /// 316 /// The main accessors in \c TXMPMeta set and retrieve property values as strings. additional 317 /// functions, such as \c TXMPMeta::SetPropertyInt(), set and retrieve property values as 318 /// explicit binary data types. Use these functions to convert between binary and string 319 /// values. 320 /// 321 /// Strings can be specified as null-terminated UTF-8 (\c #XMP_StringPtr), or as string 322 /// objects (\c tStringObj) of the type declared when instantiating the XMP classes; see 323 /// \c XMP.hpp. Alternate forms of each conversion function allow either type of string. 324 325 // --------------------------------------------------------------------------------------------- 326 /// @brief \c ConvertFromBool() converts a Boolean value to a string. 327 /// 328 /// The string values of Booleans are returned by the macros \c #kXMP_TrueStr and 329 /// \c #kXMP_FalseStr in \c XMP_Const.h. 330 /// 331 /// @param binValue The Boolean value to be converted. 332 /// 333 /// @param strValue [out] A buffer in which to return the string representation of the value. 334 335 static void ConvertFromBool ( bool binValue, 336 tStringObj * strValue ); 337 338 // --------------------------------------------------------------------------------------------- 339 /// @brief \c ConvertFromInt() converts a 32-bit integer value to a string. 340 /// 341 /// @param binValue The integer value to be converted. 342 /// 343 /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". 344 /// 345 /// @param strValue [out] A buffer in which to return the string representation of the value. 346 347 static void ConvertFromInt ( long binValue, 348 XMP_StringPtr format, 349 tStringObj * strValue ); 350 // --------------------------------------------------------------------------------------------- 351 /// @brief \c ConvertFromInt64() converts a 64-bit integer value to a string. 352 /// 353 /// @param binValue The integer value to be converted. 354 /// 355 /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". 356 /// 357 /// @param strValue [out] A buffer in which to return the string representation of the value. 358 359 static void ConvertFromInt64 ( long long binValue, 360 XMP_StringPtr format, 361 tStringObj * strValue ); 362 363 // --------------------------------------------------------------------------------------------- 364 /// @brief \c ConvertFromFloat() converts a floating-point value to a string. 365 /// 366 /// @param binValue The floating-point value to be converted. 367 /// 368 /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". 369 /// 370 /// @param strValue [out] A buffer in which to return the string representation of the value. 371 372 static void ConvertFromFloat ( double binValue, 373 XMP_StringPtr format, 374 tStringObj * strValue ); 375 376 // --------------------------------------------------------------------------------------------- 377 /// @brief \c ConvertFromDate() converts a date/time value to a string. 378 /// 379 /// Formats a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime: 380 /// <pre> 381 /// YYYY 382 /// YYYY-MM 383 /// YYYY-MM-DD 384 /// YYYY-MM-DDThh:mmTZD 385 /// YYYY-MM-DDThh:mm:ssTZD 386 /// YYYY-MM-DDThh:mm:ss.sTZD 387 /// </pre> 388 /// 389 /// \c YYYY = four-digit year, formatted as "%.4d" <br> 390 /// \c MM = two-digit month (01=January) <br> 391 /// \c DD = two-digit day of month (01 through 31) <br> 392 /// \c hh = two digits of hour (00 through 23) <br> 393 /// \c mm = two digits of minute (00 through 59) <br> 394 /// \c ss = two digits of second (00 through 59) <br> 395 /// \c s = one or more digits representing a decimal fraction of a second <br> 396 /// \c TZD = time zone designator (Z or +hh:mm or -hh:mm) 397 /// 398 /// Time-only input is allowed where the year, month, and day are all zero. This is output as 399 /// "0000-00-00...". 400 /// 401 /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows 402 /// any year, even negative ones. 403 /// 404 /// @param binValue The date/time value to be converted. 405 /// 406 /// @param strValue [out] A buffer in which to return the ISO 8601 string representation of the date/time. 407 408 static void ConvertFromDate ( const XMP_DateTime & binValue, 409 tStringObj * strValue ); 410 411 // --------------------------------------------------------------------------------------------- 412 /// @brief \c ConvertToBool() converts a string to a Boolean value. 413 /// 414 /// The preferred strings are those returned by the macros \c #kXMP_TrueStr and \c #kXMP_FalseStr. 415 /// If these do not match, the function does a case insensitive comparison, then simply 't' or 'f', 416 /// and finally non-zero and zero integer representations. 417 /// 418 /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. 419 /// 420 /// @return The appropriate C++ bool value for the string. 421 422 static bool ConvertToBool ( XMP_StringPtr strValue ); 423 424 // --------------------------------------------------------------------------------------------- 425 /// @brief \c ConvertToBool() converts a string to a Boolean value. 426 /// 427 /// Overloads the basic form of the function, allowing you to pass a string object, 428 /// rather than a <tt>const * char</tt>. It is otherwise identical; see details in the canonical form. 429 /// 430 /// @param strValue The string representation of the value, specified as a string object. 431 /// 432 /// @return The appropriate C++ bool value for the string. 433 434 static bool ConvertToBool ( const tStringObj & strValue ); 435 436 // --------------------------------------------------------------------------------------------- 437 /// @brief \c ConvertToInt() converts a string to a 32-bit integer value. 438 /// 439 /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. 440 /// 441 /// @return The 32-bit integer value. 442 443 static long ConvertToInt ( XMP_StringPtr strValue ); 444 445 // --------------------------------------------------------------------------------------------- 446 /// @brief \c ConvertToInt() converts a string to a 32-bit integer value. 447 /// 448 /// Overloads the basic form of the function, allowing you to pass a string object, 449 /// rather than a <tt>const * char</tt>. It is otherwise identical. 450 /// 451 /// @param strValue The string representation of the value, specified as a string object. 452 /// 453 /// @return The 32-bit integer value. 454 455 static long ConvertToInt ( const tStringObj & strValue ); 456 457 // --------------------------------------------------------------------------------------------- 458 /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value. 459 /// 460 /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. 461 /// 462 /// @return The 64-bit integer value. 463 464 static long long ConvertToInt64 ( XMP_StringPtr strValue ); 465 466 // --------------------------------------------------------------------------------------------- 467 /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value. 468 /// 469 /// Overloads the basic form of the function, allowing you to pass a string object, 470 /// rather than a <tt>const * char</tt>. It is otherwise identical. 471 /// 472 /// @param strValue The string representation of the value, specified as a string object. 473 /// 474 /// @return The 64-bit integer value. 475 476 static long long ConvertToInt64 ( const tStringObj & strValue ); 477 478 // --------------------------------------------------------------------------------------------- 479 /// @brief \c ConvertToFloat() converts a string to a floating-point value. 480 /// 481 /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. 482 /// 483 /// @return The floating-point value. 484 485 static double ConvertToFloat ( XMP_StringPtr strValue ); 486 487 // --------------------------------------------------------------------------------------------- 488 /// @brief \c ConvertToFloat() converts a string to a floating-point value. 489 /// 490 /// Overloads the basic form of the function, allowing you to pass a string object, 491 /// rather than a <tt>const * char</tt>. It is otherwise identical. 492 /// 493 /// @param strValue The string representation of the value, specified as a string object. 494 /// 495 /// @return The floating-point value. 496 497 static double ConvertToFloat ( const tStringObj & strValue ); 498 499 // --------------------------------------------------------------------------------------------- 500 /// @brief \c ConvertToDate() converts a string to a date/time value. 501 /// 502 /// Parses a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime: 503 /// <pre> 504 /// YYYY 505 /// YYYY-MM 506 /// YYYY-MM-DD 507 /// YYYY-MM-DDThh:mmTZD 508 /// YYYY-MM-DDThh:mm:ssTZD 509 /// YYYY-MM-DDThh:mm:ss.sTZD 510 /// </pre> 511 /// 512 /// \c YYYY = four-digit year, formatted as "%.4d" <br> 513 /// \c MM = two-digit month (01=January) <br> 514 /// \c DD = two-digit day of month (01 through 31) <br> 515 /// \c hh = two digits of hour (00 through 23) <br> 516 /// \c mm = two digits of minute (00 through 59) <br> 517 /// \c ss = two digits of second (00 through 59) <br> 518 /// \c s = one or more digits representing a decimal fraction of a second <br> 519 /// \c TZD = time zone designator (Z or +hh:mm or -hh:mm) 520 /// 521 /// A missing date portion or missing TZD are tolerated. A missing date value can begin with 522 /// "Thh:" or "hh:"; the year, month, and day are all set to zero in the \c #XMP_DateTime value. 523 /// A missing TZD is assumed to be UTC. 524 /// 525 /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows 526 /// any year, even negative ones. 527 /// 528 /// @param strValue The ISO 8601 string representation of the date/time, specified as a 529 /// null-terminated UTF-8 string. 530 /// 531 /// @param binValue [out] A buffer in which to return the binary date/time value. 532 533 static void ConvertToDate ( XMP_StringPtr strValue, 534 XMP_DateTime * binValue ); 535 536 // --------------------------------------------------------------------------------------------- 537 /// @brief \c ConvertToDate() converts a string to a date/time value. 538 /// 539 /// Overloads the basic form of the function, allowing you to pass a string object, 540 /// rather than a <tt>const * char</tt>. It is otherwise identical. 541 /// See details for the canonical form. 542 /// 543 /// 544 /// @param strValue The ISO 8601 string representation of the date/time, specified as a string 545 /// object. 546 /// 547 /// @param binValue [out] A buffer in which to return the binary date/time value. 548 549 static void ConvertToDate ( const tStringObj & strValue, 550 XMP_DateTime * binValue ); 551 552 /// @} 553 554 // ============================================================================================= 555 /// \name Date-time manipulation 556 /// @{ 557 /// 558 /// In addition to the type-conversion functions that convert between strings and binary 559 /// date-time values, these functions create, manipulate, and compare date-time values. 560 561 // --------------------------------------------------------------------------------------------- 562 /// @brief \c CurrentDateTime() obtains the current date and time. 563 /// 564 /// Creates and returns a binary \c #XMP_DateTime value. The returned time is UTC, properly 565 /// adjusted for the local time zone. The resolution of the time is not guaranteed to be finer 566 /// than seconds. 567 /// 568 /// @param time [out] A buffer in which to return the date/time value. 569 570 static void CurrentDateTime ( XMP_DateTime * time ); 571 572 // --------------------------------------------------------------------------------------------- 573 /// @brief \c SetTimeZone() sets the time zone in a date/time value to the local time zone. 574 /// 575 /// Any existing time zone value is replaced. The other date/time fields are not adjusted in any way. 576 /// 577 /// @param time A pointer to the date-time value, which is modified in place. 578 579 static void SetTimeZone ( XMP_DateTime * time ); 580 581 // --------------------------------------------------------------------------------------------- 582 /// @brief \c ConvertToUTCTime() ensures that a time is UTC. 583 /// 584 /// If the time zone is not UTC, the time is adjusted and the time zone set to be UTC. If the 585 /// time zone is already UTC, the value is not modified. 586 /// 587 /// @param time A pointer to the date-time value, which is modified in place. 588 589 static void ConvertToUTCTime ( XMP_DateTime * time ); 590 591 // --------------------------------------------------------------------------------------------- 592 /// @brief \c ConvertToLocalTime() ensures that a time is local. 593 /// 594 /// If the time zone is not the local zone, the time is adjusted and the time zone set to be local. 595 /// If the time zone is already the local zone, the value is not modified. 596 /// 597 /// @param time A pointer to the date-time value, which is modified in place. 598 599 static void ConvertToLocalTime ( XMP_DateTime * time ); 600 601 // --------------------------------------------------------------------------------------------- 602 /// @brief \c CompareDateTime() compares the order of two date/time values. 603 /// 604 /// @param left The left-side date/time value. 605 /// 606 /// @param right The right-side date/time value. 607 /// 608 /// @return An integer indicating the order: 609 /// \li -1 if left is earlier than right 610 /// \li 0 if left matches right 611 /// \li +1 if left is later than right 612 613 static int CompareDateTime ( const XMP_DateTime & left, 614 const XMP_DateTime & right ); 615 616 /// @} 617 618 // ============================================================================================= 619 /// \name Base64 encoding and decoding 620 /// @{ 621 /// 622 /// These functions convert between raw data values and Base64-encoded strings. 623 624 // --------------------------------------------------------------------------------------------- 625 /// @brief \c EncodeToBase64() converts a raw data value to a Base64-encoded string. 626 /// 627 /// @param rawStr An \c #XMP_StringPtr (char *) string containing the raw data to be converted. 628 /// 629 /// @param rawLen The number of characters of raw data to be converted. 630 /// 631 /// @param encodedStr [out] A string object in which to return the encoded string. 632 633 static void EncodeToBase64 ( XMP_StringPtr rawStr, 634 XMP_StringLen rawLen, 635 tStringObj * encodedStr ); 636 637 // --------------------------------------------------------------------------------------------- 638 /// @brief \c EncodeToBase64() converts a raw data value passed in a string object to a Base64-encoded string. 639 /// 640 /// Overloads the basic form of the function, allowing you to pass a string object as input. 641 /// It is otherwise identical. 642 /// 643 /// @param rawStr A string object containing the raw data to be converted. 644 /// 645 /// @param encodedStr [out] A string object in which to return the encoded string. 646 647 static void EncodeToBase64 ( const tStringObj & rawStr, 648 tStringObj * encodedStr ); 649 650 // --------------------------------------------------------------------------------------------- 651 /// @brief \c DecodeFromBase64() Decodes a Base64-encoded string to raw data. 652 /// 653 /// @param encodedStr An \c #XMP_StringPtr (char *) string containing the encoded data to be converted. 654 /// 655 /// @param encodedLen The number of characters of raw data to be converted. 656 /// 657 /// @param rawStr [out] A string object in which to return the decoded data. 658 659 static void DecodeFromBase64 ( XMP_StringPtr encodedStr, 660 XMP_StringLen encodedLen, 661 tStringObj * rawStr ); 662 663 // --------------------------------------------------------------------------------------------- 664 /// @brief \c DecodeFromBase64() Decodes a Base64-encoded string, passed as a string object, to raw data. 665 /// 666 /// Overloads the basic form of the function, allowing you to pass a string object as input. 667 /// It is otherwise identical. 668 /// 669 /// @param encodedStr An string object containing the encoded data to be converted. 670 /// 671 /// @param rawStr [out] A string object in which to return the decoded data. 672 673 static void DecodeFromBase64 ( const tStringObj & encodedStr, 674 tStringObj * rawStr ); 675 676 /// @} 677 678 // ============================================================================================= 679 // ============================================================================================= 680 /// \name JPEG file handling 681 /// @{ 682 /// 683 /// These functions support the partitioning of XMP in JPEG files into standard and extended 684 /// portions in order to work around the 64KB size limit of JPEG marker segments. 685 /// 686 /// @note (Doc note) Add detail about how to write out and read back extended data 687 688 // --------------------------------------------------------------------------------------------- 689 /// @brief \c PackageForJPEG() creates XMP serializations appropriate for a JPEG file. 690 /// 691 /// The standard XMP in a JPEG file is limited to 64K bytes. This function serializes the XMP 692 /// metadata in an XMP object into a string of RDF (see \c TXMPMeta::SerializeToBuffer()). If 693 /// the data does not fit into the 64K byte limit, it creates a second packet string with the 694 /// extended data. 695 /// 696 /// @param xmpObj The XMP object containing the metadata. 697 /// 698 /// @param standardXMP [out] A string object in which to return the full standard XMP packet. 699 /// 700 /// @param extendedXMP [out] A string object in which to return the serialized extended XMP, 701 /// empty if not needed. 702 /// 703 /// @param extendedDigest [out] A string object in which to return an MD5 digest of the serialized 704 /// extended XMP, empty if not needed. 705 /// 706 /// @see \c MergeFromJPEG() 707 708 static void PackageForJPEG ( const TXMPMeta<tStringObj> & xmpObj, 709 tStringObj * standardXMP, 710 tStringObj * extendedXMP, 711 tStringObj * extendedDigest ); 712 713 // --------------------------------------------------------------------------------------------- 714 /// @brief \c MergeFromJPEG() merges standard and extended XMP retrieved from a JPEG file. 715 /// 716 /// When an extended partition stores properties that do not fit into the JPEG file limitation 717 /// of 64K bytes, this function integrates those properties back into the same XMP object with 718 /// those from the standard XMP packet. 719 /// 720 /// @param fullXMP [in, out] An XMP object which the caller has initialized from the standard 721 /// XMP packet in a JPEG file. The extended XMP is added to this object. 722 /// 723 /// @param extendedXMP An XMP object which the caller has initialized from the extended XMP 724 /// packet in a JPEG file. 725 /// 726 /// @see \c PackageForJPEG() 727 728 static void MergeFromJPEG ( TXMPMeta<tStringObj> * fullXMP, 729 const TXMPMeta<tStringObj> & extendedXMP ); 730 731 /// @} 732 733 // ============================================================================================= 734 /// \name Editing utilities 735 /// @{ 736 /// 737 /// These functions are useful in implementing a user interface for editing XMP. They 738 /// convert sets of property values to and from displayable and manipulable strings, and perform 739 /// operations on sets of metadata, such as those available from the File Info dialog box. 740 741 // --------------------------------------------------------------------------------------------- 742 /// @brief \c CatenateArrayItems() creates a single edit string from a set of array item values. 743 /// 744 /// Collects the values of all items in an array into a single string, using a specified 745 /// separation string. Each item in the specified array must be a simple string value. 746 /// 747 /// @param xmpObj The XMP object containing the array to be catenated. 748 /// 749 /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string. 750 /// 751 /// @param arrayName The name of the array. May be a general path expression, must not be null 752 /// or the empty string. 753 /// 754 /// @param separator The string with which to separate the items in the catenated string. 755 /// Defaults to "; ", ASCII semicolon and space (U+003B, U+0020). 756 /// 757 /// @param quotes The character or characters to use as quotes around array items that contain a 758 /// separator. Defaults to the double-quote character ("), ASCII quote (U+0022). 759 /// 760 /// @param options Option flags to control the catenation. <<what options?>> 761 /// 762 /// @param catedStr [out] A string object in which to return the catenated array items. 763 /// 764 /// @see \c SeparateArrayItems() 765 766 static void CatenateArrayItems ( const TXMPMeta<tStringObj> & xmpObj, 767 XMP_StringPtr schemaNS, 768 XMP_StringPtr arrayName, 769 XMP_StringPtr separator, 770 XMP_StringPtr quotes, 771 XMP_OptionBits options, 772 tStringObj * catedStr ); 773 774 // --------------------------------------------------------------------------------------------- 775 /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values. 776 /// 777 /// This reverses the action of \c CatenateArrayItems(), separating out individual array items 778 /// from the edit string and updating the array with the new values. Each item in the array must 779 /// be a simple string value. 780 /// 781 /// @param xmpObj The XMP object containing the array to be updated. 782 /// 783 /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string. 784 /// 785 /// @param arrayName The name of the array. May be a general path expression, must not be null 786 /// or the empty string. 787 /// 788 /// @param options Option flags to control the separation. <<what options?>> 789 /// 790 /// @param catedStr The concatenated array items, as created by \c CatenateArrayItems(), 791 /// specified as a null-terminated UTF-8 string. 792 793 static void SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj, 794 XMP_StringPtr schemaNS, 795 XMP_StringPtr arrayName, 796 XMP_OptionBits options, 797 XMP_StringPtr catedStr ); 798 799 // --------------------------------------------------------------------------------------------- 800 /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values. 801 /// 802 /// Overloads the basic form of the function, allowing you to pass a string object in which 803 /// to return the concatenated string. It is otherwise identical; see details for the canonical form. 804 /// 805 806 static void SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj, 807 XMP_StringPtr schemaNS, 808 XMP_StringPtr arrayName, 809 XMP_OptionBits options, 810 const tStringObj & catedStr ); 811 812 // --------------------------------------------------------------------------------------------- 813 /// @brief \c RemoveProperties() removes multiple properties from an XMP object. 814 /// 815 /// The operation depends on how the namespace and property are specified: 816 /// 817 /// \li Non-empty \c schemaNS and \c propName - The named property is removed if it is an 818 /// external property, or if the \c #kXMPUtil_DoAllProperties option flag is set. It does not 819 /// matter whether the named property is an actual property or an alias. 820 /// 821 /// \li Non-empty \c schemaNS and empty \c propName - All external properties in the named 822 /// schema are removed. Internal properties are also removed if the 823 /// \c #kXMPUtil_DoAllProperties option flag is set. In addition, aliases from the named schema 824 /// are removed if the \c #kXMPUtil_IncludeAliases option flag is set. 825 /// 826 /// \li Empty \c schemaNS and empty \c propName - All external properties in all schemas are 827 /// removed. Internal properties are also removed if the \c #kXMPUtil_DoAllProperties option 828 /// flag is set. Aliases are handled implicitly, because the associated actuals are removed or 829 /// not. 830 /// 831 /// \li It is an error to pass an empty \c schemaNS and non-empty \c propName. 832 /// 833 /// @param xmpObj The XMP object containing the properties to be removed. 834 /// 835 /// @param schemaNS Optional schema namespace URI for the properties to be removed. 836 /// 837 /// @param propName Optional path expression for the property to be removed. 838 /// 839 /// @param options Option flags to control the deletion operation. A logical OR of these 840 /// bit-flag constants: 841 /// \li \c #kXMPUtil_DoAllProperties - Delete internal properties in addition to external properties. 842 /// \li \c #kXMPUtil_IncludeAliases - Include aliases if the schema is explicitly specified. 843 844 static void RemoveProperties ( TXMPMeta<tStringObj> * xmpObj, 845 XMP_StringPtr schemaNS = 0, 846 XMP_StringPtr propName = 0, 847 XMP_OptionBits options = 0 ); 848 849 // --------------------------------------------------------------------------------------------- 850 /// @brief \c AppendProperties() adds or moves properties from one XMP object to another. 851 /// 852 /// The default operation is to append only external properties that do not already exist in the 853 /// destination. Option flags allow you to add internal properties, and to merge values of 854 /// properties that exist in both the source and destination. 855 /// 856 /// \li \c #kXMPUtil_DoAllProperties: Operate on all top-level properties, external and 857 /// internal. You can use this flag together with \c #kXMPUtil_ReplaceOldValues to replace the 858 /// values of existing top-level properties. 859 /// 860 /// \li \c #kXMPUtil_ReplaceOldValues: Propogate all top-level properties from the source to 861 /// the destination, replacing any existing values. The values of properties in the 862 /// destination that are not in the source are not modified.<br> 863 /// The keep-or-replace-old notion also applies within structs and arrays. Top-level 864 /// properties are added to the destination if they do not already exist. If they do exist but 865 /// differ in form (simple/struct/array) then the destination is not modified. If the forms 866 /// match, simple properties are left unchanged, while structs and arrays are merged.<br> 867 /// Do not use this option when the processing is more complicated. <<than what??>> 868 /// 869 /// \li \c #kXMPUtil_DeleteEmptyValues: An empty value in the source XMP causes the 870 /// corresponding destination property to be deleted. By default, empty values are treated in 871 /// the same way as non-empty values. An empty value is a simple empty string, an array with 872 /// no items,or a struct with no fields. Qualifiers are ignored. 873 /// 874 /// The detailed behavior is defined by the following pseudo-code: 875 /// 876 /// <pre> 877 /// AppendProperties ( sourceXMP, destXMP, options ): 878 /// doAll = options & kXMPUtil_DoAllProperties 879 /// replaceOld = options & kXMPUtil_ReplaceOldValues 880 /// deleteEmpty = options & kXMPUtil_DeleteEmptyValues 881 /// for all source schema (top level namespaces): 882 /// for all top level properties in sourceSchema: 883 /// if doAll or prop is external: 884 /// AppendSubtree ( sourceNode, destSchema, replaceOld, deleteEmpty ) 885 /// 886 /// AppendSubtree ( sourceNode, destParent, replaceOld, deleteEmpty ): 887 /// if deleteEmpty and source value is empty: 888 /// delete the corresponding child from destParent 889 /// else if sourceNode not in destParent (by name): 890 /// copy sourceNode's subtree to destParent 891 /// else if replaceOld: 892 /// delete subtree from destParent 893 /// copy sourceNode's subtree to destParent 894 /// else: // (Already exists in dest and not replacing, merge structs and arrays) 895 /// if sourceNode and destNode forms differ: 896 /// return, leave the destNode alone 897 /// else if form is a struct: 898 /// for each field in sourceNode: 899 /// AppendSubtree ( sourceNode.field, destNode, replaceOld ) 900 /// else if form is an alt-text array: 901 /// copy new items by xml:lang value into the destination 902 /// else if form is an array: 903 /// copy new items by value into the destination, ignoring order and duplicates 904 /// </pre> 905 /// 906 /// Array item checking is n-squared; this can be time-intensive if the replace-old options is 907 /// not specified. Each source item is checked to see if it already exists in the destination, 908 /// without regard to order or duplicates. Simple items are compared by value and \c xml:lang 909 /// qualifier; other qualifiers are ignored. Structs are recursively compared by field names, 910 /// without regard to field order. Arrays are compared by recursively comparing all items. 911 /// 912 /// @param source The source XMP object. 913 /// 914 /// @param dest The destination XMP object. 915 /// 916 /// @param options Option flags to control the copying. A logical OR of these bit-flag constants: 917 /// \li \c kXMPUtil_DoAllProperties - Operate on internal properties in addition to external properties. 918 /// \li \c kXMPUtil_ReplaceOldValues - Replace the values of existing properties. 919 /// \li \c kXMPUtil_DeleteEmptyValues - Delete properties if the new value is empty. 920 921 static void AppendProperties ( const TXMPMeta<tStringObj> & source, 922 TXMPMeta<tStringObj> * dest, 923 XMP_OptionBits options = 0 ); 924 925 // --------------------------------------------------------------------------------------------- 926 /// @brief \c DuplicateSubtree() replicates a subtree from one XMP object into another. 927 /// 928 /// The destination can be a different namespace and root location in the same object, or the 929 /// same or a different location in another XMP object. 930 /// 931 /// @param source The source XMP object. 932 /// 933 /// @param dest The destination XMP object. 934 /// 935 /// @param sourceNS The schema namespace URI for the source subtree. 936 /// 937 /// @param sourceRoot The root location for the source subtree. Can be a general path expression, 938 /// must not be null or the empty string. 939 /// 940 /// @param destNS The schema namespace URI for the destination. Defaults to the source namespace. 941 /// 942 /// @param destRoot The root location for the destination. Can be a general path expression. 943 /// Defaults to the source location. 944 /// 945 /// @param options Option flags to control the operation. <<options?>> 946 947 static void DuplicateSubtree ( const TXMPMeta<tStringObj> & source, 948 TXMPMeta<tStringObj> * dest, 949 XMP_StringPtr sourceNS, 950 XMP_StringPtr sourceRoot, 951 XMP_StringPtr destNS = 0, 952 XMP_StringPtr destRoot = 0, 953 XMP_OptionBits options = 0 ); 954 955 /// @} 956 957 // ============================================================================================= 958 959 // ============================================================================================= 960 961 }; // class TXMPUtils 962 963 // ================================================================================================= 964 965 #endif // __TXMPUtils_hpp__ 966