cbf.c

Go to the documentation of this file.
00001 /**********************************************************************
00002  * cbf -- cbflib API functions                                        *
00003  *                                                                    *
00004  * Version 0.6 13 January 1999                                        *
00005  *                                                                    *
00006  *            Paul Ellis (ellis@ssrl.slac.stanford.edu) and           *
00007  *         Herbert J. Bernstein (yaya@bernstein-plus-sons.com)        *
00008  **********************************************************************/
00009   
00010 /**********************************************************************
00011  *                               NOTICE                               *
00012  * Creative endeavors depend on the lively exchange of ideas. There   *
00013  * are laws and customs which establish rights and responsibilities   *
00014  * for authors and the users of what authors create.  This notice     *
00015  * is not intended to prevent you from using the software and         *
00016  * documents in this package, but to ensure that there are no         *
00017  * misunderstandings about terms and conditions of such use.          *
00018  *                                                                    *
00019  * Please read the following notice carefully.  If you do not         *
00020  * understand any portion of this notice, please seek appropriate     *
00021  * professional legal advice before making use of the software and    *
00022  * documents included in this software package.  In addition to       *
00023  * whatever other steps you may be obliged to take to respect the     *
00024  * intellectual property rights of the various parties involved, if   *
00025  * you do make use of the software and documents in this package,     *
00026  * please give credit where credit is due by citing this package,     *
00027  * its authors and the URL or other source from which you obtained    *
00028  * it, or equivalent primary references in the literature with the    *
00029  * same authors.                                                      *
00030  *                                                                    *
00031  * Some of the software and documents included within this software   *
00032  * package are the intellectual property of various parties, and      *
00033  * placement in this package does not in any way imply that any       *
00034  * such rights have in any way been waived or diminished.             *
00035  *                                                                    *
00036  * With respect to any software or documents for which a copyright    *
00037  * exists, ALL RIGHTS ARE RESERVED TO THE OWNERS OF SUCH COPYRIGHT.   *
00038  *                                                                    *
00039  * Even though the authors of the various documents and software      *
00040  * found here have made a good faith effort to ensure that the        *
00041  * documents are correct and that the software performs according     *
00042  * to its documentation, and we would greatly appreciate hearing of   *
00043  * any problems you may encounter, the programs and documents any     *
00044  * files created by the programs are provided **AS IS** without any   *
00045  * warranty as to correctness, merchantability or fitness for any     *
00046  * particular or general use.                                         *
00047  *                                                                    *
00048  * THE RESPONSIBILITY FOR ANY ADVERSE CONSEQUENCES FROM THE USE OF    *
00049  * PROGRAMS OR DOCUMENTS OR ANY FILE OR FILES CREATED BY USE OF THE   *
00050  * PROGRAMS OR DOCUMENTS LIES SOLELY WITH THE USERS OF THE PROGRAMS   *
00051  * OR DOCUMENTS OR FILE OR FILES AND NOT WITH AUTHORS OF THE          *
00052  * PROGRAMS OR DOCUMENTS.                                             *
00053  **********************************************************************/
00054  
00055 /**********************************************************************
00056  *                          The IUCr Policy                           *
00057  *                                 on                                 *
00058  *     the Use of the Crystallographic Information File (CIF)         *
00059  *                                                                    *
00060  * The Crystallographic Information File (Hall, Allen & Brown,        *
00061  * 1991) is, as of January 1992, the recommended method for           *
00062  * submitting publications to Acta Crystallographica Section C. The   *
00063  * International Union of Crystallography holds the Copyright on      *
00064  * the CIF, and has applied for Patents on the STAR File syntax       *
00065  * which is the basis for the CIF format.                             *
00066  *                                                                    *
00067  * It is a principal objective of the IUCr to promote the use of      *
00068  * CIF for the exchange and storage of scientific data. The IUCr's    *
00069  * sponsorship of the CIF development was motivated by its            *
00070  * responsibility to its scientific journals, which set the           *
00071  * standards in crystallographic publishing. The IUCr intends that    *
00072  * CIFs will be used increasingly for electronic submission of        *
00073  * manuscripts to these journals in future. The IUCr recognises       *
00074  * that, if the CIF and the STAR File are to be adopted as a means    *
00075  * for universal data exchange, the syntax of these files must be     *
00076  * strictly and uniformly adhered to. Even small deviations from      *
00077  * the syntax would ultimately cause the demise of the universal      *
00078  * file concept. Through its Copyrights and Patents the IUCr has      *
00079  * taken the steps needed to ensure strict conformance with this      *
00080  * syntax.                                                            *
00081  *                                                                    *
00082  * The IUCr policy on the use of the CIF and STAR File processes is   *
00083  * as follows:                                                        *
00084  * _________________________________________________________________  *
00085  *                                                                    *
00086  *  * 1 CIFs and STAR Files may be generated, stored or transmitted,  *
00087  *    without permission or charge, provided their purpose is not     *
00088  *    specifically for profit or commercial gain, and provided that   *
00089  *    the published syntax is strictly adhered to.                    *
00090  *  * 2 Computer software may be developed for use with CIFs or STAR  *
00091  *    files, without permission or charge, provided it is distributed *
00092  *    in the public domain. This condition also applies to software   *
00093  *    for which a charge is made, provided that its primary function  *
00094  *    is for use with files that satisfy condition 1 and that it is   *
00095  *    distributed as a minor component of a larger package of         *
00096  *    software.                                                       *
00097  *  * 3 Permission will be granted for the use of CIFs and STAR Files *
00098  *    for specific commercial purposes (such as databases or network  *
00099  *    exchange processes), and for the distribution of commercial     *
00100  *    CIF/STAR software, on written application to the IUCr Executive *
00101  *    Secretary, 2 Abbey Square, Chester CH1 2HU, England. The        *
00102  *    nature, terms and duration of the licences granted will be      *
00103  *    determined by the IUCr Executive and Finance Committees.        *
00104  *                                                                    *
00105  * _________________________________________________________________  *
00106  *                                                                    *
00107  * In summary, the IUCr wishes to promote the use of the STAR File    *
00108  * concepts as a standard universal data file. It will insist on      *
00109  * strict compliance with the published syntax for all                *
00110  * applications. To assist with this compliance, the IUCr provides    *
00111  * public domain software for checking the logical integrity of a     *
00112  * CIF, and for validating the data name definitions contained        *
00113  * within a CIF. Detailed information on this software, and the       *
00114  * associated dictionaries, may be obtained from the IUCr Office at   *
00115  * 5 Abbey Square, Chester CH1 2HU, England.                          *
00116  **********************************************************************/
00117 
00118 #ifdef __cplusplus
00119 
00120 extern "C" {
00121 
00122 #endif
00123 
00124 #include "cbf.h"
00125 #include "cbf_alloc.h"
00126 #include "cbf_binary.h"
00127 #include "cbf_write.h"
00128 
00129 #include <stdlib.h>
00130 #include <string.h>
00131 
00132 int cbf_parse (void *context);
00133 
00134 
00135   /* Create a handle */
00136 
00137 int cbf_make_handle (cbf_handle *handle)
00138 {
00139   int errorcode;
00140   
00141   cbf_failnez (cbf_alloc ((void **) handle, NULL, sizeof (cbf_handle), 1))
00142 
00143   errorcode = cbf_make_node (&(*handle)->node, CBF_ROOT, NULL, NULL);
00144 
00145   if (errorcode)
00146 
00147     return errorcode | cbf_free ((void **) handle, NULL);
00148     
00149   (*handle)->row = 0;
00150 
00151   (*handle)->search_row = 0;
00152 
00153   return 0;
00154 }
00155 
00156 
00157   /* Free a handle */
00158 
00159 int cbf_free_handle (cbf_handle handle)
00160 {
00161   int errorcode;
00162   
00163   if (handle)
00164   {
00165     errorcode = cbf_free_node (handle->node);
00166 
00167     return errorcode | cbf_free ((void **) &handle, NULL);
00168   }
00169 
00170   return 0;
00171 }
00172 
00173 
00174   /* Read a file */
00175 
00176 int cbf_read_file (cbf_handle handle, FILE *stream, int headers)
00177 {
00178   cbf_file *file;
00179 
00180   cbf_node *node;
00181 
00182   void *parse [2];
00183 
00184   int errorcode;
00185 
00186   unsigned int children;
00187 
00188   const char *name;
00189 
00190 
00191     /* Check the arguments */
00192 
00193   if (!handle)
00194 
00195     return CBF_ARGUMENT;
00196 
00197   if (((headers & (MSG_DIGEST | MSG_DIGESTNOW)) && (headers & MSG_NODIGEST)))
00198 
00199     return CBF_ARGUMENT;
00200 
00201   
00202     /* Delete the old datablocks */
00203 
00204   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
00205 
00206   cbf_failnez (cbf_set_children (node, 0))
00207 
00208   handle->node = node;
00209 
00210   
00211     /* Create the input file */
00212 
00213   cbf_failnez (cbf_make_file (&file, stream))
00214 
00215 
00216     /* Defaults */
00217     
00218   if ((headers & (MSG_DIGEST | MSG_NODIGEST | MSG_DIGESTNOW)) == 0)
00219 
00220     headers |= (HDR_DEFAULT & (MSG_DIGEST | MSG_NODIGEST | MSG_DIGESTNOW));
00221 
00222   if (headers & MSG_DIGESTNOW)
00223   
00224     headers |= MSG_DIGEST;
00225 
00226 
00227     /* Copy the flags */
00228     
00229   file->read_headers = headers;
00230 
00231 
00232     /* Parse the file */
00233     
00234   parse [0] = file;
00235   parse [1] = handle->node;
00236   
00237   errorcode = cbf_parse (parse);
00238 
00239 
00240     /* Delete the first datablock if it's empty */
00241 
00242   if (!errorcode)
00243   {
00244     errorcode = cbf_get_child (&node, node, 0);
00245     
00246     if (!errorcode)
00247     {
00248       errorcode = cbf_get_name (&name, node);
00249 
00250       if (!errorcode && !name)
00251       {
00252         errorcode = cbf_count_children (&children, node);
00253 
00254         if (!errorcode && !children)
00255 
00256           errorcode = cbf_free_node (node);
00257       }
00258     }
00259     else
00260 
00261       if (errorcode == CBF_NOTFOUND)
00262 
00263         errorcode = 0;
00264   }
00265 
00266 
00267     /* Disconnect the file */
00268 
00269   return errorcode | cbf_delete_fileconnection (&file);
00270 }
00271 
00272 
00273   /* Write a file */
00274 
00275 int cbf_write_file (cbf_handle handle, FILE *stream, int isbuffer,
00276                                                      int ciforcbf,
00277                                                      int headers,
00278                                                      int encoding)
00279 {
00280   cbf_file *file;
00281 
00282   cbf_node *node;
00283 
00284   int errorcode;
00285 
00286   int little;
00287 
00288 
00289     /* CIF or CBF? */
00290     
00291   if (ciforcbf == CIF)
00292 
00293     encoding = encoding & ~ENC_NONE;
00294 
00295   else
00296 
00297     encoding = (encoding & ~(ENC_BASE8   |
00298                              ENC_BASE10  |
00299                              ENC_BASE16  |
00300                              ENC_BASE64  |
00301                              ENC_QP      |
00302                              ENC_FORWARD |
00303                              ENC_BACKWARD)) | ENC_NONE | ENC_CRTERM 
00304                                                        | ENC_LFTERM;
00305 
00306 
00307     /* Check the arguments */
00308 
00309   if (!handle)
00310 
00311     return CBF_ARGUMENT;
00312     
00313   if (((headers  & MIME_HEADERS)  && (headers  & PLAIN_HEADERS)) ||
00314       ((headers  & MSG_DIGEST)    && (headers  & MSG_NODIGEST))  ||
00315       ((headers  & MSG_DIGEST)    && (headers  & PLAIN_HEADERS)) ||
00316       ((headers  & MSG_DIGESTNOW) && (headers  & MSG_NODIGEST))  ||
00317       ((headers  & MSG_DIGESTNOW) && (headers  & PLAIN_HEADERS)) ||
00318       ((encoding & ENC_FORWARD)   && (encoding & ENC_BACKWARD)))
00319 
00320     return CBF_ARGUMENT;
00321     
00322   if (((encoding & ENC_NONE)   > 0) +
00323       ((encoding & ENC_BASE8)  > 0) +
00324       ((encoding & ENC_BASE10) > 0) +
00325       ((encoding & ENC_BASE16) > 0) +
00326       ((encoding & ENC_BASE64) > 0) +
00327       ((encoding & ENC_QP)     > 0) > 1)
00328 
00329     return CBF_ARGUMENT;
00330  
00331 
00332     /* Find the root node */
00333 
00334   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
00335 
00336 
00337     /* Create the file */
00338 
00339   cbf_failnez (cbf_make_file (&file, stream))
00340 
00341 
00342     /* Defaults */
00343     
00344   if (headers & (MSG_DIGEST | MSG_DIGESTNOW))
00345   
00346     headers |= MIME_HEADERS;
00347     
00348   else
00349     
00350     if ((headers & (MIME_HEADERS | PLAIN_HEADERS)) == 0)
00351 
00352       headers |= (HDR_DEFAULT & (MIME_HEADERS | PLAIN_HEADERS));
00353 
00354   if (headers & PLAIN_HEADERS)
00355   
00356     headers |= MSG_NODIGEST;
00357     
00358   else
00359 
00360     if ((headers & (MSG_DIGEST | MSG_NODIGEST | MSG_DIGESTNOW)) == 0)
00361 
00362       headers |= (HDR_DEFAULT & (MSG_DIGEST | MSG_NODIGEST | MSG_DIGESTNOW));
00363 
00364   if (headers & MSG_DIGESTNOW)
00365   
00366     headers |= MSG_DIGEST;
00367 
00368   if ((encoding & (ENC_NONE   |
00369                    ENC_BASE8  |
00370                    ENC_BASE10 |
00371                    ENC_BASE16 |
00372                    ENC_BASE64 |
00373                    ENC_QP)) == 0)
00374 
00375     encoding |= (ENC_DEFAULT & (ENC_NONE   |
00376                                 ENC_BASE8  |
00377                                 ENC_BASE10 |
00378                                 ENC_BASE16 |
00379                                 ENC_BASE64 |
00380                                 ENC_QP));
00381                                
00382   if ((encoding & (ENC_CRTERM | ENC_LFTERM)) == 0)
00383 
00384     encoding |= (ENC_DEFAULT & (ENC_CRTERM | ENC_LFTERM));
00385 
00386   if ((encoding & (ENC_FORWARD | ENC_BACKWARD)) == 0)
00387   
00388     encoding |= (ENC_DEFAULT & (ENC_FORWARD | ENC_BACKWARD));
00389 
00390 
00391     /* Copy the flags */
00392     
00393   file->write_headers  = headers;
00394   file->write_encoding = encoding;
00395  
00396 
00397     /* Write the file */
00398 
00399   errorcode = cbf_write_node (node, file, isbuffer);
00400 
00401 
00402     /* Free the file structure but don't close the file? */
00403 
00404   if (!isbuffer)
00405 
00406     file->stream = NULL;
00407 
00408 
00409     /* Disconnect the file */
00410 
00411   return errorcode | cbf_delete_fileconnection (&file);
00412 }
00413 
00414 
00415   /* Add a data block */
00416 
00417 int cbf_new_datablock (cbf_handle handle, const char *datablockname)
00418 {
00419   cbf_node *node;
00420 
00421   int errorcode;
00422 
00423   if (!handle)
00424 
00425     return CBF_ARGUMENT;
00426 
00427   
00428     /* Find the root node */
00429 
00430   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
00431 
00432 
00433     /* Copy the name */
00434 
00435   if (datablockname)
00436   {
00437     datablockname = cbf_copy_string (NULL, datablockname, 0);
00438 
00439     if (!datablockname)
00440 
00441       return CBF_ALLOC;
00442   }
00443 
00444 
00445     /* Add a datablock */
00446 
00447   errorcode = cbf_make_child (&node, node, CBF_DATABLOCK, datablockname);
00448 
00449   if (errorcode)
00450   {
00451     cbf_free_string (NULL, datablockname);
00452 
00453     return errorcode;
00454   }
00455 
00456 
00457     /* Success */
00458 
00459   handle->node = node;
00460 
00461   return 0;
00462 }
00463 
00464 
00465   /* Add a data block, allowing for duplicates */
00466 
00467 int cbf_force_new_datablock (cbf_handle handle, const char *datablockname)
00468 {
00469   cbf_node *node;
00470 
00471   int errorcode;
00472 
00473   if (!handle)
00474 
00475     return CBF_ARGUMENT;
00476 
00477   
00478     /* Find the root node */
00479 
00480   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
00481 
00482 
00483     /* Copy the name */
00484 
00485   if (datablockname)
00486   {
00487     datablockname = cbf_copy_string (NULL, datablockname, 0);
00488 
00489     if (!datablockname)
00490 
00491       return CBF_ALLOC;
00492   }
00493 
00494 
00495     /* Add a datablock */
00496 
00497   errorcode = cbf_make_new_child (&node, node, CBF_DATABLOCK, datablockname);
00498 
00499   if (errorcode)
00500   {
00501     cbf_free_string (NULL, datablockname);
00502 
00503     return errorcode;
00504   }
00505 
00506 
00507     /* Success */
00508 
00509   handle->node = node;
00510 
00511   return 0;
00512 }
00513 
00514 
00515   /* Add a category to the current data block */
00516 
00517 int cbf_new_category (cbf_handle handle, const char *categoryname)
00518 {
00519   cbf_node *node;
00520 
00521   int errorcode;
00522 
00523   if (!handle)
00524 
00525     return CBF_ARGUMENT;
00526 
00527   
00528     /* Find the data block node */
00529 
00530   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
00531 
00532 
00533     /* Copy the name */
00534 
00535   if (categoryname)
00536   {
00537     categoryname = cbf_copy_string (NULL, categoryname, 0);
00538 
00539     if (!categoryname)
00540 
00541       return CBF_ALLOC;
00542   }
00543 
00544 
00545     /* Add a category */
00546 
00547   errorcode = cbf_make_child (&node, node, CBF_CATEGORY, categoryname);
00548 
00549   if (errorcode)
00550   {
00551     cbf_free_string (NULL, categoryname);
00552 
00553     return errorcode;
00554   }
00555 
00556 
00557     /* Success */
00558 
00559   handle->node = node;
00560 
00561   return 0;
00562 }
00563 
00564 
00565   /* Add a category to the current data block, allowing for duplicates */
00566 
00567 int cbf_force_new_category (cbf_handle handle, const char *categoryname)
00568 {
00569   cbf_node *node;
00570 
00571   int errorcode;
00572 
00573   if (!handle)
00574 
00575     return CBF_ARGUMENT;
00576 
00577   
00578     /* Find the data block node */
00579 
00580   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
00581 
00582 
00583     /* Copy the name */
00584 
00585   if (categoryname)
00586   {
00587     categoryname = cbf_copy_string (NULL, categoryname, 0);
00588 
00589     if (!categoryname)
00590 
00591       return CBF_ALLOC;
00592   }
00593 
00594 
00595     /* Add a category */
00596 
00597   errorcode = cbf_make_new_child (&node, node, CBF_CATEGORY, categoryname);
00598 
00599   if (errorcode)
00600   {
00601     cbf_free_string (NULL, categoryname);
00602 
00603     return errorcode;
00604   }
00605 
00606 
00607     /* Success */
00608 
00609   handle->node = node;
00610 
00611   return 0;
00612 }
00613 
00614 
00615   /* Add a column to the current category */
00616   
00617 int cbf_new_column (cbf_handle handle, const char *columnname)
00618 {
00619   cbf_node *node;
00620 
00621   int errorcode;
00622 
00623   unsigned int rows;
00624 
00625   if (!handle)
00626 
00627     return CBF_ARGUMENT;
00628 
00629   
00630     /* Find the category node */
00631 
00632   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
00633 
00634 
00635     /* How many rows does this category have? */
00636 
00637   cbf_failnez (cbf_count_rows (handle, &rows))
00638   
00639 
00640     /* Copy the name */
00641 
00642   if (columnname)
00643   {
00644     columnname = cbf_copy_string (NULL, columnname, 0);
00645 
00646     if (!columnname)
00647 
00648       return CBF_ALLOC;
00649   }
00650 
00651 
00652     /* Add a column */
00653 
00654   errorcode = cbf_make_child (&node, node, CBF_COLUMN, columnname);
00655 
00656   if (errorcode)
00657   {
00658     cbf_free_string (NULL, columnname);
00659 
00660     return errorcode;
00661   }
00662 
00663 
00664     /* Set the number of rows */
00665 
00666   errorcode = cbf_set_children (node, rows);
00667 
00668   if (errorcode)
00669 
00670     return errorcode | cbf_free_node (node);
00671 
00672 
00673     /* Success */
00674 
00675   handle->node = node;
00676 
00677   handle->row = 0;
00678 
00679   handle->search_row = 0;
00680 
00681   return 0;
00682 }
00683 
00684 
00685   /* Add a row to the current category */
00686 
00687 int cbf_new_row (cbf_handle handle)
00688 {
00689   cbf_node *node, *columnnode;
00690 
00691   int errorcode [2];
00692 
00693   unsigned int rows, columns, column;
00694 
00695   if (!handle)
00696 
00697     return CBF_ARGUMENT;
00698 
00699   
00700     /* Find the category node */
00701 
00702   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
00703 
00704 
00705     /* How many rows and columns does this category have? */
00706 
00707   cbf_failnez (cbf_count_rows (handle, &rows))
00708   
00709   cbf_failnez (cbf_count_columns (handle, &columns))
00710   
00711 
00712     /* Add a row to each column */
00713 
00714   for (column = 0; column < columns; column++)
00715   {
00716     errorcode [0] = cbf_get_child (&columnnode, node, column);
00717 
00718     if (!errorcode [0])
00719 
00720       errorcode [0] = cbf_add_columnrow (columnnode, NULL);
00721 
00722     if (errorcode [0])
00723     {
00724         /* Set the columns back to the original number of rows */
00725         
00726       while (column)
00727       {
00728         column--;
00729 
00730         errorcode [1] = cbf_get_child (&columnnode, node, column);
00731 
00732         if (!errorcode [1])
00733 
00734           errorcode [1] |= cbf_set_children (columnnode, rows);
00735 
00736         errorcode [0] |= errorcode [1];
00737       }
00738 
00739       return errorcode [0];
00740     }
00741   }
00742 
00743   
00744     /* Success */
00745 
00746   handle->row = rows;
00747 
00748   handle->search_row = rows;
00749 
00750   return 0;
00751 }
00752 
00753 
00754   /* Insert a row in the current category */
00755 
00756 int cbf_insert_row (cbf_handle handle, const int rownumber)
00757 {
00758   cbf_node *node, *columnnode;
00759 
00760   int errorcode [2];
00761 
00762   unsigned int rows, columns, column;
00763 
00764   if (!handle)
00765 
00766     return CBF_ARGUMENT;
00767 
00768   
00769     /* Find the category node */
00770 
00771   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
00772 
00773 
00774     /* How many rows and columns does this category have? */
00775 
00776   cbf_failnez (cbf_count_rows (handle, &rows))
00777   
00778   cbf_failnez (cbf_count_columns (handle, &columns))
00779   
00780 
00781     /* Insert a row into each column */
00782 
00783   for (column = 0; column < columns; column++)
00784   {
00785     errorcode [0] = cbf_get_child (&columnnode, node, column);
00786 
00787     if (!errorcode [0])
00788 
00789       errorcode [0] = cbf_insert_columnrow (columnnode, rownumber, NULL);
00790 
00791     if (errorcode [0])
00792     {
00793         /* Set the columns back to the original number of rows */
00794         
00795       while (column)
00796       {
00797         column--;
00798 
00799         errorcode [1] = cbf_get_child (&columnnode, node, column);
00800 
00801         if (!errorcode [1])
00802 
00803           errorcode [1] |= cbf_delete_columnrow (columnnode, rownumber);
00804 
00805         errorcode [0] |= errorcode [1];
00806       }
00807 
00808       return errorcode [0];
00809     }
00810   }
00811 
00812   
00813     /* Success */
00814 
00815   handle->row = rownumber;
00816 
00817   handle->search_row = rownumber;
00818 
00819   return 0;
00820 }
00821 
00822 
00823   /* Delete a row from the current category */
00824 
00825 int cbf_delete_row (cbf_handle handle, const int rownumber)
00826 {
00827   cbf_node *node, *columnnode;
00828 
00829   int errorcode [2];
00830 
00831   unsigned int rows, columns, column;
00832 
00833   if (!handle)
00834 
00835     return CBF_ARGUMENT;
00836 
00837   
00838     /* Find the category node */
00839 
00840   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
00841 
00842 
00843     /* How many rows and columns does this category have? */
00844 
00845   cbf_failnez (cbf_count_rows (handle, &rows))
00846   
00847   cbf_failnez (cbf_count_columns (handle, &columns))
00848   
00849 
00850     /* Delete a row from each column */
00851 
00852   errorcode [0] = 0;
00853   
00854   for (column = 0; column < columns; column++)
00855   {
00856     errorcode [1] = cbf_get_child (&columnnode, node, column);
00857 
00858     if (!errorcode [1])
00859 
00860       errorcode [1] = cbf_delete_columnrow (columnnode, rownumber);
00861 
00862     errorcode [0] |= errorcode [1];
00863   }
00864 
00865   rows--;
00866 
00867   if (handle->row > rownumber)
00868 
00869     handle->row--;
00870 
00871   if (handle->search_row > rownumber)
00872 
00873     handle->search_row--;
00874 
00875   return errorcode [0];
00876 }
00877 
00878 
00879   /* Change the name of the current data block */
00880 
00881 int cbf_set_datablockname (cbf_handle handle, const char *datablockname)
00882 {
00883   cbf_node *node;
00884 
00885   int errorcode;
00886 
00887   if (!handle)
00888 
00889     return CBF_ARGUMENT;
00890 
00891   
00892     /* Find the data block node */
00893 
00894   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
00895 
00896 
00897     /* Copy the name */
00898 
00899   if (datablockname)
00900   {
00901     datablockname = cbf_copy_string (NULL, datablockname, 0);
00902 
00903     if (!datablockname)
00904 
00905       return CBF_ALLOC;
00906   }
00907 
00908 
00909     /* Change the name */
00910 
00911   errorcode = cbf_name_node (node, datablockname);
00912 
00913   if (errorcode)
00914   {
00915     cbf_free_string (NULL, datablockname);
00916 
00917     return errorcode;
00918   }
00919 
00920 
00921     /* Success */
00922 
00923   handle->node = node;
00924 
00925   return 0;
00926 }
00927 
00928 
00929   /* Delete all categories from all the data blocks */
00930 
00931 int cbf_reset_datablocks (cbf_handle handle)
00932 {
00933   cbf_node *node, *datablocknode;
00934 
00935   unsigned int datablocks, datablock;
00936 
00937   int errorcode;
00938 
00939   if (!handle)
00940 
00941     return CBF_ARGUMENT;
00942 
00943   
00944     /* Find the data block node */
00945 
00946   errorcode = cbf_find_parent (&datablocknode, handle->node, CBF_DATABLOCK);
00947 
00948   if (errorcode && errorcode != CBF_NOTFOUND)
00949 
00950     return errorcode;
00951 
00952 
00953     /* Find the root node */
00954 
00955   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
00956 
00957   if (errorcode)
00958   
00959     handle->node = node;
00960 
00961   else
00962 
00963     handle->node = datablocknode;
00964 
00965 
00966     /* Delete all grandchildren */
00967 
00968   cbf_failnez (cbf_count_children (&datablocks, node))
00969 
00970   for (datablock = 0; datablock < datablocks; datablock++)
00971   {
00972     cbf_failnez (cbf_get_child (&node, handle->node, datablock))
00973 
00974     cbf_failnez (cbf_set_children (node, 0))
00975   }
00976 
00977 
00978     /* Success */
00979 
00980   return 0;
00981 }
00982 
00983 
00984   /* Delete all categories from the current data block */
00985 
00986 int cbf_reset_datablock (cbf_handle handle)
00987 {
00988   cbf_node *node;
00989 
00990   if (!handle)
00991 
00992     return CBF_ARGUMENT;
00993 
00994   
00995     /* Find the data block node */
00996 
00997   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
00998 
00999   handle->node = node;
01000 
01001 
01002     /* Delete the children */
01003 
01004   return cbf_set_children (node, 0);
01005 }
01006 
01007 
01008   /* Delete all columns and rows from the current category */
01009 
01010 int cbf_reset_category (cbf_handle handle)
01011 {
01012   cbf_node *node;
01013 
01014   if (!handle)
01015 
01016     return CBF_ARGUMENT;
01017 
01018   
01019     /* Find the category node */
01020 
01021   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01022 
01023   handle->node = node;
01024 
01025 
01026     /* Delete the children */
01027 
01028   return cbf_set_children (node, 0);
01029 }
01030 
01031 
01032   /* Delete the current data block */
01033 
01034 int cbf_remove_datablock (cbf_handle handle)
01035 {
01036   cbf_node *node, *parent;
01037 
01038   if (!handle)
01039 
01040     return CBF_ARGUMENT;
01041 
01042   
01043     /* Find the data block node */
01044 
01045   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01046 
01047 
01048     /* Find the root node */
01049     
01050   cbf_failnez (cbf_find_parent (&parent, node, CBF_ROOT))
01051 
01052   handle->node = parent;
01053 
01054 
01055     /* Delete the datablock */
01056 
01057   return cbf_free_node (node);
01058 }
01059 
01060 
01061   /* Delete the current category */
01062 
01063 int cbf_remove_category (cbf_handle handle)
01064 {
01065   cbf_node *node, *parent;
01066 
01067   if (!handle)
01068 
01069     return CBF_ARGUMENT;
01070 
01071   
01072     /* Find the category node */
01073 
01074   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01075 
01076 
01077     /* Find the data block node */
01078     
01079   cbf_failnez (cbf_find_parent (&parent, node, CBF_DATABLOCK))
01080 
01081   handle->node = parent;
01082 
01083 
01084     /* Delete the column */
01085 
01086   return cbf_free_node (node);
01087 }
01088 
01089 
01090   /* Delete the current column */
01091 
01092 int cbf_remove_column (cbf_handle handle)
01093 {
01094   cbf_node *node, *parent;
01095 
01096   if (!handle)
01097 
01098     return CBF_ARGUMENT;
01099 
01100   
01101     /* Find the column node */
01102 
01103   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01104 
01105 
01106     /* Find the category node */
01107     
01108   cbf_failnez (cbf_find_parent (&parent, node, CBF_CATEGORY))
01109 
01110   handle->node = parent;
01111 
01112 
01113     /* Delete the column */
01114 
01115   return cbf_free_node (node);
01116 }
01117 
01118 
01119   /* Delete the current row */
01120 
01121 int cbf_remove_row (cbf_handle handle)
01122 {
01123   if (!handle)
01124 
01125     return CBF_ARGUMENT;
01126 
01127   return cbf_delete_row (handle, handle->row);
01128 }
01129 
01130 
01131   /* Make the first data block the current data block */
01132 
01133 int cbf_rewind_datablock (cbf_handle handle)
01134 {
01135   cbf_node *node;
01136 
01137   if (!handle)
01138 
01139     return CBF_ARGUMENT;
01140 
01141   
01142     /* Find the root node */
01143 
01144   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
01145 
01146 
01147     /* Find the first child */
01148 
01149   cbf_failnez (cbf_get_child (&node, node, 0))
01150 
01151   handle->node = node;
01152 
01153 
01154     /* Success */
01155 
01156   return 0;
01157 }
01158 
01159 
01160   /* Make the first category in the current data block the current category */
01161 
01162 int cbf_rewind_category (cbf_handle handle)
01163 {
01164   cbf_node *node;
01165 
01166   if (!handle)
01167 
01168     return CBF_ARGUMENT;
01169 
01170   
01171     /* Find the data block node */
01172 
01173   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01174 
01175 
01176     /* Find the first child */
01177 
01178   cbf_failnez (cbf_get_child (&node, node, 0))
01179 
01180   handle->node = node;
01181 
01182 
01183     /* Success */
01184 
01185   return 0;
01186 }
01187 
01188 
01189   /* Make the first column in the current category the current column */
01190 
01191 int cbf_rewind_column (cbf_handle handle)
01192 {
01193   cbf_node *node;
01194 
01195   if (!handle)
01196 
01197     return CBF_ARGUMENT;
01198 
01199   
01200     /* Find the category node */
01201 
01202   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01203 
01204 
01205     /* Find the first child */
01206 
01207   cbf_failnez (cbf_get_child (&node, node, 0))
01208 
01209   handle->node = node;
01210 
01211 
01212     /* Success */
01213 
01214   return 0;
01215 }
01216 
01217 
01218   /* Make the first row in the current category the current row */
01219 
01220 int cbf_rewind_row (cbf_handle handle)
01221 {
01222   if (!handle)
01223 
01224     return CBF_ARGUMENT;
01225 
01226   handle->row = 0;
01227 
01228   handle->search_row = 0;
01229 
01230 
01231     /* Success */
01232 
01233   return 0;
01234 }
01235 
01236 
01237   /* Make the next data block the current data block */
01238 
01239 int cbf_next_datablock (cbf_handle handle)
01240 {
01241   cbf_node *parent, *node;
01242 
01243   unsigned int index;
01244   
01245   if (!handle)
01246 
01247     return CBF_ARGUMENT;
01248 
01249 
01250     /* Find the data block node */
01251 
01252   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01253 
01254 
01255     /* Find the root node */
01256 
01257   cbf_failnez (cbf_find_parent (&parent, node, CBF_ROOT))
01258 
01259 
01260     /* Which child is this? */
01261 
01262   cbf_failnez (cbf_child_index (&index, node))
01263   
01264 
01265     /* Get the next data block */
01266 
01267   cbf_failnez (cbf_get_child (&node, parent, index + 1))
01268 
01269   handle->node = node;
01270 
01271 
01272     /* Success */
01273 
01274   return 0;
01275 }
01276 
01277 
01278   /* Make the next category in the current data block the current category */
01279 
01280 int cbf_next_category (cbf_handle handle)
01281 {
01282   cbf_node *parent, *node;
01283 
01284   unsigned int index;
01285   
01286   if (!handle)
01287 
01288     return CBF_ARGUMENT;
01289 
01290 
01291     /* Find the category node */
01292 
01293   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01294 
01295 
01296     /* Find the data block node */
01297 
01298   cbf_failnez (cbf_find_parent (&parent, node, CBF_DATABLOCK))
01299 
01300 
01301     /* Which child is this? */
01302 
01303   cbf_failnez (cbf_child_index (&index, node))
01304   
01305 
01306     /* Get the next category */
01307 
01308   cbf_failnez (cbf_get_child (&node, parent, index + 1))
01309 
01310   handle->node = node;
01311 
01312 
01313     /* Success */
01314 
01315   return 0;
01316 }
01317 
01318 
01319   /* Make the next column in the current category the current column */
01320 
01321 int cbf_next_column (cbf_handle handle)
01322 {
01323   cbf_node *parent, *node;
01324 
01325   unsigned int index;
01326   
01327   if (!handle)
01328 
01329     return CBF_ARGUMENT;
01330 
01331 
01332     /* Find the column node */
01333 
01334   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01335 
01336 
01337     /* Find the category node */
01338 
01339   cbf_failnez (cbf_find_parent (&parent, node, CBF_CATEGORY))
01340 
01341 
01342     /* Which child is this? */
01343 
01344   cbf_failnez (cbf_child_index (&index, node))
01345   
01346 
01347     /* Get the next column */
01348 
01349   cbf_failnez (cbf_get_child (&node, parent, index + 1))
01350 
01351   handle->node = node;
01352 
01353 
01354     /* Success */
01355 
01356   return 0;
01357 }
01358 
01359 
01360   /* Make the next row in the current category the current row */
01361 
01362 int cbf_next_row (cbf_handle handle)
01363 {
01364   cbf_node *node;
01365 
01366   unsigned int rows;
01367   
01368   if (!handle)
01369 
01370     return CBF_ARGUMENT;
01371 
01372 
01373     /* Find the column node */
01374 
01375   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01376 
01377   cbf_failnez (cbf_count_children (&rows, node))
01378 
01379 
01380     /* Is the row valid? */
01381 
01382   if (handle->row >= rows)
01383 
01384     return CBF_NOTFOUND;
01385 
01386   handle->row++;
01387 
01388   handle->search_row = handle->row;
01389 
01390 
01391     /* Success */
01392 
01393   return 0;
01394 }
01395 
01396 
01397   /* Make the specified data block the current data block */
01398 
01399 int cbf_select_datablock (cbf_handle handle, unsigned int datablock)
01400 {
01401   cbf_node *node;
01402 
01403   if (!handle)
01404 
01405     return CBF_ARGUMENT;
01406 
01407 
01408     /* Find the root node */
01409 
01410   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
01411 
01412 
01413     /* Select the data block */
01414 
01415   cbf_failnez (cbf_get_child (&node, node, datablock))
01416 
01417   handle->node = node;
01418 
01419 
01420     /* Success */
01421 
01422   return 0;
01423 }
01424 
01425 
01426   /* Make the specified category the current category */
01427 
01428 int cbf_select_category (cbf_handle handle, unsigned int category)
01429 {
01430   cbf_node *node;
01431 
01432   if (!handle)
01433 
01434     return CBF_ARGUMENT;
01435 
01436 
01437     /* Find the data block node */
01438 
01439   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01440 
01441 
01442     /* Select the category */
01443 
01444   cbf_failnez (cbf_get_child (&node, node, category))
01445 
01446   handle->node = node;
01447 
01448 
01449     /* Success */
01450 
01451   return 0;
01452 }
01453 
01454 
01455   /* Make the specified column the current column */
01456 
01457 int cbf_select_column (cbf_handle handle, unsigned int column)
01458 {
01459   cbf_node *node;
01460 
01461   if (!handle)
01462 
01463     return CBF_ARGUMENT;
01464 
01465 
01466     /* Find the category node */
01467 
01468   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01469 
01470 
01471     /* Select the column */
01472 
01473   cbf_failnez (cbf_get_child (&node, node, column))
01474 
01475   handle->node = node;
01476 
01477 
01478     /* Success */
01479 
01480   return 0;
01481 }
01482 
01483 
01484   /* Make the specified row the current row */
01485 
01486 int cbf_select_row (cbf_handle handle, unsigned int row)
01487 {
01488   cbf_node *node;
01489 
01490   unsigned int rows;
01491   
01492   if (!handle)
01493 
01494     return CBF_ARGUMENT;
01495 
01496 
01497     /* Find the column node */
01498 
01499   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01500 
01501   cbf_failnez (cbf_count_children (&rows, node))
01502 
01503 
01504     /* Is the row valid? */
01505 
01506   if (row >= rows)
01507 
01508     return CBF_NOTFOUND;
01509 
01510   handle->row = row;
01511 
01512   handle->search_row = row;
01513 
01514 
01515     /* Success */
01516 
01517   return 0;
01518 }
01519 
01520 
01521   /* Make the named data block the current data block */
01522 
01523 int cbf_find_datablock (cbf_handle handle, const char *datablockname)
01524 {
01525   cbf_node *node;
01526 
01527   if (!handle)
01528 
01529     return CBF_ARGUMENT;
01530 
01531 
01532     /* Find the root node */
01533 
01534   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
01535 
01536 
01537     /* Find the data block */
01538 
01539   cbf_failnez (cbf_find_child (&node, node, datablockname))
01540 
01541   handle->node = node;
01542 
01543 
01544     /* Success */
01545 
01546   return 0;
01547 }
01548 
01549 
01550   /* Make the named category in the current data block the current category */
01551 
01552 int cbf_find_category (cbf_handle handle, const char *categoryname)
01553 {
01554   cbf_node *node;
01555 
01556   if (!handle)
01557 
01558     return CBF_ARGUMENT;
01559 
01560 
01561     /* Find the data block node */
01562 
01563   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01564 
01565 
01566     /* Find the category */
01567 
01568   cbf_failnez (cbf_find_child (&node, node, categoryname))
01569 
01570   handle->node = node;
01571 
01572   handle->row = 0;
01573 
01574   handle->search_row = 0;
01575 
01576 
01577     /* Success */
01578 
01579   return 0;
01580 }
01581 
01582 
01583   /* Make the named column in the current category the current column */
01584 
01585 int cbf_find_column (cbf_handle handle, const char *columnname)
01586 {
01587   cbf_node *node;
01588 
01589   if (!handle)
01590 
01591     return CBF_ARGUMENT;
01592 
01593 
01594     /* Find the category node */
01595 
01596   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01597 
01598 
01599     /* Find the column */
01600 
01601   cbf_failnez (cbf_find_child (&node, node, columnname))
01602 
01603   handle->node = node;
01604 
01605 
01606     /* Success */
01607 
01608   return 0;
01609 }
01610 
01611 
01612   /* Make the first row with matching value the current row */
01613 
01614 int cbf_find_row (cbf_handle handle, const char *value)
01615 {
01616   cbf_failnez (cbf_rewind_row (handle))
01617 
01618   return cbf_find_nextrow (handle, value);
01619 }
01620 
01621 
01622   /* Make the next row with matching value the current row */
01623 
01624 int cbf_find_nextrow (cbf_handle handle, const char *value)
01625 {
01626   cbf_node *node;
01627 
01628   unsigned int row, rows;
01629 
01630   const char *text;
01631 
01632   if (!handle)
01633 
01634     return CBF_ARGUMENT;
01635 
01636 
01637     /* Find the column node */
01638 
01639   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01640 
01641 
01642     /* Count the rows */
01643 
01644   cbf_failnez (cbf_count_children (&rows, node))
01645 
01646   for (row = handle->search_row; row < rows; row++)
01647   {
01648       /* Is the value ascii? */
01649 
01650     if (cbf_is_binary (node, row))
01651 
01652       continue;
01653 
01654 
01655       /* Get the value of the current row */
01656 
01657     cbf_failnez (cbf_get_columnrow (&text, node, row))
01658 
01659 
01660       /* Compare the values */
01661 
01662     if (text && value)
01663     {
01664       if (strcmp (text + 1, value))
01665 
01666         continue;
01667     }
01668     else
01669 
01670       if (text != value)
01671 
01672         continue;
01673 
01674 
01675       /* Found a match */
01676 
01677     handle->row = row;
01678 
01679     handle->search_row = row + 1;
01680 
01681     return 0;
01682   }
01683 
01684 
01685     /* Fail */
01686 
01687   return CBF_NOTFOUND;
01688 }
01689 
01690 
01691   /* Count the data blocks */
01692 
01693 int cbf_count_datablocks (cbf_handle handle, unsigned int *datablocks)
01694 {
01695   cbf_node *node;
01696 
01697   if (!handle)
01698 
01699     return CBF_ARGUMENT;
01700 
01701 
01702     /* Find the root node */
01703 
01704   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_ROOT))
01705 
01706 
01707     /* Count the data blocks */
01708 
01709   return cbf_count_children (datablocks, node);
01710 }
01711 
01712 
01713   /* Count the categories in the current data block */
01714 
01715 int cbf_count_categories (cbf_handle handle, unsigned int *categories)
01716 {
01717   cbf_node *node;
01718 
01719   if (!handle)
01720 
01721     return CBF_ARGUMENT;
01722 
01723 
01724     /* Find the data block node */
01725 
01726   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01727 
01728 
01729     /* Count the categories */
01730 
01731   return cbf_count_children (categories, node);
01732 }
01733 
01734 
01735   /* Count the columns in the current category */
01736 
01737 int cbf_count_columns (cbf_handle handle, unsigned int *columns)
01738 {
01739   cbf_node *node;
01740 
01741   if (!handle)
01742 
01743     return CBF_ARGUMENT;
01744 
01745 
01746     /* Find the category node */
01747 
01748   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01749 
01750 
01751     /* Count the columns */
01752 
01753   return cbf_count_children (columns, node);
01754 }
01755 
01756 
01757   /* Count the rows in the current category */
01758 
01759 int cbf_count_rows (cbf_handle handle, unsigned int *rows)
01760 {
01761   cbf_node *node, *parent;
01762 
01763   unsigned int columns, column, columnrows, categoryrows;
01764 
01765   if (!handle)
01766 
01767     return CBF_ARGUMENT;
01768 
01769 
01770     /* Find the category node */
01771 
01772   cbf_failnez (cbf_find_parent (&parent, handle->node, CBF_CATEGORY))
01773 
01774 
01775     /* Count the columns */
01776 
01777   cbf_failnez (cbf_count_children (&columns, parent))
01778 
01779 
01780     /* Get the size of each column */
01781 
01782   categoryrows = 0;
01783 
01784   for (column = 0; column < columns; column++)
01785   {
01786       /* Get the column */
01787 
01788     cbf_failnez (cbf_get_child (&node, parent, column))
01789 
01790 
01791       /* Count the number of rows */
01792 
01793     cbf_failnez (cbf_count_children (&columnrows, node))
01794 
01795 
01796       /* Is it the same size as the other columns? */
01797 
01798     if (column == 0)
01799 
01800       categoryrows = columnrows;
01801 
01802     else
01803 
01804       if (categoryrows != columnrows)
01805 
01806         return CBF_FORMAT;
01807   }
01808 
01809   if (rows)
01810 
01811     *rows = categoryrows;
01812 
01813 
01814     /* Success */
01815 
01816   return 0;
01817 }
01818 
01819 
01820   /* Get the name of the current data block */
01821   
01822 int cbf_datablock_name (cbf_handle handle, const char **datablockname)
01823 {
01824   cbf_node *node;
01825 
01826   if (!handle)
01827 
01828     return CBF_ARGUMENT;
01829 
01830 
01831     /* Find the data block node */
01832 
01833   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_DATABLOCK))
01834 
01835 
01836     /* Get the name */
01837 
01838   return cbf_get_name (datablockname, node);
01839 }
01840 
01841 
01842   /* Get the name of the current category */
01843   
01844 int cbf_category_name (cbf_handle handle, const char **categoryname)
01845 {
01846   cbf_node *node;
01847 
01848   if (!handle)
01849 
01850     return CBF_ARGUMENT;
01851 
01852 
01853     /* Find the category node */
01854 
01855   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_CATEGORY))
01856 
01857 
01858     /* Get the name */
01859 
01860   return cbf_get_name (categoryname, node);
01861 }
01862 
01863 
01864   /* Get the name of the current column */
01865   
01866 int cbf_column_name (cbf_handle handle, const char **columnname)
01867 {
01868   cbf_node *node;
01869 
01870   if (!handle)
01871 
01872     return CBF_ARGUMENT;
01873 
01874 
01875     /* Find the column node */
01876 
01877   cbf_failnez (cbf_find_parent (&node, handle->node, CBF_COLUMN))
01878 
01879 
01880     /* Get the name */
01881 
01882   return cbf_get_name (columnname, node);
01883 }
01884 
01885 
01886   /* Get the number of the current row */
01887   
01888 int cbf_row_number (cbf_handle handle, unsigned int *row)
01889 {
01890   if (!handle)
01891 
01892     return CBF_ARGUMENT;
01893 
01894   if (row)
01895 
01896     *row = handle->row;
01897 
01898 
01899     /* Success */
01900 
01901   return 0;
01902 }
01903 
01904 
01905   /* Get the ascii value of the current (row, column) entry */
01906   
01907 int cbf_get_value (cbf_handle handle, const char **value)
01908 {
01909   const char *text;
01910 
01911   
01912     /* Check the arguments */
01913 
01914   if (!handle)
01915 
01916     return CBF_ARGUMENT;
01917 
01918     
01919     /* Is the value binary? */
01920 
01921   if (cbf_is_binary (handle->node, handle->row))
01922 
01923     return CBF_BINARY;
01924 
01925 
01926     /* Get the value */
01927 
01928   cbf_failnez (cbf_get_columnrow (&text, handle->node, handle->row))
01929 
01930   if (value)
01931   
01932     if (text)
01933 
01934       *value = text + 1;
01935       
01936     else
01937     
01938       *value = NULL;
01939 
01940 
01941     /* Success */
01942 
01943   return 0;
01944 }
01945 
01946 
01947   /* Set the ascii value of the current (row, column) entry */
01948   
01949 int cbf_set_value (cbf_handle handle, const char *value)
01950 {
01951   int errorcode;
01952 
01953   
01954     /* Check the arguments */
01955 
01956   if (!handle)
01957 
01958     return CBF_ARGUMENT;
01959 
01960 
01961     /* Copy the string */
01962 
01963   if (value)
01964   {
01965     value = cbf_copy_string (NULL, value, '\200');
01966 
01967     if (!value)
01968 
01969       return CBF_ALLOC;
01970   }
01971 
01972     
01973     /* Set the new value */
01974 
01975   errorcode = cbf_set_columnrow (handle->node, handle->row, value, 1);
01976 
01977   if (errorcode)
01978   {
01979     cbf_free_string (NULL, value);
01980 
01981     return errorcode;
01982   }
01983 
01984 
01985     /* Success */
01986 
01987   return 0;
01988 }
01989 
01990 
01991   /* Get the (int) numeric value of the current (row, column) entry */
01992   
01993 int cbf_get_integervalue (cbf_handle handle, int *number)
01994 {
01995   const char *value;
01996 
01997 
01998     /* Get the value */
01999 
02000   cbf_failnez (cbf_get_value (handle, &value))
02001 
02002 
02003     /* Convert it into an integer */
02004 
02005   if (!value)
02006 
02007     return CBF_NOTFOUND;
02008 
02009   if (number)
02010   
02011     *number = atoi (value);
02012 
02013 
02014     /* Success */
02015 
02016   return 0;
02017 }
02018 
02019 
02020   /* Get the (double) numeric value of the current (row, column) entry */
02021   
02022 int cbf_get_doublevalue (cbf_handle handle, double *number)
02023 {
02024   const char *value;
02025 
02026 
02027     /* Get the value */
02028 
02029   cbf_failnez (cbf_get_value (handle, &value))
02030 
02031 
02032     /* Convert it into a double */
02033 
02034   if (!value)
02035 
02036     return CBF_NOTFOUND;
02037 
02038   if (number)
02039   
02040     *number = atof (value);
02041 
02042 
02043     /* Success */
02044 
02045   return 0;
02046 }
02047 
02048 
02049   /* Set the ascii value of the current (row, column) entry from an int */
02050   
02051 int cbf_set_integervalue (cbf_handle handle, int number)
02052 {
02053   char value [64];
02054 
02055 
02056     /* Write the value */
02057 
02058   sprintf (value, "%d", number);
02059 
02060 
02061     /* Save it */
02062 
02063   return cbf_set_value (handle, value);
02064 }
02065 
02066 
02067   /* Set the ascii value of the current (row, column) entry from a double */
02068   
02069 int cbf_set_doublevalue (cbf_handle handle, const char *format, double number)
02070 {
02071   char value [64];
02072 
02073 
02074     /* Write the value */
02075 
02076   sprintf (value, format, number);
02077 
02078 
02079     /* Save it */
02080 
02081   return cbf_set_value (handle, value);
02082 }
02083 
02084 
02085   /* Get the parameters of the current (row, column) array entry */
02086   
02087 int cbf_get_integerarrayparameters (cbf_handle    handle, 
02088                                     unsigned int *compression,
02089                                     int          *id, 
02090                                     size_t       *elsize, 
02091                                     int          *elsigned, 
02092                                     int          *elunsigned, 
02093                                     size_t       *nelem, 
02094                                     int          *minelem, 
02095                                     int          *maxelem)
02096 {
02097     /* Check the arguments */
02098 
02099   if (!handle)
02100 
02101     return CBF_ARGUMENT;
02102 
02103     
02104     /* Is the value binary? */
02105 
02106   if (!cbf_is_binary (handle->node, handle->row))
02107 
02108     return CBF_ASCII;
02109 
02110 
02111     /* Get the parameters */
02112 
02113   return cbf_binary_parameters (handle->node, handle->row, 
02114                                 compression, id, NULL, elsize,
02115                                 elsigned, elunsigned, nelem,
02116                                 minelem, maxelem);
02117 }
02118 
02119 
02120   /* Get the value of the current (row, column) array entry */
02121   
02122 int cbf_get_integerarray (cbf_handle  handle,
02123                           int        *id,
02124                           void       *value, 
02125                           size_t      elsize, 
02126                           int         elsign,
02127                           size_t      nelem, 
02128                           size_t     *nelem_read)
02129 {
02130   if (!handle)
02131 
02132     return CBF_ARGUMENT;
02133 
02134   return cbf_get_binary (handle->node, handle->row, id,
02135                          value, elsize, elsign, nelem, nelem_read);
02136 }
02137 
02138 
02139   /* Set the value of the current (row, column) array entry */
02140   
02141 int cbf_set_integerarray (cbf_handle    handle,
02142                           unsigned int  compression, 
02143                           int           id, 
02144                           void         *value, 
02145                           size_t        elsize,
02146                           int           elsign, 
02147                           size_t        nelem)
02148 {
02149   if (!handle)
02150 
02151     return CBF_ARGUMENT;
02152 
02153   return cbf_set_binary (handle->node, handle->row,
02154                          compression, id, value, elsize, elsign, nelem);
02155 }
02156 
02157 
02158   /* Issue a warning message */
02159 
02160 void cbf_warning (const char *message)
02161 
02162 {
02163   fprintf (stderr, " CBFlib: warning -- %s\n", message);
02164 }
02165 
02166 
02167   /* Issue an error message */
02168 
02169 void cbf_error (const char *message)
02170 {
02171   fprintf (stderr, " CBFlib: error -- %s\n", message);
02172 }
02173 
02174 
02175 #ifdef __cplusplus
02176 
02177 }
02178 
02179 #endif
02180