/usr/share/nexus/doc/api/napi.tex is in libnexus0-dev 4.3.2-svn1919-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 | % Copyleft (c) 1997 by Mark Koennecke at PSI, Switzerland.
%
%
% This software is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You may already have a copy of the GNU General Public License; if
% not, write to the Free Software Foundation, Inc., 675 Mass Ave,
% Cambridge, MA 02139, USA.
%
\documentclass[12pt]{article}
\usepackage[dvips]
\setlength{\oddsidemargin}{-.1in}
\setlength{\evensidemargin}{0in}
\setlength{\topmargin}{0in}
\addtolength{\topmargin}{-\headheight}
\addtolength{\topmargin}{-\headsep}
\setlength{\textheight}{8.9in}
\setlength{\textwidth}{6.2in}
\setlength{\marginparwidth}{0.5in}
\begin{document}
\title{The NeXus Application Programmer's Interface}
\author{Mark K\"onnecke\\
Labor f\"ur Neutronenstreuung\\
Paul Scherrer Institut\\
CH-5232 Villigen PSI\\
Switzerland\\
Mark.Koennecke@psi.ch \\
Przemek K\l{}osowski\\
U. of Maryland \& NIST \\
przemek.klosowski@nist.gov
}
}
\maketitle
\tableofcontents
\vskip.3in
\centerline{\large\bf Abstract}
\vskip.2in
\begin{center}
\parbox{.8\textwidth}{
There is a proposed portable data exchange format for neutron and
X-ray scattering communities, NeXus (described in a separate
publication). The present document supplements the NeXus proposal,
by defining a simplified, NeXus-compliant programming interface for
reading and writing NeXus files.
}
\end{center}
\section{Introduction}
\label{chap:intro}
This file defines an Application Programmer's Interface (API) to HDF
library as used for the NeXus data format. It encapsulates a subset of
HDF and provides some helper routines to simplify creating and reading
NeXus data files.
The API is designed to be modal; there is a hidden state that
determines which groups and datasets (Vgroups and SDSes) are open at
any given moment, and subsequent operations are implicitly performed
on these entities. This cuts down the number of parameters to pass
around in API calls, at the cost of forcing certain pre-approved {\em
mode d'emploi}. This mode d'emploi will be familiar to most: it is very
similar to navigating a directory hierarchy. In our case HDF--VGroups are
the directories, which can hold other directories and data items which are
restricted to being HDF--scientific data sets (SDS).
The API comprises the following functional groups:
\begin{enumerate}
\item General initialization and shutdown: opening and closing the file,
creating or opening an existing group or dataset, and closing them.
\item Reading and writing data and attributes to previously opened datasets.
\item Routines to obtain meta-data and to iterate over component datasets and attributes.
\item Handling of linking and group hierarchy.
\end{enumerate}
\section{Implementation}
\subsection{Data Structures}
The approach used in this version is to maintain a datastructure for each
open file. This datastructure will hold a stack of Vgroups traversed and
will thus allow stepping back and forth in the NeXus file structure. The
stack is implemented using an array. The datastructure looks like this:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap1}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ typedef struct __NexusFile {@\\
\mbox{}\verb@ int iNXID;@\\
\mbox{}\verb@ int32 iVID;@\\
\mbox{}\verb@ int32 iSID;@\\
\mbox{}\verb@ int32 iCurrentVG;@\\
\mbox{}\verb@ int32 iCurrentSDS;@\\
\mbox{}\verb@ int32 iStack[NXMAXSTACK];@\\
\mbox{}\verb@ int iStackPtr; @\\
\mbox{}\verb@ int iNDir;@\\
\mbox{}\verb@ int iCurDir;@\\
\mbox{}\verb@ int *iRefDir;@\\
\mbox{}\verb@ int *iTagDir;@\\
\mbox{}\verb@ } NexusFile, *pNexusFile;@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
The fields in more detail: \begin{itemize}
\item iNXID is a test value against memory corruption.
\item iVID is the file ID to use for the Vgroup interface.
\item iSID is the file ID to use for the SDS interface.
\item iCurrentVG is the ID of the current open Vgroup. Is 0, if there is
no Vgroup open.
\item iCurrentSDS is the ID of the current open SDS. Is 0, if there is
no SDS open.
\item iStack is the stack array.
\item iStackPtr is the pointer to the current Vgroup in iStack.
\item iNDir, iCurDir, iRefDir, iTagDir are data fields used during an
directory search with NXgetnextentry. They are:
\begin{itemize}
\item iNDir: number of directory entries.
\item iCurDir current directory entry.
\item iRefDir array of reference numbers.
\item iTagDir array of tag numbers.
\end{itemize}
\end{itemize}
The other datastructure used is NXlink. It encapsulates all information
necessary to do a link between Vgroups and SDS's. This is easy:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap2}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ typedef struct {@\\
\mbox{}\verb@ int32 iTag;@\\
\mbox{}\verb@ int32 iRef;@\\
\mbox{}\verb@ } NXlink;@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
Before diving into code, it may be helpful to highlight a few pecularities
of the HDF interface which help confuse the code. The first is, that there
is no single ID to refer to a given file. The Vgroup interface and the SDS
interface use two different ID's which have to be initialised at file
opening and used apropriatetly.
The other feature is the plethora of integer ID's associated with each
HDF--object. First there is something called a reference ID which seems to
be an ID which identifies an object within an HDF file. Coming with it there
is a tag, which denotes the type of the object. When things need to be done
to an object, HDF requires to attach or open the object. These calls usually
return another ID which can than be used furtheron. This becomes invalid
once you close the object again. So much bookeeping is needed to keep track
of all these ID's. \label{ididid}
\subsection{General initialization and shutdown}
\label{ss:gen}
The routines in this group are for opening and closing the NeXus/HDF file,
creating or opening an existing group or dataset, and closing them.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap3}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@NXhandle NXopen(char * filename, NXaccess access_method);@\\
\mbox{}\verb@NXstatus NXclose(NXhandle fileid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@NXstatus NXmakegroup (NXhandle fileid, char* Vgroup, char* NXclass);@\\
\mbox{}\verb@NXstatus NXopengroup (NXhandle fileid, char* Vgroup, char* NXclass);@\\
\mbox{}\verb@NXstatus NXclosegroup(NXhandle fileid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@NXstatus NXmakedata (NXhandle fileid, char* label, int datatype, int rank, int dim[]);@\\
\mbox{}\verb@NXstatus NXopendata (NXhandle fileid, char* label);@\\
\mbox{}\verb@NXstatus NXclosedata(NXhandle fileid);@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXopen}
NXopen opens the HDF--file filename and creates and initialises a NexusFile
structure. The returned handle is actually the pointer to this structure.
This danger of this aproach is, that somebody might try arithemetic on the
handle and thereby corrupt the system. In order to test for this the
NexusFile structure contains the NXID field which can be checked against a
predefined value.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap4}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXhandle NXopen(char *filename, NXaccess am)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pNew = NULL;@\\
\mbox{}\verb@ char pBuffer[512];@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* get memory */@\\
\mbox{}\verb@ pNew = (pNexusFile)malloc(sizeof(NexusFile));@\\
\mbox{}\verb@ if(!pNew)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData, "ERROR: no memory to create File datastructure");@\\
\mbox{}\verb@ return NULL;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ memset(pNew,0,sizeof(NexusFile));@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* start SDS interface */@\\
\mbox{}\verb@ pNew->iSID = SDstart(filename,am);@\\
\mbox{}\verb@ if(pNew->iSID <= 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot open file: %s",filename);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ free(pNew);@\\
\mbox{}\verb@ return NULL;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* otherwise we try to create the file two times which makes HDF@\\
\mbox{}\verb@ Trow up on us.@\\
\mbox{}\verb@ */@\\
\mbox{}\verb@ if(am == NXACC_CREATE)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ am = NXACC_RDWR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* start Vgroup API */@\\
\mbox{}\verb@ pNew->iVID = Hopen(filename,am,100);@\\
\mbox{}\verb@ if(pNew->iVID <= 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot open file: %s",filename);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ free(pNew);@\\
\mbox{}\verb@ return NULL;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ iRet = Vstart(pNew->iVID);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot initalise Vgroup interface");@\\
\mbox{}\verb@@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ pNew->iNXID = NXSIGNATURE;@\\
\mbox{}\verb@ pNew->iStack[0] = 0; /* root! */@\\
\mbox{}\verb@@\\
\mbox{}\verb@ return (NXhandle)pNew; @\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXclose}
NXclose closes an Nexus file and deletes all associated datastructures from
memory. The handle fileid will no longer be valid after this.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap5}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXclose(NXhandle fid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile = NULL;@\\
\mbox{}\verb@ int iRet; @\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* close links into vGroups or SDS */@\\
\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: ending access to SDS");@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* close the SDS and Vgroup API's */@\\
\mbox{}\verb@ Vend(pFile->iVID);@\\
\mbox{}\verb@ iRet = SDend(pFile->iSID);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot close SDS interface");@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@@\\
\mbox{}\verb@ iRet = Hclose(pFile->iVID);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot close HDF file");@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* release memory */@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ free(pFile);@\\
\mbox{}\verb@ return NX_OK; @\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXmakegroup}
NXmakegroup creates a new Vgroup at the current level in the Vgroup
hierarchy. The new Vgroup will have the name Vgroup and have the class
descriptor NXclass. This call does not open the new group automatically.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap6}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXmakegroup(NXhandle fid, char *name, char *class)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iNew, iRet;@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ pFile = NXIassert(fid); @\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* create and configure the group */@\\
\mbox{}\verb@ iNew = Vattach(pFile->iVID,-1,"w"); @\\
\mbox{}\verb@ if(iNew < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF could not create Vgroup");@\\
\mbox{}\verb@ return NX_ERROR; @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vsetname(iNew,name);@\\
\mbox{}\verb@ Vsetclass(iNew,class);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* insert it into the hierarchy, when apropriate */@\\
\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = Vinsert(pFile->iCurrentVG,iNew);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vdetach(iNew);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF failed to insert Vgroup");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXopengroup}
NXopengroup opens an existing Vgroup for writing and reading data to it.
This routine maintains the Vgroup stack. There are several possible
situations. The first is that we are at root level (iCurrentVG = 0). The
vGroup must be found and attatched to. Than the Stack has to be incremented.
The next situation is, that we are already in a Vgroup. Than we have to find
the new Vgroup, detach the current Vgroup and attach to the new one, thereby
incrementing the stack.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap7}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
\mbox{}\verb@ NXstatus NXopengroup(NXhandle fid, char *name, char *class)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iNew, iRef;@\\
\mbox{}\verb@ char pBuffer[256];@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ iRef = NXIFindVgroup(pFile,name,class);@\\
\mbox{}\verb@ if(iRef < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: Vgroup %s, class %s NOT found",name,class);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* are we at root level ? */@\\
\mbox{}\verb@ if(pFile->iCurrentVG == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,iRef,"w");@\\
\mbox{}\verb@ if(pFile->iCurrentVG < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot attach to vGroup %s",name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ pFile->iStackPtr++;@\\
\mbox{}\verb@ pFile->iStack[pFile->iStackPtr] = iRef;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\
\mbox{}\verb@ pFile->iStackPtr++;@\\
\mbox{}\verb@ pFile->iStack[pFile->iStackPtr] = iRef;@\\
\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,@\\
\mbox{}\verb@ pFile->iStack[pFile->iStackPtr],@\\
\mbox{}\verb@ "w");@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXclosegroup}
NXclosegroup closes an open Vgroup and travels one back in the Vgroup
hierarchy. The usual hassle with the tons of different indices again.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap8}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXclosegroup(NXhandle fid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* first catch the trivial case: we are at root and cannot get @\\
\mbox{}\verb@ deeper into a negative directory hierarchy (anti-directory)@\\
\mbox{}\verb@ */@\\
\mbox{}\verb@ if(pFile->iCurrentVG = 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else /* Sighhh. Some work to do */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* close the current VG and decrement stack */@\\
\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\
\mbox{}\verb@ pFile->iStackPtr--;@\\
\mbox{}\verb@ if(pFile->iStackPtr <= 0) /* we hit root */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pFile->iStackPtr = 0;@\\
\mbox{}\verb@ pFile->iCurrentVG = 0;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* attach to the lower Vgroup */@\\
\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,@\\
\mbox{}\verb@ pFile->iStack[pFile->iStackPtr],@\\
\mbox{}\verb@ "w");@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXmakedata}
NXmakedata creates a new scientific datset. As argument it takes the usual filehandle,
Than there is an integer denoting the datatype. This needs to be one of the
HDF defined type identifiers. Commonly used types are: DFNT\_FLOAT for 32 bit
floats, DFNT\_INT32 for 32-bit integers, DFNT\_UINT8 for unsigned bytes (or
characters). rank is the dimensionality of the data. The parameter dims is
an integer array which has rank values. Each value denotes the length of the
data in the dimensions. Note that this function does not open a dataset.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap9}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXmakedata(NXhandle fid, char *name, int datatype, int rank, @\\
\mbox{}\verb@ int dimensions[])@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iNew;@\\
\mbox{}\verb@ char pBuffer[256];@\\
\mbox{}\verb@ int i, iRet;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* do some argument checking */@\\
\mbox{}\verb@ if( (datatype != DFNT_FLOAT32) && (datatype != DFNT_FLOAT64) &&@\\
\mbox{}\verb@ (datatype != DFNT_INT8) && (datatype != DFNT_UINT8) &&@\\
\mbox{}\verb@ (datatype != DFNT_INT16) && (datatype != DFNT_UINT16) &&@\\
\mbox{}\verb@ (datatype != DFNT_INT32) && (datatype != DFNT_UINT32))@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: unknown datatype specified for SDS %s",@\\
\mbox{}\verb@ name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(rank <= 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: invalid rank specified for SDS %s",@\\
\mbox{}\verb@ name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ for(i = 0; i < rank; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ if(dimensions[i] <= 0 )@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,@\\
\mbox{}\verb@ "ERROR: invalid dimension %d, value %d given for SDS %s",@\\
\mbox{}\verb@ i,dimensions[i], name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* behave nicely, if there is still an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ SDendaccess(pFile->iCurrentSDS);@\\
\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* dataset creation */@\\
\mbox{}\verb@ iNew = SDcreate(pFile->iSID,name,datatype,rank,dimensions);@\\
\mbox{}\verb@ if(iNew < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot create SDS %s, check argumenst",@\\
\mbox{}\verb@ name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR; @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ /* link into Vgroup, if in one */@\\
\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = Vaddtagref(pFile->iCurrentVG,DFTAG_SDG,SDidtoref(iNew));@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ iRet = SDendaccess(iNew);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXopendata}
NXopendata opens a scientific data set for further manipulation, i.e. reading
and writing of data or getting information about it. The scientific dataset
must exist.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap10}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXopendata(NXhandle fid, char *name)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iNew; @\\
\mbox{}\verb@ char pBuffer[256];@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* first find the reference number of the SDS */@\\
\mbox{}\verb@ iNew = NXIFindSDS(fid,name);@\\
\mbox{}\verb@ if(iNew < 0) @\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: SDS %s not found at this level",name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* be nice: properly close the old open SDS silently if there is@\\
\mbox{}\verb@ still an SDS open.@\\
\mbox{}\verb@ */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = 1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* clear pending attribute directories first */@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* open the SDS */@\\
\mbox{}\verb@ iNew = SDreftoindex(pFile->iSID, iNew);@\\
\mbox{}\verb@ pFile->iCurrentSDS = SDselect(pFile->iSID,iNew);@\\
\mbox{}\verb@ if(pFile->iCurrentSDS < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF error opening SDS");@\\
\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXclosedata}
NXclosedata ends the access to the currently active scientific dataset.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap11}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXclosedata(NXhandle fid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\
\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open --> nothing to do");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ NXIKillDir(pFile); /* for attribute data */@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsection{Reading and writing}
\label{ss:rw}
Routines to read and write data and attributes to previously opened datasets:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap12}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@NXstatus NXgetdata(NXhandle fileid, void* data);@\\
\mbox{}\verb@NXstatus NXgetslab(NXhandle fileid, void* data, int start[], int size[]);@\\
\mbox{}\verb@NXstatus NXgetattr(NXhandle fileid, char* name, char* data, int datalen);@\\
\mbox{}\verb@@\\
\mbox{}\verb@NXstatus NXputdata(NXhandle fileid, void* data);@\\
\mbox{}\verb@NXstatus NXputslab(NXhandle fileid, void* data, int start[], int size[]);@\\
\mbox{}\verb@NXstatus NXputattr(NXhandle fileid, char* name, char* data, int datalen);@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
Please note, that all data reading and writing routines require that the
scientific dataset has been opened beforehand with NXopenadata.
\subsubsection{NXgetdata}
NXgetdata reads data from the currently open scientific data set into
data. Please note, that memory overwrite occurs if the caller has not
allocated enough memory to hold all the data available. There are functions
in the section \ref{ss:meta} which allow to inquire the data size first.
Note as well that the scientific dataset must have been opened with
NXopendata before this function can succeed. Before it can do its job,
NXgetdata has to get dimension information first.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap13}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXgetdata(NXhandle fid, void *data)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iStart[MAX_VAR_DIMS], iEnd[MAX_VAR_DIMS];@\\
\mbox{}\verb@ NXname pBuffer;@\\
\mbox{}\verb@ int32 iRank, iAtt, iType;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* check if there is an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* first read dimension information */@\\
\mbox{}\verb@ memset(iStart,0,MAX_VAR_DIMS*sizeof(int32));@\\
\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,&iRank,iEnd,&iType,&iAtt);@\\
\mbox{}\verb@ /* actually read */@\\
\mbox{}\verb@ SDreaddata(pFile->iCurrentSDS,iStart,NULL,iEnd,data);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetslab}
NXgetslab reads a subset of the data in the current scientific data set.
The start dimensions to read from are specified in iStart, the end in iEnd.
The caller is responsable for allocation enough memory for data.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap14}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXgetslab(NXhandle fid, void *data, int iStart[], int iEnd[])@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* check if there is an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* actually read */@\\
\mbox{}\verb@ SDreaddata(pFile->iCurrentSDS,iStart,NULL,iEnd,data);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetattr}
HDF has the concept of attributes. This is additional data which goes with
usually an SDS. Such attributes are used to denotes axis, units etc. The
other class of attributes are global attributes. This function reads such
attributes. If an SDS is open, it reads the attributes associated with the SDS, else
the it tries to find a global attribute. The data read is transfered to
data, but maximum datalen bytes. The caller is responsible for allocating at
least datalen bytes for data. In order to enable this scheme, NXgetattr
has to read the first into an internal temporary buffer before it copies the
data to the datat buffer provided. And discards with the temporary buffer.
Note that searching for attributes is handled differently if attributes at
global level are searched compared to searching attributes in an SDS.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap15}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXgetattr(NXhandle fid, char *name, char *data, int datalen)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iNew;@\\
\mbox{}\verb@ void *pData = NULL;@\\
\mbox{}\verb@ int32 iLen, iType, iRet;@\\
\mbox{}\verb@ char pBuffer[256];@\\
\mbox{}\verb@ NXname pNam; @\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* find attribute */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* SDS attribute */@\\
\mbox{}\verb@ iNew = SDfindattr(pFile->iCurrentSDS,name);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* global attribute */@\\
\mbox{}\verb@ iNew = SDfindattr(pFile->iSID,name);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iNew < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: attribute %s not found",name);@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* get more info, allocate temporary data space */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDattrinfo(pFile->iCurrentSDS,iNew,pNam,&iType,&iLen);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDattrinfo(pFile->iSID,iNew,pNam,&iType,&iLen);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: HDF could not read attribute info");@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ iLen = iLen*DFKNTsize(iType); @\\
\mbox{}\verb@ pData = (void *)malloc(iLen);@\\
\mbox{}\verb@ if(!pData)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: allocating memory in NXgetattr");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ memset(pData,0,iLen);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* finally read the data */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDreadattr(pFile->iCurrentSDS,iNew,pData);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDreadattr(pFile->iSID,iNew,pData);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pBuffer,"ERROR: HDF could not read attribute data");@\\
\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* copy data to caller */@\\
\mbox{}\verb@ memset(data,0,datalen);@\\
\mbox{}\verb@ if(datalen < iLen)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iLen = datalen - 1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ memcpy(data,pData,iLen);@\\
\mbox{}\verb@ free(pData);@\\
\mbox{}\verb@ return NX_OK; @\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXputdata}
NXputdata copies data into the currently open scientific data set in the
HDF file.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap16}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXputdata(NXhandle fid, void *data)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int32 iStart[MAX_VAR_DIMS], iEnd[MAX_VAR_DIMS], iStride[MAX_VAR_DIMS];@\\
\mbox{}\verb@ NXname pBuffer;@\\
\mbox{}\verb@ int32 iRank, iAtt, iType, iRet, i;@\\
\mbox{}\verb@ char pError[512];@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* check if there is an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ @\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* first read dimension information */@\\
\mbox{}\verb@ memset(iStart,0,MAX_VAR_DIMS*sizeof(int32));@\\
\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,&iRank,iEnd,&iType,&iAtt);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* initialise stride to 1 */@\\
\mbox{}\verb@ for(i = 0; i < iRank; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iStride[i] = 1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* actually write */@\\
\mbox{}\verb@ iRet = SDwritedata(pFile->iCurrentSDS,iStart,iStride,iEnd,data);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sprintf(pError,"ERROR: failure to write data to %s",pBuffer);@\\
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
\mbox{}\verb@ return NX_ERROR; @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXputslab}
NXputslab writes an subset of data as specified by iStart to iEnd into the
currently open SDS.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap17}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXputslab(NXhandle fid, void *data, int iStart[], int iEnd[])@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@ int iStride[MAX_VAR_DIMS], i;@\\
\mbox{}\verb@ @\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* check if there is an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* initialise stride to 1 */@\\
\mbox{}\verb@ for(i = 0; i < MAX_VAR_DIMS; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iStride[i] = 1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* actually write */@\\
\mbox{}\verb@ iRet = SDwritedata(pFile->iCurrentSDS,iStart,iStride,iEnd,data);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: writing slab failed");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXputattr}
Nxputattr puts an attribute into an Nexus file.If an SDS is open, the SDS
will get the attribute. If not, a global attribute will be generated.
Attributes are name = value pairs.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap18}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXputattr(NXhandle fid, char *name, char *data, int datalen)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* SDS attribute */@\\
\mbox{}\verb@ iRet = SDsetattr(pFile->iCurrentSDS,name,DFNT_UINT8,@\\
\mbox{}\verb@ datalen,data);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* global attribute */@\\
\mbox{}\verb@ iRet = SDsetattr(pFile->iSID,name,DFNT_UINT8,@\\
\mbox{}\verb@ datalen, data);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDf failed to store attribute ");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsection{Meta-data}
\label{ss:meta}
Routines to obtain meta-data and to iterate over component datasets and attributes.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap19}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@NXstatus NXgetinfo (NXhandle fileid, int* rank, int dimension[], int* datatype);@\\
\mbox{}\verb@NXstatus NXgetnextentry (NXhandle fileid, NXname name, NXname class, int* datatype);@\\
\mbox{}\verb@NXstatus NXgetnextattr(NXhandle fileid, NXname pName, int *iLength, int *iType);@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetinfo}
NXgetinfo gets information about an SDS. rank is the dimesionality of the
data, dimension will contain the size of the data in each dimension and
datatype results to one of the HDF--datatypes. The SDS has to be open in
order for this routine to work.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap20}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXgetinfo(NXhandle fid, int *rank,int dimension[], int *iType)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ NXname pBuffer;@\\
\mbox{}\verb@ int32 iAtt;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* check if there is an SDS open */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* read information */@\\
\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,rank,dimension,iType,&iAtt);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetnextentry}
NXgetnextentry implements a directory search facility on the current Vgroup
level. The first call will initialize Vgroup searching facilities and return
information on the first data item in the list. Subsequent calls will yield
information about the next item in the Vgroup. If the end of the list is
reached, NXgetentry will return NX\_EOD. Before, the usual NX\_ERROR or NX\_OK
are returned. Information returned is different for each type of data. For
Vgroups the name and class of the Vgroup will be returned, iType will be 0.
For scientific data sets, the name field will be the name, class will be SDS
and iType will denote the number type of the scientific data set. For types
not known to Nexus (but to HDF) both name and class will be set to
"UNKNOWN".
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap21}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ int NXgetnextentry(NXhandle fid, NXname name, NXname class, int *datatype)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int iRet; @\\
\mbox{}\verb@ int32 iTemp, iD1, iD2, iA;@\\
\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* first case to check for: no directory entry */@\\
\mbox{}\verb@ if(pFile->iRefDir == NULL)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = NXIInitDir(pFile);@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData, @\\
\mbox{}\verb@ "ERROR: no memory to store directory info");@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* next case: end of directory */@\\
\mbox{}\verb@ if(pFile->iCurDir >= pFile->iNDir)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ return NX_EOD;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* next case: we have data! suppy it and increment counter */@\\
\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iTemp = Vattach(pFile->iVID,pFile->iRefDir[pFile->iCurDir],@\\
\mbox{}\verb@ "r");@\\
\mbox{}\verb@ if(iTemp < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot attach to Vgroup");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vgetname(iTemp,name);@\\
\mbox{}\verb@ Vgetclass(iTemp,class);@\\
\mbox{}\verb@ *datatype = DFTAG_VG;@\\
\mbox{}\verb@ pFile->iCurDir++;@\\
\mbox{}\verb@ Vdetach(iTemp);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else /* in Vgroup */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ if(pFile->iTagDir[pFile->iCurDir] == DFTAG_VG) /* Vgroup */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iTemp = Vattach(pFile->iVID,pFile->iRefDir[pFile->iCurDir],@\\
\mbox{}\verb@ "r");@\\
\mbox{}\verb@ if(iTemp < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot attach to Vgroup");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vgetname(iTemp,name);@\\
\mbox{}\verb@ Vgetclass(iTemp,class);@\\
\mbox{}\verb@ *datatype = DFTAG_VG;@\\
\mbox{}\verb@ pFile->iCurDir++;@\\
\mbox{}\verb@ Vdetach(iTemp);@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else if( (pFile->iTagDir[pFile->iCurDir] == DFTAG_SDG) ||@\\
\mbox{}\verb@ (pFile->iTagDir[pFile->iCurDir] == DFTAG_NDG) )@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iTemp = SDreftoindex(pFile->iSID, @\\
\mbox{}\verb@ pFile->iRefDir[pFile->iCurDir]);@\\
\mbox{}\verb@ iTemp = SDselect(pFile->iSID,iTemp);@\\
\mbox{}\verb@ SDgetinfo(iTemp,name,&iA,iDim,&iD1, &iD2);@\\
\mbox{}\verb@ strcpy(class,"SDS");@\\
\mbox{}\verb@ *datatype = iD1;@\\
\mbox{}\verb@ SDendaccess(iTemp);@\\
\mbox{}\verb@ pFile->iCurDir++;@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else /* unidentified */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ strcpy(name,"UNKNOWN");@\\
\mbox{}\verb@ strcpy(class,"UNKNOWN");@\\
\mbox{}\verb@ pFile->iCurDir++;@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_ERROR; /* not reached */@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetnextattr}
NXgetnextattr works very much like NXgetnextentry except, that it works on
SDS attributes and not on Vgroup entries. This function allows to scan the
names of attributes available. iLength will be filled with the length of the
attributes data in byte. iType will be filled with the HDF type of the
attribute. Be warned: this routine returns global attributes when no SDS is
currently open.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap22}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
\mbox{}\verb@ NXstatus NXgetnextattr(NXhandle fileid, NXname pName, @\\
\mbox{}\verb@ int *iLength, int *iType)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@ int32 iPType, iCount;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fileid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* first check if we have to start a new attribute search */@\\
\mbox{}\verb@ if(pFile->iNDir == 0) @\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = NXIInitAttDir(pFile);@\\
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* are we done ? */@\\
\mbox{}\verb@ if(pFile->iCurDir >= pFile->iNDir)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIKillDir(pFile);@\\
\mbox{}\verb@ return NX_EOD;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* well, there must be data to copy */@\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0) /* global attribute */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDattrinfo(pFile->iSID,pFile->iCurDir, pName, &iPType,&iCount); @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDattrinfo(pFile->iCurrentSDS,pFile->iCurDir,@\\
\mbox{}\verb@ pName, &iPType,&iCount);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot read attribute info");@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ *iLength = iCount*DFKNTsize(iPType);@\\
\mbox{}\verb@ *iType = iPType;@\\
\mbox{}\verb@ pFile->iCurDir++;@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsection{ Handling of linking and group hierarchy}
\label{ss:link}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap23}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@NXlink NXgetgroupID(NXhandle fileid);@\\
\mbox{}\verb@NXlink NXgetdataID(NXhandle fileid);@\\
\mbox{}\verb@NXstatus NXmakelink(NXhandle fileid, NXlink link);@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{ NXgetgroupID}
NXgetgroupID retrieves the ID and tag of the currently open
Vgroup in an NXlink strcuture. In case of an error the iTag field of this
structure will contain NX\_ERROR.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap24}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXlink NXgetgroupID(NXhandle fileid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ NXlink sRes;@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ pFile = NXIassert(fileid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(pFile->iCurrentVG == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\
\mbox{}\verb@ return sRes;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sRes.iTag = DFTAG_VG;@\\
\mbox{}\verb@ sRes.iRef = pFile->iCurrentVG;@\\
\mbox{}\verb@ return sRes;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ /* not reached */@\\
\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\
\mbox{}\verb@ return sRes;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{NXgetdataID}
NXgetdataID retrieves the tag and reference number of the current data
object. Returns NX\_ERROR if none is open.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap25}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXlink NXgetdataID(NXhandle fid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@ NXlink sRes;@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\
\mbox{}\verb@ return sRes;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ sRes.iTag = DFTAG_SDS;@\\
\mbox{}\verb@ sRes.iRef = SDidtoref(pFile->iCurrentSDS);@\\
\mbox{}\verb@ return sRes;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\
\mbox{}\verb@ return sRes; /* not reached */@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{ NXlink}
NXlink links a Vgroup or SDS into a Vgroup.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap26}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ NXstatus NXmakelink(NXhandle fid, NXlink sLink)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pFile;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level, can not link here */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(sLink.iTag == DFTAG_VG)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vinsert(pFile->iCurrentVG,sLink.iRef);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else @\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vaddtagref(pFile->iCurrentVG, sLink.iTag,sLink.iRef);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsection{Internal routines}
There are a couple of internal Nexus API routines which are declared
static and are not visible outside of the module. First a few
defines.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap27}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@#include <stdlib.h>@\\
\mbox{}\verb@#include <assert.h>@\\
\mbox{}\verb@#include <string.h>@\\
\mbox{}\verb@#include "fortify.h"@\\
\mbox{}\verb@#include "napi.h"@\\
\mbox{}\verb@@\\
\mbox{}\verb@#define NXMAXSTACK 50@\\
\mbox{}\verb@#define NXSIGNATURE 959697@\\
\mbox{}\verb@@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
MAXSTACK denotes the maximum depth of Vgroup stacking permissible. If there
are problems, feel free to increase this value and recompile. 50 is probably
fairly generous.
NXSIGNATURE is just the signature which the Nexus API will check for on
handles in order to prevent against tampering with the handles.
NXMAXNAME is the number of characters permitted for names and Vgroup names.
The internal function NXIassert will convert a filehandle to a pointer
to a NexusFile datastructure. Furthermore, it will check the signature and
throw an assertion, when the signature does not match.
\subsubsection{NX error handling}
As each piece of non trivial software the Nexus API needs a error handling
policy. The policy implemented is as follows: The NX routines terminate when
an invalid NXhandle has been specified. This is a serious programmer error.
In any other case the NX routines are meant to complain, recover and present
an NX-ERROR return to the higher level code. That code is than responsible
to deal with the problem. The problem left is error reporting. This is done
througout the code by a call to NXIReportError. This function takes as first
parameter a pointer to void and as next parameter the string with the
complaint. The default implementation of NXIReportError will print to
stdout. However, there are environments where this strategy is not feasible
because stdout is supported only in a very strange way. Think about
operating system like MS-Windows, MAC-OS (going to die anyway) or other
windowing systems. In order to cater for this there is an inofficial support
function which allows to set both a pointer to a datastructure and a new
function for error reporting. This is called NXMSetError.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap28}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
\mbox{}\verb@ static void NXNXNXReportError(void *pData, char *string)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ printf("%s \n",string);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
\mbox{}\verb@ static void *NXpData = NULL;@\\
\mbox{}\verb@ static void (*NXIReportError)(void *pData, char *string) =@\\
\mbox{}\verb@ NXNXNXReportError;@\\
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
\mbox{}\verb@ void NXMSetError(void *pData, void (*NewError)(void *pD, char *text))@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXpData = pData;@\\
\mbox{}\verb@ NXIReportError = NewError;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap29}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*--------------------------------------------------------------------*/@\\
\mbox{}\verb@ static pNexusFile NXIassert(NXhandle fid)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile pRes;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ assert(fid);@\\
\mbox{}\verb@ pRes = (pNexusFile)fid;@\\
\mbox{}\verb@ assert(pRes->iNXID == NXSIGNATURE);@\\
\mbox{}\verb@ return pRes;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{ Object finding dunctions}
Routines for finding objects in an HDF file have to cope with two quirks in
the HDF interface. The first is that the root level is no Vgroup. This
implies that the root level is searched for objects using different routines
than searching for objects in a Vgroup. The last one uses, of course, Vgroup
interface routines.
Finding routines have to cope with the plethora of different integer
ID's for any given HDF object. See \ref{ididid} for more details.
NXIFindVgroup searches the current Vgroup level in the file for the
occurence of a Vgroup with a specified name and of a specified class. If no
suitable Vgroup can be found NIXFinfVgroup returns -1, else the ID of the
Vgroup.
NXIFindVgroup has to cope with the plethora of different integer
ID's for any give Vgroup. There is the Vgroup ID, than there is the
reference number which can be obtained by Vgettagref and which can refer to
any object in the HDF file. Additionally there is a Tag which denotes the
type of the object.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap30}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
\mbox{}\verb@ static int32 NXIFindVgroup(pNexusFile pFile, char *name, char *class)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ int32 iNew, iRef, iTag;@\\
\mbox{}\verb@ int iN, i;@\\
\mbox{}\verb@ int32 *pArray = NULL;@\\
\mbox{}\verb@ NXname pText;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ assert(pFile);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* get the number and ID's of all lone Vgroups in the file */@\\
\mbox{}\verb@ iN = Vlone(pFile->iVID,NULL,0);@\\
\mbox{}\verb@ pArray = (int32 *)malloc(iN*sizeof(int32));@\\
\mbox{}\verb@ if(!pArray)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIFindVgroup");@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vlone(pFile->iVID,pArray,iN);@\\
\mbox{}\verb@ @\\
\mbox{}\verb@ /* loop and check */@\\
\mbox{}\verb@ for(i = 0; i < iN; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iNew = Vattach(pFile->iVID,pArray[i],"r");@\\
\mbox{}\verb@ Vgetname(iNew, pText);@\\
\mbox{}\verb@ if(strcmp(pText,name) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vgetclass(iNew,pText);@\\
\mbox{}\verb@ if(strcmp(pText,class) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* found !*/@\\
\mbox{}\verb@ Vdetach(iNew);@\\
\mbox{}\verb@ iNew = pArray[i];@\\
\mbox{}\verb@ free(pArray);@\\
\mbox{}\verb@ return iNew;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vdetach(iNew);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ /* nothing found */@\\
\mbox{}\verb@ free(pArray); @\\
\mbox{}\verb@ return -1; @\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ else /* case in Vgroup */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iN = Vntagrefs(pFile->iCurrentVG);@\\
\mbox{}\verb@ for(i = 0; i < iN; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vgettagref(pFile->iCurrentVG,i,&iTag, &iRef);@\\
\mbox{}\verb@ if(iTag == DFTAG_VG)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iNew = Vattach(pFile->iVID,iRef,"r");@\\
\mbox{}\verb@ Vgetname(iNew, pText);@\\
\mbox{}\verb@ if(strcmp(pText,name) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vgetclass(iNew,pText);@\\
\mbox{}\verb@ if(strcmp(pText,class) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* found !*/@\\
\mbox{}\verb@ Vdetach(iNew);@\\
\mbox{}\verb@ return iRef;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vdetach(iNew);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ } /* end for */ @\\
\mbox{}\verb@ } /* end else */ @\\
\mbox{}\verb@ /* not found */@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ } @\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
NXIFindSDS searches the current Vgroup level for an SDS name. It returns
the reference ID of the SDS when found and -1 when no SDS of this name can
be found on this level.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap31}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ static int32 NXIFindSDS(NXhandle fid, char *name)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ pNexusFile self;@\\
\mbox{}\verb@ int32 iNew, iRet, iTag, iRef;@\\
\mbox{}\verb@ int32 i, iN, iA, iD1, iD2;@\\
\mbox{}\verb@ NXname pNam;@\\
\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\
\mbox{}\verb@@\\
\mbox{}\verb@ self = NXIassert(fid);@\\
\mbox{}\verb@@\\
\mbox{}\verb@ /* root level search */@\\
\mbox{}\verb@ if(self->iCurrentVG == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ i = SDfileinfo(self->iSID,&iN,&iA);@\\
\mbox{}\verb@ if(i < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData, "ERROR: failure to read file information");@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ for(i = 0; i < iN; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iNew = SDselect(self->iSID,i);@\\
\mbox{}\verb@ SDgetinfo(iNew,pNam,&iA,iDim,&iD2, &iD2);@\\
\mbox{}\verb@ if(strcmp(pNam,name) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDidtoref(iNew);@\\
\mbox{}\verb@ SDendaccess(iNew);@\\
\mbox{}\verb@ return iRet;@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ SDendaccess(iNew);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ /* not found */@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }/* end root level */@\\
\mbox{}\verb@ else /* search in a Vgroup */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iN = Vntagrefs(self->iCurrentVG);@\\
\mbox{}\verb@ for(i = 0; i < iN; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vgettagref(self->iCurrentVG,i,&iTag, &iRef);@\\
\mbox{}\verb@ if( (iTag == DFTAG_SDG) || (iTag == DFTAG_NDG) || @\\
\mbox{}\verb@ (iTag == DFTAG_SDS) )@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iNew = SDreftoindex(self->iSID, iRef);@\\
\mbox{}\verb@ iNew = SDselect(self->iSID,iNew);@\\
\mbox{}\verb@ SDgetinfo(iNew,pNam,&iA,iDim,&iD2, &iD2);@\\
\mbox{}\verb@ if(strcmp(pNam,name) == 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ SDendaccess(iNew);@\\
\mbox{}\verb@ return iRef;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ SDendaccess(iNew);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ } /* end for */ @\\
\mbox{}\verb@ } /* end Vgroup */@\\
\mbox{}\verb@ /* we get here, only if nothing found */@\\
\mbox{}\verb@ return -1; @\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\subsubsection{Helper routines for directory search}
NXIInitDir initialises the directory data fields in the Nexus File structure
for a subsequent directory request. Please note, that at root level only
Vgroups will be searched. When searching SDS's at root level, all SDS's in
the whole
file seem to be returned.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap32}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ static int NXIInitDir(pNexusFile self)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ int i;@\\
\mbox{}\verb@ int32 iTag, iRef;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ if(self->iCurrentVG == 0) /* root level */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* get the number and ID's of all lone Vgroups in the file */@\\
\mbox{}\verb@ self->iNDir = Vlone(self->iVID,NULL,0);@\\
\mbox{}\verb@ self->iRefDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\
\mbox{}\verb@ if(!self->iRefDir)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIInitDir");@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ Vlone(self->iVID,self->iRefDir,self->iNDir);@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ /* Vgroup level */@\\
\mbox{}\verb@ self->iNDir = Vntagrefs(self->iCurrentVG);@\\
\mbox{}\verb@ self->iRefDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\
\mbox{}\verb@ self->iTagDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\
\mbox{}\verb@ if( (!self->iRefDir) || (!self->iTagDir))@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIInitDir");@\\
\mbox{}\verb@ return -1;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ for(i = 0; i < self->iNDir; i++)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ Vgettagref(self->iCurrentVG,i,&iTag, &iRef);@\\
\mbox{}\verb@ self->iRefDir[i] = iRef;@\\
\mbox{}\verb@ self->iTagDir[i] = iTag;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ } @\\
\mbox{}\verb@ self->iCurDir = 0;@\\
\mbox{}\verb@ return 1;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
NXIKillDir removes all data associated with a directory search from
memory.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap33}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@ static void NXIKillDir(pNexusFile self)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ if(self->iRefDir)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ free(self->iRefDir);@\\
\mbox{}\verb@ self->iRefDir = NULL;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(self->iTagDir)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ free(self->iTagDir);@\\
\mbox{}\verb@ self->iTagDir = NULL;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ self->iCurDir = 0;@\\
\mbox{}\verb@ self->iNDir = 0;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
NXIInitAttDir will initialise the counters for reading either SDS or global
attribute data.
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap34}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
\mbox{}\verb@ static int NXIInitAttDir(pNexusFile pFile)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ int iRet;@\\
\mbox{}\verb@ int32 iData, iAtt, iRank, iType;@\\
\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\
\mbox{}\verb@ NXname pNam;@\\
\mbox{}\verb@@\\
\mbox{}\verb@ pFile->iCurDir = 0;@\\
\mbox{}\verb@ if(pFile->iCurrentSDS != 0) /* SDS level */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDgetinfo(pFile->iCurrentSDS,pNam, &iRank, iDim,&iType, @\\
\mbox{}\verb@ &iAtt); @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ else /* global level */@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ iRet = SDfileinfo(pFile->iSID,&iData,&iAtt); @\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ if(iRet < 0)@\\
\mbox{}\verb@ {@\\
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot read attribute numbers");@\\
\mbox{}\verb@ pFile->iNDir = 0;@\\
\mbox{}\verb@ return NX_ERROR;@\\
\mbox{}\verb@ }@\\
\mbox{}\verb@ pFile->iNDir = iAtt;@\\
\mbox{}\verb@ return NX_OK;@\\
\mbox{}\verb@ }@\\
\end{list}
\vspace{-1ex}
\footnotesize\addtolength{\baselineskip}{-1ex}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap35}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
\mbox{}\verb@ Nexus API header file@\\
\mbox{}\verb@@\\
\mbox{}\verb@ copyleft: Mark Koennecke, March 1997 at LNS,PSI, Switzerland@\\
\mbox{}\verb@ Przemek Klosowski, U. of Maryland & NIST, USA @\\
\mbox{}\verb@@\\
\mbox{}\verb@ No warranties of any kind taken.@\\
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef NEXUSAPI@\\
\mbox{}\verb@#define NEXUSAPI@\\
\mbox{}\verb@@\\
\mbox{}\verb@#include <mfhdf.h>@\\
\mbox{}\verb@@\\
\mbox{}\verb@typedef enum {NXACC_READ = DFACC_READ, @\\
\mbox{}\verb@ NXACC_RDWR = DFACC_RDWR, @\\
\mbox{}\verb@ NXACC_CREATE = DFACC_CREATE } NXaccess;@\\
\mbox{}\verb@typedef void * NXhandle;@\\
\mbox{}\verb@typedef int NXstatus;@\\
\mbox{}\verb@typedef char NXname[VGNAMELENMAX];@\\
\mbox{}\verb@@\\
\mbox{}\verb@#define NX_OK 1@\\
\mbox{}\verb@#define NX_ERROR 0@\\
\mbox{}\verb@#define NX_EOD -1@\\
\mbox{}\verb@/*-------------------------------------------------------------------------@\\
\mbox{}\verb@ HDF Datatype values for datatype parameters @\\
\mbox{}\verb@ in the Nexus API@\\
\mbox{}\verb@@\\
\mbox{}\verb@ DFNT_FLOAT32 32 bit float@\\
\mbox{}\verb@ DFNT_FLOAT64 64 nit float == double@\\
\mbox{}\verb@ DFNT_INT8 8 bit integer ==char, byte@\\
\mbox{}\verb@ DFNT_UINT8 8 bit unsigned integer@\\
\mbox{}\verb@ DFNT_INT16 16 bit integer@\\
\mbox{}\verb@ DFNT_UINT16 16 bit unsigned integer@\\
\mbox{}\verb@ DFNT_INT32 32 bit integer@\\
\mbox{}\verb@ DFNT_UINT32 32 bit unsigned integer@\\
\mbox{}\verb@@\\
\mbox{}\verb@ This list is a edited version of the one found in the HDF header file@\\
\mbox{}\verb@ htndefs.h. That source will always be the real reference, this is@\\
\mbox{}\verb@ documented here for your convenience.@\\
\mbox{}\verb@--------------------------------------------------------------------------*/ @\\
\mbox{}\verb@@\\
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
\mbox{}\verb@ A non Nexus standars function to set an error handler @\\
\mbox{}\verb@*/@\\
\mbox{}\verb@ void NXMSetError(void *pData, void (*ErrFunc)(void *pD, char *text));@\\
\mbox{}\verb@@\\
\mbox{}\verb@#endif@\\
\mbox{}\verb@@\\
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap36}
\vspace{-1ex}
\begin{list}{}{} \item
\mbox{}\verb@@\\
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
\mbox{}\verb@ Nexus API implementation file.@\\
\mbox{}\verb@@\\
\mbox{}\verb@ For documentation see the Napi.tex file which comes with this @\\
\mbox{}\verb@ distribution.@\\
\mbox{}\verb@@\\
\mbox{}\verb@ copyleft: Mark Koennecke@\\
\mbox{}\verb@ Labor fuer Neutronenstreuung@\\
\mbox{}\verb@ Paul Scherrer Institut@\\
\mbox{}\verb@ CH-5232 Villigen-PSI@\\
\mbox{}\verb@ Switzerland@\\
\mbox{}\verb@ Mark.Koenencke@{\tt @}\verb@psi.ch@\\
\mbox{}\verb@ Przemek Klosowski@\\
\mbox{}\verb@ U. of Maryland & NIST @\\
\mbox{}\verb@ przemek.klosowski@{\tt @}\verb@nist.gov @\\
\mbox{}\verb@@\\
\mbox{}\verb@ no warranties of any kind, whether explicit or implied, taken.@\\
\mbox{}\verb@ Distributed under the GNU copyleft license as documented elsewhere.@\\
\mbox{}\verb@@\\
\mbox{}\verb@ March 1997@\\
\mbox{}\verb@@\\
\mbox{}\verb@ Version: 1.0@\\
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
\end{list}
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
\end{document}
|