Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add method sam_open_write #1055

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions hts.c
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,7 @@ int hts_close(htsFile *fp)
hts_idx_destroy(fp->idx);
free(fp->fn);
free(fp->fn_aux);
free((void *)fp->fnidx);
free(fp->line.s);
free(fp);
errno = save;
Expand All @@ -1242,6 +1243,11 @@ const htsFormat *hts_get_format(htsFile *fp)
return fp? &fp->format : NULL;
}

const char *hts_get_fn(htsFile *fp)
{
return fp? fp->fn : NULL;
}

const char *hts_format_file_extension(const htsFormat *format) {
if (!format)
return "?";
Expand Down
8 changes: 8 additions & 0 deletions htslib/hts.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,14 @@ int hts_close(htsFile *fp);
HTSLIB_EXPORT
const htsFormat *hts_get_format(htsFile *fp);

/*!
@abstract Returns the file's name
@param fp The file handle
@return Read-only pointer to the file's fn field.
*/
HTSLIB_EXPORT
const char *hts_get_fn(htsFile *fp);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other parts of the API that have …fn in API function names? I'd rather spell it out as …filename (and it needs to be clear what if any relationship this has to hts_set_fai_filename).


/*!
@ abstract Returns a string containing the file format extension.
@ param format Format structure containing the file type.
Expand Down
20 changes: 17 additions & 3 deletions htslib/sam.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,8 +1089,7 @@ int bam_set_qname(bam1_t *b, const char *qname);
/** @param fp File handle for the data file being written.
@param h Bam header structured (needed for BAI and CSI).
@param min_shift 0 for BAI, or larger for CSI (CSI defaults to 14).
@param fnidx Filename to write index to. This pointer must remain valid
until after sam_idx_save is called.
@param fnidx Filename to write index to.
@return 0 on success, <0 on failure.

@note This must be called after the header has been written, but before
Expand Down Expand Up @@ -1325,6 +1324,20 @@ const char *sam_parse_region(sam_hdr_t *h, const char *s, int *tid,
const char *mode,
const char *format);

/// sam_open_write - Open a file for writing only
/** The method opens a new alignment file for writing, writes header hdr to it
* and attaches the header struct to the returned htsFile struct.
* If successful, ownership of hdr is given to the htsFile struct and hdr
* should not be freed separately.
* @param fn Name of the file
* @param h Pointer to the header previously read or created
* @param mode Pointer to the mode string (must contain "w")
* @param fmt Pointer to the format
* @return Pointer to the htsFile (with hdr) on success, NULL on failure
*/
HTSLIB_EXPORT
htsFile *sam_open_write(const char *fn, sam_hdr_t *hdr, const char *mode, const htsFormat *fmt);

HTSLIB_EXPORT
int sam_hdr_change_HD(sam_hdr_t *h, const char *key, const char *val);

Expand All @@ -1343,7 +1356,8 @@ const char *sam_parse_region(sam_hdr_t *h, const char *s, int *tid,
int sam_read1(samFile *fp, sam_hdr_t *h, bam1_t *b) HTS_RESULT_USED;
/// sam_write1 - Write a record to a file
/** @param fp Pointer to the destination file
* @param h Pointer to the header structure previously read
* @param h Pointer to the header structure previously read. Can be NULL,
* if fp has a non-NULL pointer to a valid header struct.
* @param b Pointer to the record to be written
* @return >= 0 on successfully writing the record, -1 on error
*/
Expand Down
34 changes: 32 additions & 2 deletions sam.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,9 @@ int bam_index_build(const char *fn, int min_shift)
// Initialise fp->idx for the current format type.
// This must be called after the header has been written but no other data.
int sam_idx_init(htsFile *fp, sam_hdr_t *h, int min_shift, const char *fnidx) {
fp->fnidx = fnidx;
fp->fnidx = strdup(fnidx);
if (!fp->fnidx) return -1;

if (fp->format.format == bam || fp->format.format == bcf ||
(fp->format.format == sam && fp->format.compression == bgzf)) {
int n_lvls, fmt = HTS_FMT_CSI;
Expand Down Expand Up @@ -1671,6 +1673,30 @@ int sam_hdr_write(htsFile *fp, const sam_hdr_t *h)
return 0;
}

htsFile *sam_open_write(const char *fn, sam_hdr_t *hdr, const char *mode, const htsFormat *fmt) {
htsFile *sf = NULL;
if (fn && mode) {
if (strchr(mode, 'w')) {
sf = hts_open_format(fn, mode, fmt);
if (sf) {
if (sam_hdr_write(sf, hdr) < 0) {
hts_log_error("Writing header to file \"%s\" failed", fn);
sam_close(sf);
sf = NULL;
} else {
if (sf->bam_header)
sam_hdr_destroy(sf->bam_header);
sf->bam_header = hdr;
}
}
} else {
hts_log_error("Only write mode allowed");
}
}

return sf;
}

static int old_sam_hdr_change_HD(sam_hdr_t *h, const char *key, const char *val)
{
char *p, *q, *beg = NULL, *end = NULL, *newtext;
Expand Down Expand Up @@ -3192,8 +3218,12 @@ int sam_format1(const bam_hdr_t *h, const bam1_t *b, kstring_t *str)

// Sadly we need to be able to modify the bam_hdr here so we can
// reference count the structure.
int sam_write1(htsFile *fp, const sam_hdr_t *h, const bam1_t *b)
int sam_write1(htsFile *fp, const sam_hdr_t *hdr, const bam1_t *b)
{
if (!fp || !b) { errno = EINVAL; return -1; }
const sam_hdr_t *h = hdr ? hdr : fp->bam_header;
if (!h) { hts_log_error("No header available for file \"%s\"", fp->fn); return -1; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h == NULL here is an error in the program, not a user error. So there's not much point reporting it to the user (they can't do anything about it!), but it does need to set errno (as other error paths do).


switch (fp->format.format) {
case binary_format:
fp->format.category = sequence_data;
Expand Down
14 changes: 12 additions & 2 deletions vcf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3295,7 +3295,12 @@ static int vcf_idx_init(htsFile *fp, bcf_hdr_t *h, int min_shift, const char *fn
fp->idx = NULL;
return -1;
}
fp->fnidx = fnidx;
fp->fnidx = strdup(fnidx);
if (!fp->fnidx) {
hts_idx_destroy(fp->idx);
fp->idx = NULL;
return -1;
}

return 0;
}
Expand All @@ -3315,7 +3320,12 @@ int bcf_idx_init(htsFile *fp, bcf_hdr_t *h, int min_shift, const char *fnidx) {

fp->idx = hts_idx_init(nids, HTS_FMT_CSI, bgzf_tell(fp->fp.bgzf), min_shift, n_lvls);
if (!fp->idx) return -1;
fp->fnidx = fnidx;
fp->fnidx = strdup(fnidx);
if (!fp->fnidx) {
hts_idx_destroy(fp->idx);
fp->idx = NULL;
return -1;
}

return 0;
}
Expand Down