NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
output_stream.cpp
Go to the documentation of this file.
1 /*
2  * nvbio
3  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <nvbio/io/output_stream.h>
29 #include <nvbio/basic/console.h>
30 #include <zlib/zlib.h>
31 #include <lz4/lz4frame.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 namespace nvbio {
37 
38 GZOutputFile::GZOutputFile(const char* name, const char* comp)
39 {
40  char options_string[16];
41  sprintf( options_string, "w%s", comp);
42 
43  m_file = gzopen( name, options_string );
44 }
46 {
47  if (m_file)
48  gzclose( m_file );
49 }
50 
51 uint32 GZOutputFile::write(const uint32 bytes, const void* buffer)
52 {
53  if (bytes == 0)
54  return 0;
55 
56  const int r = gzwrite( m_file, buffer, bytes );
57  if (r <= 0)
58  {
59  gzclose( m_file );
60  m_file = NULL;
61  return 0;
62  }
63  return uint32(r);
64 }
65 
66 LZ4OutputFile::LZ4OutputFile(const char* name, const char* comp)
67 {
68  m_file = (FILE*)fopen( name, "wb" );
69  if (m_file == NULL)
70  return;
71 
72  m_buffer.resize( 1024*1024 );
73 
74  // create a compression context
76 
77  LZ4F_preferences_t* preferences = (LZ4F_preferences_t*)calloc( sizeof(LZ4F_preferences_t), 1u );
78  // TODO: handle compression modes
79 
80  const size_t compressed_bytes = LZ4F_compressBegin( m_context, &m_buffer[0], m_buffer.size(), preferences );
81 
82  if (compressed_bytes == 0)
83  return;
84 
85  // write down
86  if (fwrite( &m_buffer[0], 1u, compressed_bytes, (FILE*)m_file ) < compressed_bytes)
87  {
88  // an error has occurred, shutdown the file
89  fclose( (FILE*)m_file ); m_file = NULL;
90 
92  }
93 }
95 {
96  // flush any remaining data
97  if (m_context && m_file)
98  {
99  const size_t compressed_bytes = LZ4F_compressEnd( m_context, &m_buffer[0], m_buffer.size(), NULL );
100 
101  fwrite( &m_buffer[0], 1u, compressed_bytes, (FILE*)m_file );
102  }
103 
104  if (m_file)
105  fclose( (FILE*)m_file );
106 
107  if (m_context)
109 }
110 
111 uint32 LZ4OutputFile::write(const uint32 bytes, const void* buffer)
112 {
113  if (bytes == 0)
114  return 0;
115 
116  const size_t dst_max = LZ4F_compressBound( bytes, NULL );
117  if (m_buffer.size() <= dst_max)
118  m_buffer.resize( dst_max );
119 
120  // compress in-memory
121  const size_t compressed_bytes = LZ4F_compressUpdate( m_context, &m_buffer[0], m_buffer.size(), buffer, bytes, NULL );
122 
123  // check whether the compressor has actually produced any output
124  if (compressed_bytes == 0)
125  return bytes;
126 
127  // write down
128  if (fwrite( &m_buffer[0], 1u, compressed_bytes, (FILE*)m_file ) < compressed_bytes)
129  {
130  // an error has occurred, shutdown the file
131  fclose( (FILE*)m_file ); m_file = NULL;
132 
134  }
135  return bytes;
136 }
137 
138 // output file factory method
139 //
140 OutputStream* open_output_file(const char* file_name, const char* compressor, const char* options)
141 {
142  if (compressor == NULL || strcmp( compressor, "" ) == 0)
143  return new GZOutputFile( file_name, "T" );
144  else if (strcmp( compressor, "gzip" ) == 0 || strcmp( compressor, "gz" ) == 0)
145  return new GZOutputFile( file_name, options );
146  else if (strcmp( compressor, "lz4" ) == 0)
147  return new LZ4OutputFile( file_name, options );
148 
149  log_warning(stderr, "unknown output file compressor \"%s\"\n", compressor );
150  return NULL;
151 }
152 
153 } // namespace nvbio