cbf_write_binary.c

Go to the documentation of this file.
00001 /**********************************************************************
00002  * cbf_write_binary -- write binary sections                          *
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_tree.h"
00126 #include "cbf_compress.h"
00127 #include "cbf_context.h"
00128 #include "cbf_binary.h"
00129 #include "cbf_codes.h"
00130 
00131 #include <stdlib.h>
00132 #include <string.h>
00133 #include <ctype.h>
00134 #include <limits.h>
00135 
00136 #include "cbf_write_binary.h"
00137 
00138                 
00139   /* Write a binary value */
00140   
00141 int cbf_write_binary (cbf_node *column, unsigned int row, 
00142                                         cbf_file *file, 
00143                                         int isbuffer)
00144 {
00145   cbf_file *infile;
00146 
00147   char digest [25], text [100];
00148   
00149   long start;
00150   
00151   size_t size;
00152   
00153   unsigned int compression;
00154 
00155   int id, bits, sign, type, checked_digest, elsize;
00156 
00157 
00158     /* Check the arguments */
00159 
00160   if (!file)
00161 
00162     return CBF_ARGUMENT;
00163     
00164   if (((file->write_encoding & ENC_QP)     > 0) + 
00165       ((file->write_encoding & ENC_BASE64) > 0) + 
00166       ((file->write_encoding & ENC_BASE8)  > 0) + 
00167       ((file->write_encoding & ENC_BASE10) > 0) + 
00168       ((file->write_encoding & ENC_BASE16) > 0) + 
00169       ((file->write_encoding & ENC_NONE)   > 0) != 1)
00170 
00171     return CBF_ARGUMENT;
00172     
00173   if (!cbf_is_binary (column, row))
00174 
00175     return CBF_ARGUMENT;
00176     
00177   if (cbf_is_mimebinary (column, row))
00178 
00179     return CBF_ARGUMENT;
00180     
00181 
00182     /* Parse the value */
00183 
00184   cbf_failnez (cbf_get_bintext (column, row, &type, &id, &infile,
00185                                 &start, &size, &checked_digest,
00186                                  digest, &bits, &sign, &compression))
00187 
00188 
00189     /* Position the file at the start of the binary section */
00190 
00191   cbf_failnez (cbf_set_fileposition (infile, start, SEEK_SET))
00192   
00193 
00194     /* Calculate the digest if necessary */
00195   
00196   if (!cbf_is_base64digest (digest) && (file->write_headers & MSG_DIGEST))
00197   {
00198       /* Discard any bits in the buffers */
00199 
00200     cbf_failnez (cbf_reset_bits (infile))
00201 
00202 
00203       /* Compute the message digest */
00204 
00205     cbf_failnez (cbf_md5digest (infile, size, digest))
00206       
00207 
00208       /* Go back to the start of the binary data */
00209 
00210     cbf_failnez (cbf_set_fileposition (infile, start, SEEK_SET))
00211     
00212     
00213       /* Update the entry */
00214       
00215     checked_digest = 1;
00216       
00217     cbf_failnez (cbf_set_bintext (column, row, type,
00218                                   id, infile, start, size,
00219                                   checked_digest, digest, bits, 
00220                                                           sign,
00221                                                           compression))
00222   }
00223 
00224 
00225     /* Discard any bits in the buffers */
00226 
00227   cbf_failnez (cbf_reset_bits (infile))
00228 
00229   
00230     /* Do we need MIME headers? */
00231     
00232   if (compression == CBF_NONE && (file->write_headers & MIME_NOHEADERS))
00233   
00234     return CBF_ARGUMENT;
00235     
00236 
00237     /* Write the header */
00238 
00239   cbf_failnez (cbf_write_string (file, "\n;\n"))
00240 
00241 
00242     /* MIME header? */
00243 
00244   if (file->write_headers & MIME_HEADERS)
00245   {
00246     cbf_failnez (cbf_write_string (file, "--CIF-BINARY-FORMAT-SECTION--\n"))
00247     
00248     if (compression == CBF_NONE)
00249     
00250       cbf_failnez (cbf_write_string (file, 
00251                                 "Content-Type: application/octet-stream\n"))
00252       
00253     else
00254     {
00255       cbf_failnez (cbf_write_string (file, 
00256                                 "Content-Type: application/octet-stream;\n"))
00257  
00258       switch (compression)
00259       {
00260         case CBF_PACKED:
00261         
00262           cbf_failnez (cbf_write_string (file, 
00263                                 "     conversions=\"x-CBF_PACKED\"\n"))
00264 
00265           break;
00266               
00267         case CBF_CANONICAL:
00268         
00269           cbf_failnez (cbf_write_string (file, 
00270                                 "     conversions=\"x-CBF_CANONICAL\"\n"))
00271 
00272           break;
00273               
00274         case CBF_BYTE_OFFSET:
00275         
00276           cbf_failnez (cbf_write_string (file, 
00277                                 "     conversions=\"x-CBF_BYTE_OFFSET\"\n"))
00278 
00279           break;
00280               
00281         case CBF_PREDICTOR:
00282         
00283           cbf_failnez (cbf_write_string (file, 
00284                                 "     conversions=\"x-CBF_PREDICTOR\"\n"))
00285 
00286           break;
00287               
00288         default:
00289       
00290           cbf_failnez (cbf_write_string (file, 
00291                                 "     conversions=\"x-CBF_UNKNOWN\"\n"))
00292       }
00293     }
00294 
00295     if (file->write_encoding & ENC_QP)
00296                                 
00297       cbf_failnez (cbf_write_string (file, 
00298                       "Content-Transfer-Encoding: QUOTED-PRINTABLE\n"))
00299                                 
00300     else
00301                   
00302       if (file->write_encoding & ENC_BASE64)
00303                                 
00304         cbf_failnez (cbf_write_string (file, 
00305                       "Content-Transfer-Encoding: BASE64\n"))
00306                                 
00307       else
00308                   
00309         if (file->write_encoding & ENC_BASE8)
00310                                 
00311           cbf_failnez (cbf_write_string (file, 
00312                       "Content-Transfer-Encoding: X-BASE8\n"))
00313                                 
00314         else
00315                   
00316           if (file->write_encoding & ENC_BASE10)
00317                                 
00318             cbf_failnez (cbf_write_string (file, 
00319                       "Content-Transfer-Encoding: X-BASE10\n"))
00320                                 
00321           else
00322                   
00323             if (file->write_encoding & ENC_BASE16)
00324                                 
00325               cbf_failnez (cbf_write_string (file, 
00326                       "Content-Transfer-Encoding: X-BASE16\n"))
00327                       
00328             else
00329             
00330               cbf_failnez (cbf_write_string (file, 
00331                       "Content-Transfer-Encoding: BINARY\n"))
00332 
00333     sprintf (text, "X-Binary-Size: %u\n", size);
00334     
00335     cbf_failnez (cbf_write_string (file, text))
00336 
00337     sprintf (text, "X-Binary-ID: %d\n", id);
00338 
00339     cbf_failnez (cbf_write_string (file, text))
00340     
00341     if (sign)
00342     
00343       sprintf (text, "X-Binary-Element-Type: \"signed %d-bit integer\"\n", 
00344                                                     bits);
00345       
00346     else
00347 
00348       sprintf (text, "X-Binary-Element-Type: \"unsigned %d-bit integer\"\n", 
00349                                                       bits);
00350       
00351     cbf_failnez (cbf_write_string (file, text))
00352     
00353     
00354       /* Save the digest if we have one */
00355 
00356     if (cbf_is_base64digest (digest))
00357     {
00358       sprintf (text, "Content-MD5: %24s\n", digest);
00359 
00360       cbf_failnez (cbf_write_string (file, text))
00361     }
00362 
00363     cbf_failnez (cbf_write_string (file, "\n"))  
00364   }
00365   else
00366 
00367       /* Simple header */
00368     
00369     cbf_failnez (cbf_write_string (file, "START OF BINARY SECTION\n"))
00370     
00371 
00372     /* Copy the binary section to the output file */
00373     
00374   if (file->write_encoding & ENC_NONE)
00375   {
00376       /* Write the separators */  
00377   
00378     cbf_failnez (cbf_put_character (file, 12))
00379     cbf_failnez (cbf_put_character (file, 26))
00380     cbf_failnez (cbf_put_character (file, 4))
00381     cbf_failnez (cbf_put_character (file, 213))
00382 
00383 
00384       /* Flush any bits in the buffers */
00385 
00386     cbf_failnez (cbf_flush_bits (file))
00387 
00388 
00389       /* If no MIME header, write the necessary data here */
00390 
00391     if ( !(file->write_headers & MIME_HEADERS) ) {
00392 
00393 
00394         /* Write the binary identifier (64 bits) */
00395 
00396       cbf_failnez (cbf_put_integer (file, id, 1, 64))
00397 
00398 
00399         /* Write the size of the binary section (64 bits) */
00400 
00401       cbf_failnez (cbf_put_integer (file, size, 0, 64))
00402 
00403 
00404         /* Write the compression type (64 bits) */
00405 
00406       cbf_failnez (cbf_put_integer (file, compression, 0, 64))
00407     }
00408 
00409 
00410       /* Get the current point in the new file */
00411 
00412     cbf_failnez (cbf_get_fileposition (file, &start))
00413 
00414 
00415       /* Copy the binary section to the output file */
00416 
00417     cbf_failnez (cbf_copy_file (file, infile, size))
00418   }
00419   else
00420   {
00421       /* Read the element size with no compression? */
00422       
00423     if (compression == CBF_NONE)
00424     {
00425       elsize = (bits + 4) / 8;
00426       
00427       if (elsize < 1 || elsize == 5)
00428       
00429         elsize = 4;
00430         
00431       else
00432         
00433         if (elsize == 7)
00434       
00435           elsize = 6;
00436           
00437         else
00438 
00439           if (elsize > 8)
00440       
00441             elsize = 8;
00442     }
00443     else
00444     
00445       elsize = 4;
00446       
00447       
00448       /* Go back to the start of the binary data */
00449 
00450     cbf_failnez (cbf_set_fileposition (infile, start, SEEK_SET))
00451 
00452 
00453       /* Flush any bits in the buffers */
00454 
00455     cbf_failnez (cbf_flush_bits (infile))
00456 
00457 
00458     if (file->write_encoding & ENC_QP)
00459   
00460       cbf_failnez (cbf_toqp (infile, file, size))
00461 
00462     else
00463   
00464       if (file->write_encoding & ENC_BASE64)
00465   
00466         cbf_failnez (cbf_tobase64 (infile, file, size))
00467 
00468       else
00469   
00470         if (file->write_encoding & ENC_BASE8)
00471   
00472           cbf_failnez (cbf_tobasex (infile, file, size, elsize, 8))
00473 
00474         else
00475   
00476           if (file->write_encoding & ENC_BASE10)
00477   
00478             cbf_failnez (cbf_tobasex (infile, file, size, elsize, 10))
00479 
00480           else
00481   
00482             cbf_failnez (cbf_tobasex (infile, file, size, elsize, 16))
00483   }
00484 
00485 
00486     /* Write the MIME footer */
00487 
00488   if (file->write_headers & MIME_HEADERS)
00489 
00490     cbf_failnez (cbf_write_string (file, 
00491                                "\n--CIF-BINARY-FORMAT-SECTION----\n;\n"))
00492     
00493   else
00494   
00495     cbf_failnez (cbf_write_string (file, "\nEND OF BINARY SECTION\n;\n"))
00496 
00497 
00498     /* Flush the buffer */
00499 
00500   cbf_failnez (cbf_flush_characters (file))
00501 
00502 
00503     /* Replace a connection to a temporary file? */
00504     
00505   if (start  != 0               && 
00506       isbuffer                  && 
00507       type == CBF_TOKEN_TMP_BIN && (file->write_encoding & ENC_NONE))
00508 
00509     cbf_failnez (cbf_set_bintext (column, row, CBF_TOKEN_BIN,
00510                                   id, file, start, size, checked_digest,
00511                                   digest, bits, sign, compression))
00512 
00513 
00514     /* Success */
00515 
00516   return 0;
00517 }
00518 
00519 
00520 #ifdef __cplusplus
00521 
00522 }
00523 
00524 #endif