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