-
Notifications
You must be signed in to change notification settings - Fork 36
/
udunits2lib.texi
1776 lines (1540 loc) · 64.8 KB
/
udunits2lib.texi
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
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename udunits2lib.info
@settitle The UDUNITS-2 C API Guide
@c %**end of header
@dircategory Software libraries
@direntry
* UDUNITS-2: (udunits2lib). The Unidata units library.
@end direntry
@syncodeindex fn cp
@syncodeindex tp cp
@copying
@include COPYRIGHT
@end copying
@titlepage
@title The UDUNITS-2 C API
@author Steven R. Emmerson
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@contents
@ifnottex
@node Top, Synopsis, (dir), (dir)
@top UDUNITS-2
This manual describes how to use the C API of the UDUNITS-2 library.
Among other things, the library allows C code to obtain a binary
representation of a unit of a physical quantity, to
operate on such units, and to convert numeric values between compatible
units.
The library comes with an extensive database of units all referenced to the
SI system of units.
@insertcopying
@end ifnottex
@menu
* Synopsis:: Terse usage display
* Why:: What's a unit package good for?
* Unit-Systems:: Explanation of unit-systems and how to get one
* Parsing:: Converting strings into units
* Syntax:: Syntax for string representation of units
* Formatting:: Converting units into strings
* Value Conversion:: Converting values between units
* Prefixes:: Defining unit prefixes
* Mapping:: Mapping between units and identifiers
* Operations:: Operations on units
* Time:: Handling time
* Errors:: Error-handling
* Database:: The units database
* Types:: Data types
* Complete Index:: Complete index
@end menu
@node Synopsis, Why, Top, Top
@chapter Synopsis
@cindex synopsis
Coding:
@example
#include <udunits2.h>
@quotation
@multitable {ut_error_message_handler} {ut_get_dimensionless_unit_one(}
@item const char* @tab @ref{ut_get_path_xml(),ut_get_path_xml}(const char* @var{path}, ut_status* @var{status});
@item ut_system* @tab @ref{ut_read_xml(),ut_read_xml}(const char* @var{path});
@item ut_system* @tab @ref{ut_new_system(),ut_new_system}(void);
@item void @tab @ref{ut_free_system(), ut_free_system}(ut_system* @var{system});
@item ut_system* @tab @ref{ut_get_system(),ut_get_system}(const ut_unit* @var{unit});
@item ut_unit* @tab @ref{ut_get_dimensionless_unit_one(),ut_get_dimensionless_unit_one}(const ut_system* @var{system});
@item ut_unit* @tab @ref{ut_get_unit_by_name(),ut_get_unit_by_name}(const ut_system* @var{system}, const char* @var{name});
@item ut_unit* @tab @ref{ut_get_unit_by_symbol(),ut_get_unit_by_symbol}(const ut_system* @var{system}, const char* @var{symbol});
@item ut_status @tab @ref{ut_set_second(),ut_set_second}(const ut_unit* @var{second});
@item ut_status @tab @ref{ut_add_name_prefix(),ut_add_name_prefix}(ut_system* @var{system}, const char* @var{name}, double @var{value});
@item ut_status @tab @ref{ut_add_symbol_prefix(),ut_add_symbol_prefix}(ut_system* @var{system}, const char* @var{symbol}, double @var{value});
@item ut_unit* @tab @ref{ut_new_base_unit(),ut_new_base_unit}(ut_system* @var{system});
@item ut_unit* @tab @ref{ut_new_dimensionless_unit(),ut_new_dimensionless_unit}(ut_system* @var{system});
@item ut_unit* @tab @ref{ut_clone(),ut_clone}(const ut_unit* @var{unit});
@item void @tab @ref{ut_free(),ut_free}(ut_unit* @var{unit});
@item const char* @tab @ref{ut_get_name(),ut_get_name}(const ut_unit* @var{unit}, ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_map_name_to_unit(),ut_map_name_to_unit}(const char* @var{name}, const ut_encoding @var{encoding}, const ut_unit* @var{unit});
@item ut_status @tab @ref{ut_unmap_name_to_unit(),ut_unmap_name_to_unit}(ut_system* @var{system}, const char* @var{name}, const ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_map_unit_to_name(),ut_map_unit_to_name}(const ut_unit* @var{unit}, const char* @var{name}, ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_unmap_unit_to_name(),ut_unmap_unit_to_name}(const ut_unit* @var{unit}, ut_encoding @var{encoding});
@item const char* @tab @ref{ut_get_symbol(),ut_get_symbol}(const ut_unit* @var{unit}, ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_map_symbol_to_unit(),ut_map_symbol_to_unit}(const char* @var{symbol}, const ut_encoding @var{encoding}, const ut_unit* @var{unit});
@item ut_status @tab @ref{ut_unmap_symbol_to_unit(),ut_unmap_symbol_to_unit}(ut_system* @var{system}, const char* @var{symbol}, const ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_map_unit_to_symbol(),ut_map_unit_to_symbol}(const ut_unit* @var{unit}, const char* @var{symbol}, ut_encoding @var{encoding});
@item ut_status @tab @ref{ut_unmap_unit_to_symbol(),ut_unmap_unit_to_symbol}(const ut_unit* @var{unit}, ut_encoding @var{encoding});
@item int @tab @ref{ut_is_dimensionless(),ut_is_dimensionless}(const ut_unit* @var{unit});
@item int @tab @ref{ut_same_system(),ut_same_system}(const ut_unit* @var{unit1}, const ut_unit* @var{unit2});
@item int @tab @ref{ut_compare(),ut_compare}(const ut_unit* @var{unit1}, const ut_unit* @var{unit2});
@item int @tab @ref{ut_are_convertible(),ut_are_convertible}(const ut_unit* @var{unit1}, const ut_unit* @var{unit2});
@item cv_converter* @tab @ref{ut_get_converter(),ut_get_converter}(ut_unit* @var{from}, ut_unit* @var{to});
@item ut_unit* @tab @ref{ut_scale(),ut_scale}(double @var{factor}, const ut_unit* @var{unit});
@item ut_unit* @tab @ref{ut_offset(),ut_offset}(const ut_unit* @var{unit}, double @var{offset});
@item ut_unit* @tab @ref{ut_offset_by_time(),ut_offset_by_time}(const ut_unit* @var{unit}, double @var{origin});
@item ut_unit* @tab @ref{ut_multiply(),ut_multiply}(const ut_unit* @var{unit1}, const ut_unit* @var{unit2});
@item ut_unit* @tab @ref{ut_invert(),ut_invert}(const ut_unit* @var{unit});
@item ut_unit* @tab @ref{ut_divide(),ut_divide}(const ut_unit* @var{numer}, const ut_unit* @var{denom});
@item ut_unit* @tab @ref{ut_raise(),ut_raise}(const ut_unit* @var{unit}, int @var{power});
@item ut_unit* @tab @ref{ut_root(),ut_root}(const ut_unit* @var{unit}, int @var{root});
@item ut_unit* @tab @ref{ut_log(),ut_log}(double @var{base}, const ut_unit* @var{reference});
@item ut_unit* @tab @ref{ut_parse(),ut_parse}(const ut_system* @var{system}, const char* @var{string}, ut_encoding @var{encoding});
@item char* @tab @ref{ut_trim(),ut_trim}(char* @var{string}, ut_encoding @var{encoding});
@item int @tab @ref{ut_format(),ut_format}(const ut_unit* @var{unit}, char* @var{buf}, size_t @var{size}, unsigned @var{opts});
@item ut_status @tab @ref{ut_accept_visitor(),ut_accept_visitor}(const ut_unit* @var{unit}, const ut_visitor* @var{visitor}, void* @var{arg});
@item double @tab @ref{ut_encode_date(),ut_encode_date}(int @var{year}, int @var{month}, int @var{day});
@item double @tab @ref{ut_encode_clock(),ut_encode_clock}(int @var{hours}, int @var{minutes}, double @var{seconds});
@item double @tab @ref{ut_encode_time(),ut_encode_time}(int @var{year}, int @var{month}, int @var{day}, int @var{hour}, int @var{minute}, double @var{second});
@item void @tab @ref{ut_decode_time(),ut_decode_time}(double @var{value}, int* @var{year}, int* @var{month}, int* @var{day}, int* @var{hour}, int* @var{minute}, double* @var{second}, double* @var{resolution});
@item ut_status @tab @ref{ut_get_status(),ut_get_status}(void);
@item void @tab @ref{ut_set_status(),ut_set_status}(ut_status @var{status});
@item int @tab @ref{ut_handle_error_message(),ut_handle_error_message}(const char* @var{fmt}, ...);
@item ut_error_message_handler @tab @ref{ut_set_error_message_handler(),ut_set_error_message_handler}(ut_error_message_handler @var{handler});
@item int @tab @ref{ut_write_to_stderr(),ut_write_to_stderr}(const char* @var{fmt}, va_list @var{args});
@item int @tab @ref{ut_ignore(),ut_ignore}(const char* @var{fmt}, va_list @var{args});
@item
@item float @tab @ref{cv_convert_float(),cv_convert_float}(const cv_converter* @var{converter}, float @var{value});
@item double @tab @ref{cv_convert_double(),cv_convert_double}(const cv_converter* @var{converter}, double @var{value});
@item float* @tab @ref{cv_convert_floats(),cv_convert_floats}(const cv_converter* @var{converter}, const float* @var{in}, size_t @var{count}, float* @var{out});
@item double* @tab @ref{cv_convert_doubles(),cv_convert_doubles}(const cv_converter* @var{converter}, const double* @var{const} in, @var{size_t} count, @var{double}* out);
@item void @tab @ref{cv_free(),cv_free}(cv_converter* @var{conv});
@end multitable
@end quotation
@end example
Compiling:
@example
c89 -I @emph{includedir} ...
@end example
Where @emph{includedir} is the installation-directory for C header
files (e.g., @code{/usr/local/include}).
Linking:
@example
c89 ... -L@emph{libdir} -ludunits2 -lexpat ... -lm
@end example
Where @emph{libdir} is the installation-directory for object code
libraries (e.g., @code{/usr/local/lib}).
@node Why, Unit-Systems, Synopsis, Top
@chapter What's a Unit Package Good For?
The existence of a software package is justified by what you can do with it.
The three main things you can do with the UDUNIT-2 package are
@enumerate
@item
@ref{Value Conversion,
Convert numeric values between compatible units}.
@item
Convert a string representation of a unit into a binary one --- enabling
the programatic manipulation of units.
There are three ways to do this:
@itemize
@item
@ref{Extracting,Get the unit} from a @ref{unit-system}.
This requires that
you know the unit's name or symbol and that the unit is in a unit-system.
@item
@ref{Parsing,Parse a string representation of the unit into its binary
representation}.
This requires that the string be parsable by @code{@ref{ut_parse()}}.
@item
@ref{Operations,Explicity construct the unit from subcomponent units
using unit operations}.
@end itemize
@item
@ref{Formatting,Convert a binary representation of a unit into a string} ---
enabling the printing and storing of units in a human-readable form.
@end enumerate
While the above might seem to be trivial activities, their
general availability at the time might have helped prevent
the @uref{http://en.wikipedia.org/wiki/Mars_Climate_Orbiter,
Mars Climate Orbiter} fiasco.
@anchor{unit-system}
@node Unit-Systems, Value Conversion, Why, Top
@chapter Unit-Systems
@cindex unit-system
@cindex system of units
A unit-system is a set of units that are all defined in terms of the same
set of
@cindex unit, base
@cindex base unit
base units.
In the SI system of units, for example, the base units are the
meter, kilogram, second, ampere, kelvin, mole, and candela.
(For definitions of these base units, see
@uref{http://@/physics.nist.gov/@/cuu/@/Units/@/current.html}.)
In the UDUNITS-2 package, every accessible unit belongs to one and only one
unit-system. It is not possible to convert numeric values between units
of different unit-systems. Similarly, units belonging to different
unit-systems always compare unequal.
There are several categories of operations on unit-systems:
@menu
* Obtaining:: How to obtain a unit-system.
* Extracting:: Getting a unit from a unit-system.
* Adding:: Adding new units to a unit-system.
* Prefixes:: Add new unit-prefixes to a unit-system.
* Misc:: Miscellaneous unit-system operations.
@end menu
@node Obtaining, Extracting, , Unit-Systems
@section Obtaining a Unit-System
@cindex database, unit, obtaining predefined
@cindex unit database, obtaining predefined
@cindex unit-system, obtaining predefined
@cindex units, obtaining predefined
@cindex @code{ut_read_xml()}, discussion of
Typically, you would obtain a unit-system of predefined units by reading
the default unit database using @code{@ref{ut_read_xml()}}
with a @code{NULL} pathname argument.
If this doesn't quite match your needs, then there are alternatives.
Together with the typical solution, the means for obtaining a useful
unit-system are (in order of increasing complexity):
@itemize @bullet
@item
Obtain the default unit-system using @code{@ref{ut_read_xml(),ut_read_xml}(NULL)}.
@item
Copy and customize the unit database and then
call @code{@ref{ut_read_xml()}} with the pathname of the customized
database to obtain a customized unit-system.
@item
Same as either of the above but then adding new units to the unit-system using
@code{@ref{ut_new_base_unit()}} and
@code{@ref{ut_new_dimensionless_unit()}}.
@item
Same as the above but also deriving new units using
@ref{Operations, unit operations}
and then adding them to the unit-system using
@ref{Mapping, unit mapping}.
@item
Same as the above but starting with an empty unit-system obtained from
@code{@ref{ut_new_system()}},
in which case you will definitely have to start with
@code{@ref{ut_new_base_unit()}} and
@code{@ref{ut_new_dimensionless_unit()}}.
@end itemize
You should pass every unit-system pointer to @code{@ref{ut_free_system()}}
when you no longer need the corresponding unit-system.
@anchor{ut_get_path_xml()}
@deftypefun @code{const char*} ut_get_path_xml @code{(const char* @var{path}, ut_status* status)}
Returns the pathname of the XML-formatted unit-database corresponding to
@var{path}. If @var{path} is non-@code{NULL}, then it is returned; otherwise,
if the environment variable @code{UDUNITS2_XML_PATH} is set, then its value is
returned; otherwise, the pathname of the default unit-database is returned.
The value of @code{*status} indicates which of these possibilities occurred:
@table @code
@item UT_OPEN_ARG
@var{path} is non-@code{NULL} and was returned.
@item UT_OPEN_ENV
@var{path} is @code{NULL}, the environment variable
@code{UDUNITS2_XML_PATH} is set, and its value was returned.
@item UT_OPEN_DEFAULT
@var{path} is @code{NULL}, the environment variable
@code{UDUNITS2_XML_PATH} is unset, and the pathname of the default unit-database
was returned.
@end table
@end deftypefun
@anchor{ut_read_xml()}
@deftypefun @code{ut_system*} ut_read_xml @code{(const char* @var{path})}
Reads the XML-formatted unit-database specified by @var{path}
and returns the corresponding unit-sytem.
If @var{path} is @code{NULL}, then the pathname specified by the
environment variable @code{UDUNITS2_XML_PATH} is used if set; otherwise,
the compile-time pathname of the installed, default, unit database is
used.
You should pass the returned pointer to @code{ut_free_system()} when you
no longer need the unit-system.
If an error occurs,
then this function writes an error-message using
@code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return one of the following:
@table @code
@item UT_OPEN_ARG
@var{path} is non-@code{NULL} but the file couldn't be opened.
See @code{errno} for the reason.
@item UT_OPEN_ENV
@var{path} is @code{NULL} and environment variable
@code{UDUNITS2_XML_PATH} is set but the file couldn't be opened.
See @code{errno} for the reason.
@item UT_OPEN_DEFAULT
@var{path} is @code{NULL}, environment variable
@code{UDUNITS2_XML_PATH} is unset, and the installed, default, unit
database couldn't be opened.
See @code{errno} for the reason.
@item UT_OS
Operating-system error. See @code{errno}.
@item UT_PARSE
The database file couldn't be parsed.
@end table
@end deftypefun
@anchor{ut_new_system()}
@deftypefun @code{ut_system*} ut_new_system @code{(void)}
Creates and returns a new unit-system.
On success, the unit-system will be empty
except for the dimensionless unit one.
You should pass the returned pointer to @code{ut_free_system()} when you
no longer need the unit-system.
If an error occurs,
then this function writes an error-message using
@code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return the following:
@table @code
@item UT_OS
Operating-system error. See @code{errno}.
@end table
@end deftypefun
@node Extracting, Adding, Obtaining, Unit-Systems
@section Extracting Units from a Unit-System
@strong{NOTE\:} This section covers low-level access to the indidual units of a
@ref{unit-system}.
General parsing of arbitrary unit specifications is covered in
the section @ref{Parsing}.
A @ref{unit-system} contains mappings from identifiers to units (and
vice versa).
Consequently, once you have a unit-system, you can easily
obtain a unit for which you know the name or symbol using
the function @code{@ref{ut_get_unit_by_name()}} or
@code{@ref{ut_get_unit_by_symbol()}}.
@cindex getting a unit by its name
@cindex unit, getting by name
@anchor{ut_get_unit_by_name()}
@deftypefun @code{ut_unit*} ut_get_unit_by_name @code{(const ut_system* @var{system}, const char* @var{name})}
Returns the unit to which @var{name} maps from the unit-system referenced by
@var{system} or @code{NULL} if no such unit exists.
Name comparisons are case-insensitive.
If this function returns @code{NULL}, then
@code{@ref{ut_get_status()}} will return
one of the following:
@table @code
@item UT_SUCCESS
@var{name} doesn't map to a unit of @var{system}.
@item UT_BAD_ARG
@var{system} or @var{name} is @code{NULL}.
@end table
You should pass the returned unit to @code{ut_free()} when it is no longer
needed.
@end deftypefun
@cindex getting a unit by its symbol
@cindex unit, getting by symbol
@anchor{ut_get_unit_by_symbol()}
@deftypefun @code{ut_unit*} ut_get_unit_by_symbol @code{(const ut_system* @var{system}, const char* @var{symbol})}
Returns the unit to which @var{symbol} maps from the unit-system referenced by
@var{system} or @code{NULL} if no such unit exists.
Symbol comparisons are case-sensitive.
If this function returns @code{NULL}, then
@code{@ref{ut_get_status()}} will return
one of the following:
@table @code
@item UT_SUCCESS
@var{symbol} doesn't map to a unit of @var{system}.
@item UT_BAD_ARG
@var{system} or @var{symbol} is @code{NULL}.
@end table
You should pass the returned unit to @code{ut_free()} when it is no longer
needed.
@end deftypefun
@anchor{ut_get_dimensionless_unit_one()}
@deftypefun @code{ut_unit*} ut_get_dimensionless_unit_one @code{(const ut_system* @var{system})}
Returns the dimensionless unit one of the unit-system referenced by
@var{system}.
While not necessary, the returned pointer may be passed to @code{ut_free()}
when you no longer need the unit.
If @var{system} is @code{NULL}, then this function writes an error-message
using @code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return @code{UT_BAD_ARG}.
@end deftypefun
@node Adding, Prefixes, Extracting, Unit-Systems
@section Adding Units to a Unit-System
@cindex adding units to a unit-system
@cindex unit, adding to a unit-system
@cindex unit-system, adding a unit to
If you use @code{@ref{ut_read_xml()}}, then you should not normally need to
add any new units to a unit-system.
Because you get units via their names or symbols, adding a unit to a
unit-system actually means mapping one or more identifiers (i.e., names
or symbols) to the unit.
Thereafter, you can use @code{@ref{ut_get_unit_by_name()}} and
@code{@ref{ut_get_unit_by_symbol()}} to retrieve the unit.
The mapping of identifiers to units is covered @ref{Mapping,here}.
Having said that, it is possible to create a new base or dimensionless
unit within a unit-system using @code{@ref{ut_new_base_unit()}} or
@code{@ref{ut_new_dimensionless_unit()}}---you'll just also have to map
identifiers to the newly-created unit in order to be able to retrieve
it later by identifier.
@anchor{ut_new_base_unit()}
@deftypefun @code{ut_unit*} ut_new_base_unit @code{(ut_system* @var{system})}
Creates and adds a new base-unit to the unit-system referenced by @var{system}.
This function returns the new base-unit.
You should pass the returned pointer to @code{ut_free()} when you
no longer need the unit.
If an error occurs,
then this function writes an error-message using
@code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return one of the following:
@table @code
@item UT_BAD_ARG
@var{system} is @code{NULL}.
@item UT_OS
Operating-system failure. See @code{errno}.
@end table
If you use @code{@ref{ut_read_xml()}}, then you should not normally need to call this
function.
@end deftypefun
@anchor{ut_new_dimensionless_unit()}
@deftypefun @code{ut_unit*} ut_new_dimensionless_unit @code{(ut_system* @var{system})}
Creates and adds a new dimensionless-unit to the unit-system referenced by @var{system}.
This function returns the new dimensionless-unit.
You should pass the returned pointer to @code{ut_free()} when you
no longer need the unit.
If an error occurs,
then this function writes an error-message using
@code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return one of the following:
@table @code
@item UT_BAD_ARG
@var{system} is @code{NULL}.
@item UT_OS
Operating-system failure. See @code{errno}.
@end table
If you use @code{@ref{ut_read_xml()}}, then you should not normally need to call this
function.
@end deftypefun
@node Prefixes, Misc, Adding, Unit-Systems
@section Adding Unit-Prefixes to a Unit-System
@cindex prefixes, adding to a unit-system
@cindex adding prefixes to a unit-system
@cindex unit-system, adding prefixes to a
A prefix is a word or symbol that is appended to the beginning of a word or
symbol that represents a unit in order to modify the value of that unit. For
example, the prefix ``kilo'' in the word ``kiloamperes'' changes the value
from one ampere to one-thousand amperes.
If you use @code{@ref{ut_read_xml()}}, then you should not normally need to
add any new prefixes to a unit-system.
@anchor{ut_add_name_prefix()}
@deftypefun @code{@ref{ut_status}} ut_add_name_prefix @code{(ut_system* @var{system}, const char* @var{name}, double @var{value})}
Adds the name-prefix @var{name} with the value @var{value}
to the unit-system @var{system}.
A name-prefix is something like ``mega'' or ``milli''.
Comparisons between name-prefixes are case-insensitive.
This function returns one of the following:
@table @code
@item UT_SUCCESS
Success.
@item UT_BAD_ARG
@var{system} or @var{name} is @code{NULL}, or @var{value} is @code{0}.
@item UT_EXISTS
@var{name} already maps to a different value.
@item UT_OS
Operating-system failure. See @code{errno}.
@end table
@end deftypefun
@anchor{ut_add_symbol_prefix()}
@deftypefun @code{@ref{ut_status}} ut_add_symbol_prefix @code{(ut_system* @var{system}, const char* @var{symbol}, double @var{value})}
Adds the symbol-prefix @var{symbol} with the value @var{value}
to the unit-system @var{system}.
A symbol-prefix is something like ``M'' or ``m''.
Comparisons between symbol-prefixes are case-sensitive.
This function returns one of the following:
@table @code
@item UT_SUCCESS
Success.
@item UT_BAD_ARG
@var{system} or @var{symbol} is @code{NULL}, or @var{value} is @code{0}.
@item UT_EXISTS
@var{symbol} already maps to a different value.
@item UT_OS
Operating-system failure. See @code{errno}.
@end table
@end deftypefun
@node Misc, , Prefixes, Unit-Systems
@section Miscellaneous Operations on Unit-Systems
@anchor{ut_free_system()}
@deftypefun @code{void} ut_free_system @code{(ut_system* @var{system})}
Frees the unit-system referenced by @var{system}. All unit-to-identifier and
identifier-to-unit mappings are removed. Use of @code{system} after this
function returns results in undefined behavior.
@end deftypefun
@anchor{ut_set_second()}
@deftypefun @code{@ref{ut_status}} ut_set_second @code{(const ut_unit* @var{second})}
Sets the ``second'' unit of a unit-system. This function must be called before
the first call to @code{ut_offset_by_time()} for a unit in the same unit-system.
@code{@ref{ut_read_xml()}} calls this function if the
unit-system it's reading contains a unit named ``second''.
This function returns one of the following:
@table @code
@item UT_SUCCESS
The ``second'' unit of @var{system} was successfully set.
@item UT_EXISTS
The ``second'' unit of @var{system} is set to a different unit.
@item UT_BAD_ARG
@var{second} is @code{NULL}.
@end table
@end deftypefun
@node Value Conversion, Parsing, Unit-Systems, Top
@chapter Converting Values Between Units
@cindex converting values between units
@cindex unit conversion
You can convert numeric values in one unit to equivalent values in
another, compatible unit by means of a converter.
For example
@example
#include <udunits2.h>
...
ut_unit* from = ...;
ut_unit* to = ...;
cv_converter* converter = ut_get_converter(from, to);
double fromValue = ...;
double toValue = cv_convert_double(converter, fromValue);
cv_free(converter);
@end example
The converter API is declared in the header-file @code{<converter.h>},
which is automatically included by the UDUNITS-2 header-file
(@code{<udunits2.h>}) so you don't need to explicitly include it.
@anchor{ut_are_convertible()}
@deftypefun @code{int} ut_are_convertible @code{(const ut_unit* @var{unit1}, uconst t_unit* @var{unit2})}
Indicates if numeric values in unit @var{unit1} are convertible to numeric
values in unit @var{unit2} via @ref{ut_get_converter()}.
In making this determination, dimensionless units are ignored.
This function returns a non-zero value if conversion is possible;
otherwise, @code{0} is returned and @ref{ut_get_status()} will return one
of the following:
@table @code
@item UT_BAD_ARG
@var{unit1} or @var{unit2} is @code{NULL}.
@item UT_NOT_SAME_SYSTEM
@var{unit1} and @var{unit2} belong to different @ref{unit-system}s.
@item UT_SUCCESS
Conversion between the units is not possible (e.g., @var{unit1} refers
to a meter and @var{unit2} refers to a kilogram.
@end table
@end deftypefun
@anchor{ut_get_converter()}
@deftypefun @code{cv_converter*} ut_get_converter @code{(ut_unit* const @var{from}, ut_unit* const @var{to})}
Creates and returns a converter of numeric values in the @var{from} unit
to equivalent values in the @var{to} unit.
You should pass the returned pointer to @code{cv_free()} when you
no longer need the converter.
If an error occurs,
then this function writes an error-message using
@code{@ref{ut_handle_error_message()}}
and returns @code{NULL}.
Also, @code{@ref{ut_get_status()}} will return one of the following:
@table @code
@item UT_BAD_ARG
@var{from} or @var{to} is @code{NULL}.
@item UT_NOT_SAME_SYSTEM
The units @var{from} and @var{to} don't belong to the same unit-system.
@item UT_MEANINGLESS
The units belong to the same unit-system but conversion between them is
meaningless (e.g., conversion between seconds and kilograms is meaningless).
@item UT_OS
Operating-system failure. See @code{errno}.
@end table
@end deftypefun
@anchor{cv_convert_float()}
@deftypefun @code{float} cv_convert_float @code{(const cv_converter* @var{converter}, const float @var{value})}
Converts the single floating-point value @var{value} and
returns the new value.
@end deftypefun
@anchor{cv_convert_double()}
@deftypefun @code{double} cv_convert_double @code{(const cv_converter* @var{converter}, const double @var{value})}
Converts the single double-precision value @var{value} and
returns the new value.
@end deftypefun
@anchor{cv_convert_floats()}
@deftypefun @code{float*} cv_convert_floats @code{(const cv_converter* @var{converter}, const float* @var{in}, size_t @var{count}, float* @var{out})}
Converts the @var{count} floating-point values starting at @var{in}, writing
the new values starting at @var{out} and, as a convenience,
returns @var{out}.
The input and output arrays may overlap or be identical.
@end deftypefun
@anchor{cv_convert_doubles()}
@deftypefun @code{double*} cv_convert_doubles @code{(const cv_converter* @var{converter}, const double* @var{in}, size_t @var{count}, double* @var{out})}
Converts the @var{count} double-precision values starting at @var{in}, writing
the new values starting at @var{out} and, as a convenience,
returns @var{out}.
The input and output arrays may overlap or be identical.
@end deftypefun
@anchor{cv_free()}
@deftypefun @code{void} cv_free @code{(cv_converter* @var{conv})};
Frees resources associated with the converter referenced by @var{conv}.
You should call this function when you no longer need the converter.
Use of @var{conv} upon return results in undefined behavior.
@end deftypefun
@node Parsing, Syntax, Value Conversion, Top
@chapter Parsing a String into a Unit
@cindex parsing a string into a unit
@cindex string, parsing into a unit
Here's an example of parsing a string representation of a unit into
its binary representation:
@example
#include <stdlib.h>
#include <udunits2.h>
...
ut_system* unitSystem = @ref{ut_read_xml(),ut_read_xml(NULL)};
const char* string = "kg.m2/s3";
ut_unit* watt = @ref{ut_parse(),ut_parse}(unitSystem, string, UT_ASCII);
if (watt == NULL) @{
/* Unable to parse string. */
@}
else @{
/* Life is good. */
@}
@end example
@anchor{ut_parse()}
@deftypefun @code{ut_unit*} ut_parse @code{(const ut_system* @var{system}, const char* @var{string}, ut_encoding @var{encoding})}
Returns the binary unit representation corresponding to the string unit
representation @var{string} in the character-set @var{encoding} using the
unit-system @var{system}.
@var{string} must have no leading or trailing whitespace (see
@code{@ref{ut_trim()}}).
If an error occurs, then this function returns @code{NULL} and
@code{@ref{ut_get_status()}} will return one of the following:
@table @code
@item UT_BAD_ARG
@var{system} or @var{string} is @code{NULL}.
@item UT_SYNTAX
@var{string} contained a syntax error.
@item UT_UNKNOWN
@var{string} contained an unknown identifier.
@item UT_OS
Operating-system failure. See @code{errno} for the reason.
@end table
You should pass the returned unit to @code{ut_free()} when it is no longer
needed.
@end deftypefun
@anchor{ut_trim()}
@deftypefun @code{size_t} ut_trim @code{(char* @var{string}, ut_encoding @var{encoding})}
Removes all leading and trailing whitespace from the NUL-terminated string
@var{string}. Returns @var{string}, which is modified if it contained leading
or trailing whitespace.
@end deftypefun
@node Syntax, Formatting, Parsing, Top
@chapter Unit Syntax
@cindex unit syntax
@cindex syntax, unit
For the most part, the UDUNITS-2 package follows the syntax for unit-strings
promulgated by the US National Institute for Standards and Technology (NIST).
Details, of which, can be found at @uref{http://physics.nist.gov/cuu/Units/index.html}.
The one general exception to this is the invention of a syntax for
``offset''-units (e.g., the definition of the degree Celsius is ``K @@
273.15'').
@menu
* Examples:: Examples of unit specifications
* Grammar:: Formal unit grammar
@end menu
@node Examples, Grammar, , Syntax
@section Unit Specification Examples
@cindex unit specification examples
@cindex examples, unit specification
@quotation
@multitable {Logarithmic} {(5 meter)/(30 second)} {lg(re mW)} {"lg" is base 10, "ln" is base e, and "lb" is base 2}
@headitem String Type @tab Using Names @tab Using Symbols @tab Comment
@item Simple @tab meter @tab m
@item Raised @tab meter^2 @tab m2 @tab higher precedence than multiplying or
dividing
@item Product @tab newton meter @tab N.m
@item Quotient @tab meter per second @tab m/s
@item Scaled @tab 60 second @tab 60 s
@item Prefixed @tab kilometer @tab km
@item Offset @tab kelvin from 273.15 @tab K @@ 273.15 @tab lower
precedence than multiplying or dividing
@item Logarithmic @tab lg(re milliwatt) @tab lg(re mW) @tab "lg" is base 10,
"ln" is base e, and "lb" is base 2
@item Grouped @tab (5 meter)/(30 second) @tab (5 m)/(30 s)
@end multitable
@end quotation
The above may be combined, e.g., "0.1 lg(re m/(5 s)^2) @@ 50".
You may also look at the @code{<def>} elements in @ref{Database,the
units database} to see examples of string unit specifications.
You may use the @code{@ref{Top, , udunits2, udunits2prog}} utility
to experiment with string unit specifications.
@node Grammar, , Examples, Syntax
@section Unit Grammar
@cindex unit grammar
@cindex grammar, unit
Here is the unit-syntax understood by the UDUNITS-2 package. Words printed
@emph{Thusly} indicate non-terminals; words printed THUSLY indicate terminals;
and words printed <thusly> indicate lexical elements.
@example
@emph{Unit-Spec: one of}
nothing
@emph{Shift-Spec}
@emph{Shift-Spec: one of}
@emph{Product-Spec}
@emph{Product-Spec} SHIFT REAL
@emph{Product-Spec} SHIFT INT
@emph{Product-Spec} SHIFT @emph{Timestamp}
@emph{Product-Spec: one of}
@emph{Power-Spec}
@emph{Product-Spec} @emph{Power-Spec}
@emph{Product-Spec} MULTIPLY @emph{Power-Spec}
@emph{Product-Spec} DIVIDE @emph{Power-Spec}
@emph{Power-Spec: one of}
@emph{Basic-Spec}
@emph{Basic-Spec} INT
@emph{Basic-Spec} EXPONENT
@emph{Basic-Spec} RAISE INT
@emph{Basic-Spec: one of}
ID
"(" @emph{Shift-Spec} ")"
LOGREF @emph{Product_Spec} ")"
@emph{Number}
@emph{Number: one of}
INT
REAL
@emph{Timestamp: one of}
DATE
DATE CLOCK
DATE CLOCK CLOCK
DATE CLOCK INT
DATE CLOCK ID
TIMESTAMP
TIMESTAMP INT
TIMESTAMP ID
SHIFT:
<space>* <shift_op> <space>*
<shift_op>: one of
"@@"
"after"
"from"
"since"
"ref"
REAL:
the usual floating-point format
INT:
the usual integer format
MULTIPLY: one of
"-"
"."
"*"
<space>+
<centered middot>
DIVIDE:
<space>* <divide_op> <space>*
<divide_op>: one of
per
PER
"/"
EXPONENT:
ISO-8859-9 or UTF-8 encoded exponent characters
RAISE: one of
"^"
"**"
ID: one of
<id>
"%"
"'"
"\""
degree sign
greek mu character
<id>:
<alpha> <alphanum>*
<alpha>:
[A-Za-z_]
ISO-8859-1 alphabetic characters
non-breaking space
<alphanum>: one of
<alpha>
<digit>
<digit>:
[0-9]
LOGREF:
<log> <space>* <logref>
<log>: one of
"log"
"lg"
"ln"
"lb"
<logref>:
"(" <space>* <re> ":"? <space>*
DATE:
<year> "-" <month> ("-" <day>)?
<year>:
[+-]?[0-9]@{1,4@}
<month>:
"0"?[1-9]|1[0-2]
<day>:
"0"?[1-9]|[1-2][0-9]|"30"|"31"
CLOCK:
<hour> ":" <minute> (":" <second>)?
TIMESTAMP:
<year> (<month> <day>?)? "T" <hour> (<minute> <second>?)?
<hour>:
[+-]?[0-1]?[0-9]|2[0-3]
<minute>:
[0-5]?[0-9]
<second>:
(<minute>|60) (\.[0-9]*)?
@end example
@node Formatting, Operations, Syntax, Top
@chapter Formatting a Unit into a String
@cindex formatting a unit into a string
@cindex unit, formatting into a string
@cindex string, formatting a unit into a
Use the @code{@ref{ut_format()}} function to obtain the string representation
of a binary unit.
For example, the following gets the definition of the unit "watt" in
ASCII characters using unit-symbols rather than unit-names:
@example
ut_unit* watt = ...;
char buf[128];
unsigned opts = @ref{ut_encoding,UT_ASCII} | UT_DEFINITION;
int len = @ref{ut_format(),ut_format}(watt, buf, sizeof(buf), opts);
if (len == -1) @{
/* Couldn't get string */
@}
else if (len == sizeof(buf)) @{
/* Entire buffer used: no terminating NUL */
@}
else @{
/* Have string with terminating NUL */
@}
@end example
@anchor{ut_format()}
@deftypefun @code{int} ut_format @code{(const ut_unit* @var{unit}, char* @var{buf}, size_t @var{size}, unsigned @var{opts})}
Formats the unit @var{unit} (i.e., returns its string representation)
into the buffer pointed-to by @var{buf} of size @var{size}.
The argument @var{opts} specifies how the formatting is to be done and
is a bitwise OR of a @ref{ut_encoding} value and zero or more of the following:
@table @code
@item UT_NAMES
Use unit names instead of symbols.
@item UT_DEFINITION
The formatted string should be the definition of @var{unit} in terms
of basic-units instead of stopping any expansion at the highest level
possible.
@end table
On success, this function returns either the number of bytes -- excluding the
terminating @code{NUL} -- that were written into @code{buf} or the number of
bytes that @emph{would have been written}. The difference is due to the
runtime @code{snprinf()} function that was used.
On failure, this function returns @code{-1} and @ref{ut_get_status()} will
return one of the following:
@table @code
@item UT_BAD_ARG
@var{unit} or @var{buf} is @code{NULL}, or
@var{opts} contains the bit patterns of both @code{UT_LATIN1} and
@code{UT_UTF8}.
@item UT_CANT_FORMAT
@var{unit} can't be formatted in the desired manner (e.g., @var{opts}
contains @code{UT_ASCII} but @var{unit} doesn't have an identifier in
that character-set or @var{opts} doesn't contain UT_NAMES and a necessary
symbol doesn't exist).
@end table
@end deftypefun
@node Operations, Mapping, Formatting, Top
@chapter Unit Operations
@cindex unit operations
@cindex operations, unit
You can use unit operations to construct new units, get information
about units, or compare units.
@menu
* Unary:: Operations on a single unit
* Binary:: Operations on pairs of units
@end menu
@node Unary, Binary, , Operations
@section Unary Unit Operations
@cindex unary unit operations
@anchor{ut_free()}
@deftypefun @code{void} ut_free @code{(ut_unit* @var{unit})}
Frees resources associated with @var{unit}.
You should invoke this function on every unit that you no longer need.
Use of @var{unit} upon
return from this function results in undefined behavior.