%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file
Open a stream to write a file.
*/
#ifndef DK4CONF_H_INCLUDED
#include "dk4conf.h"
#endif
#ifndef DK4TYPES_H_INCLUDED
#include "dk4types.h"
#endif
#ifndef DK4ERROR_H_INCLUDED
#include "dk4error.h"
#endif
#ifndef DK4STRM_H_INCLUDED
#include "dk4strm.h"
#endif
#ifndef DK4STRMF_H_INCLUDED
#include "dk4strmf.h"
#endif
#ifndef DK4STRMG_H_INCLUDED
#include "dk4strmg.h"
#endif
#ifndef DK4STRMB_H_INCLUDED
#include "dk4strmb.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Open a stream to write a file.
CRT on Windows: Optional, disabling CRT reduces functionality
by disabling the gzip and bzip2 compression libraries.
@param filename File name of file to write.
@param erp Error report, may be NULL.
@return Pointer to stream on success, NULL on error.
- DK4_E_INVALID_ARGUMENTS
if filename is NULL,
- DK4_E_MATH_OVERFLOW
if ibs or obs is too large,
- DK4_E_MEMORY_ALLOCATION_FAILED
if allocation of input or output buffer failed.
*/
dk4_stream_t *
dk4stream_open_file_writer(const dkChar *filename, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4conf.h"
#if DK4_ON_WINDOWS && DK4_WIN_DENY_CRT
#ifndef WINDOWS_H_INCLUDED
#include
#define WINDOWS_H_INCLUDED 1
#endif
#ifndef DK4STRMH_H_INCLUDED
#include "dk4strmh.h"
#endif
#endif
#include "dk4strmw.h"
#ifndef DK4FD_H_INCLUDED
#include "dk4fd.h"
#endif
#ifndef DK4PATH_H_INCLUDED
#include "dk4pathd.h"
#endif
#ifndef DK4STRD_H_INCLUDED
#include "dk4strd.h"
#endif
#ifndef DK4FOPD_H_INCLUDED
#include "dk4fopd.h"
#endif
$!trace-include
/** Compression suffixes.
*/
static const dkChar * const dk4strmw_co_su[] = {
$!string-table macro=dkT
.gz
.svgz
.bz2
$!end
};
/** File mode for binary writing.
*/
static const char dk4strmw_c8_mode[] = { "wb" };
/** File mode for binary writing.
*/
static const dkChar dk4strmw_dk_mode[] = { dkT("wb") };
dk4_stream_t *
dk4stream_open_file_writer(const dkChar *filename, dk4_er_t *erp)
{
dk4_stream_t *back = NULL; /* Function result */
dkChar *p1 = NULL; /* File name suffix */
#if DK4_HAVE_ZLIB_H && (!(DK4_ON_WINDOWS && DK4_WIN_DENY_CRT))
gzFile gzf = NULL; /* gzip compressed output file */
#endif
#if DK4_HAVE_BZLIB_H && (!(DK4_ON_WINDOWS && DK4_WIN_DENY_CRT))
BZFILE *bzf = NULL; /* bzip2 compressed output file */
#endif
FILE *fipo = NULL; /* Output file */
#if DK4_ON_WINDOWS && DK4_WIN_DENY_CRT
HANDLE fha = INVALID_HANDLE_VALUE;
DWORD dwattr = (DWORD)0UL;
#endif
int coi = -1; /* Compression algorithm index */
#if DK4_CHAR_SIZE > 1
int fd = -1; /* File descriptor */
#endif
$? "+ dk4stream_open_file_writer \"%!ds\"", TR_STR(filename)
if (NULL != filename) {
p1 = dk4path_get_suffix(filename, erp);
if (NULL != p1) { $? ". suffix \"%!ds\"", p1
coi = dk4str_array_index(
dk4strmw_co_su, p1, DK4_HAVE_CASE_INSENSITIVE_PATHNAMES
);
if (0 > coi) { coi = -1; }
}
#if TRACE_DEBUG
else { $? ". no suffix"
}
#endif
if (0 != dk4fopen_check(filename, 1, DK4_FOPEN_SC_IS_REGULAR, erp)) {
switch (coi) {
case 0: case 1: { $? ". gzip"
#if DK4_HAVE_ZLIB_H && (!(DK4_ON_WINDOWS && DK4_WIN_DENY_CRT))
#if DK4_CHAR_SIZE > 1
/* +++++ gzip, wchar_t */
$? ". gzip mit wchar_t"
fd = dk4fd_wc_open(
filename,
(DK4_O_WRONLY | DK4_O_BINARY | DK4_O_TRUNC | DK4_O_CREAT),
erp
);
if (-1 < fd) {
gzf = gzdopen(fd, dk4strmw_c8_mode);
if (NULL != gzf) {
back = dk4stream_open_for_gzfile_with_close(
gzf, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
gzclose(gzf);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! failed to open gzf"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
(void)dk4fd_close(fd, NULL);
}
}
#if TRACE_DEBUG
else { $? "! failed to open fd"
}
#endif
/* ----- gzip, wchar_t */
#else
/* +++++ gzip, char */
$? ". gzip char"
gzf = gzopen(filename, dk4strmw_c8_mode);
if (NULL != gzf) {
back = dk4stream_open_for_gzfile_with_close(
gzf, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
gzclose(gzf);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! failed to open gzf"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
}
/* ----- gzip, char */
#endif
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
#endif
} break;
case 2: { $? ". bzip"
#if DK4_HAVE_BZLIB_H && (!(DK4_ON_WINDOWS && DK4_WIN_DENY_CRT))
#if DK4_CHAR_SIZE > 1
/* +++++ bzip2, wchar_t */
$? ". bzip2 wchar_t"
fd = dk4fd_wc_open(
filename,
(DK4_O_WRONLY | DK4_O_BINARY | DK4_O_TRUNC | DK4_O_CREAT),
erp
);
if (-1 < fd) {
bzf = BZ2_bzdopen(fd, dk4strmw_c8_mode);
if (NULL != bzf) {
back = dk4stream_open_for_bzfile_with_close(
bzf, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
BZ2_bzclose(bzf);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! failed to open bzf"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
(void)dk4fd_close(fd, NULL);
}
} else { $? "! failed to open fd"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
}
/* ----- bzip2, wchar_t */
#else
/* +++++ bzip2, char */
$? ". bzip2 char"
bzf = BZ2_bzopen(filename, dk4strmw_c8_mode);
if (NULL != bzf) {
back = dk4stream_open_for_bzfile_with_close(
bzf, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
BZ2_bzclose(bzf);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! failed to open bzf"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
}
/* ----- bzip2, char */
#endif
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
#endif
} break;
default: { $? ". plain file"
#if DK4_ON_WINDOWS && DK4_WIN_DENY_CRT
$? ". Windows without CRT"
dwattr = FILE_ATTRIBUTE_NORMAL;
dwattr |= FILE_FLAG_BACKUP_SEMANTICS;
dwattr |= FILE_FLAG_SEQUENTIAL_SCAN;
#if DK4_CHAR_SIZE > 1
fha = CreateFileW(
filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, dwattr, NULL
);
#else
fha = CreateFileA(
filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, dwattr, NULL
);
#endif
if (INVALID_HANDLE_VALUE != fha) {
back = dk4stream_open_for_windows_handle_with_close(
fha, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
(void)CloseHandle(fha);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! CreataeFile failed"
dk4error_set_simple_error_code(erp, DK4_E_OPEN_WRITE_FAILED);
}
#else
$? ". Windows with CRT allowed"
fipo = dk4fopen(
filename, dk4strmw_dk_mode, DK4_FOPEN_SC_IS_REGULAR, erp
);
if (NULL != fipo) {
back = dk4stream_open_for_file_with_close(
fipo, DK4_STREAM_WRITE, 1024, 4096, erp
);
if (NULL == back) { $? "! failed to open stream"
(void)fclose(fipo);
}
#if TRACE_DEBUG
else { $? ". stream opened"
}
#endif
} else { $? "! fipo"
}
#endif
} break;
}
} else { $? "! file check failed"
}
} else { $? "! no filename"
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
$? "- dk4stream_open_file_writer %d", TR_IPTR(back)
return back;
}