mirror of
https://github.com/chhylp123/hifiasm.git
synced 2026-09-24 06:18:13 +08:00
Using klib
This commit is contained in:
+14
-11
@@ -1,28 +1,31 @@
|
||||
#include "Assembly.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "Process_Read.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Counting()
|
||||
{
|
||||
Read r;
|
||||
init_Read(&r);
|
||||
|
||||
|
||||
kseq_t *seq = (kseq_t*)calloc(1, sizeof(kseq_t));
|
||||
|
||||
|
||||
long long read_number = 0;
|
||||
|
||||
while (inputRead(&r))
|
||||
while (get_read(seq))
|
||||
{
|
||||
|
||||
fprintf(stderr,"%s\n",r.name);
|
||||
|
||||
fprintf(stderr,"%s\n",r.seq);
|
||||
|
||||
fprintf(stderr,"@%s\n",seq->name.s);
|
||||
fprintf(stderr,"%s\n",seq->seq.s);
|
||||
fprintf(stderr,"+\n");
|
||||
fprintf(stderr,"%s\n",r.qual);
|
||||
|
||||
fprintf(stderr,"%s\n",seq->qual.s);
|
||||
|
||||
read_number++;
|
||||
|
||||
clear_read(&r);
|
||||
}
|
||||
|
||||
fprintf(stdout, "read_number: %lld\n",read_number);
|
||||
|
||||
+17
-30
@@ -1,7 +1,7 @@
|
||||
#include "CommandLines.h"
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include "ketopt.h"
|
||||
|
||||
char* read_file_name = NULL;
|
||||
char* output_file_name = NULL;
|
||||
@@ -17,41 +17,28 @@ void Print_H()
|
||||
|
||||
int CommandLine_process (int argc, char *argv[])
|
||||
{
|
||||
int o;
|
||||
int index;
|
||||
|
||||
static struct option longOptions[] =
|
||||
{
|
||||
{"seq", required_argument, 0, 'q'},
|
||||
{"threads", required_argument, 0, 't'},
|
||||
{"threads", required_argument, 0, 'o'},
|
||||
{0, 0, 0, 0},
|
||||
static ko_longopt_t longopts[] = {
|
||||
{ "help", ko_no_argument, 100},
|
||||
{ "seq", ko_required_argument, 101},
|
||||
{ "output", ko_required_argument, 102},
|
||||
{ "thread", ko_required_argument, 103},
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
ketopt_t opt = KETOPT_INIT;
|
||||
|
||||
while ( (o = getopt_long ( argc, argv, "q:t:o:", longOptions, &index)) != -1 )
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case 'q':
|
||||
read_file_name = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
output_file_name = optarg;
|
||||
break;
|
||||
case 't':
|
||||
thread_num = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
fprintf(stderr, "Unrecognized option!\n" );
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
Print_H();
|
||||
return 0;
|
||||
}
|
||||
int i, c;
|
||||
while ((c = ketopt(&opt, argc, argv, 1, "ht:o:q:", longopts)) >= 0) {
|
||||
if (c == 100 || c == 'h') Print_H();
|
||||
else if (c == 103 || c == 't') thread_num = atoi(opt.arg);
|
||||
else if (c == 102 || c == 'o') output_file_name = opt.arg;
|
||||
else if (c == 101 || c == 'q') read_file_name = opt.arg;
|
||||
else if (c == '?') printf("unknown opt: -%c\n", opt.opt? opt.opt : ':');
|
||||
else if (c == ':') printf("missing arg: -%c\n", opt.opt? opt.opt : ':');
|
||||
}
|
||||
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
Print_H();
|
||||
|
||||
+35
-140
@@ -2,163 +2,58 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
int format = -1;
|
||||
FILE *_r_fp = NULL;
|
||||
gzFile g_r_fp;
|
||||
gzFile fp;
|
||||
kseq_t *seq;
|
||||
|
||||
|
||||
int check_file_format(char *fileName)
|
||||
void init_kseq(char* file)
|
||||
{
|
||||
int i = 0;
|
||||
fp = gzopen(file, "r");
|
||||
seq = kseq_init(fp);
|
||||
}
|
||||
|
||||
char* file_extention;
|
||||
i = strlen(fileName) - 1;
|
||||
while (i >= 0 && fileName[i] != '.')
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: the input read files must be FASTQ format (file extension: .fq or .fastq) or compressed FASTQ format (file extension: .fq.gz or .fastq.gz)!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((strcmp(".fq", fileName+i) == 0)
|
||||
||
|
||||
strcmp(".fastq", fileName + i) == 0)
|
||||
{
|
||||
return FASTQ;
|
||||
}
|
||||
else if (strcmp(".gz", fileName + i) == 0)
|
||||
{
|
||||
i--;
|
||||
while (i >= 0 && fileName[i] != '.')
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: the input read files must be FASTQ format (file extension: .fq or .fastq) or compressed FASTQ format (file extension: .fq.gz or .fastq.gz)!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ((strcmp(".fq.gz", fileName + i) == 0)
|
||||
||
|
||||
strcmp(".fastq.gz", fileName + i) == 0)
|
||||
{
|
||||
return FASTQGZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: the input read files must be FASTQ format (file extension: .fq or .fastq) or compressed FASTQ format (file extension: .fq.gz or .fastq.gz)!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr,
|
||||
"ERROR: the input read files must be FASTQ format (file extension: .fq or .fastq) or compressed FASTQ format (file extension: .fq.gz or .fastq.gz)!\n");
|
||||
exit(0);
|
||||
void destory_kseq()
|
||||
{
|
||||
kseq_destroy(seq);
|
||||
gzclose(fp);
|
||||
}
|
||||
|
||||
|
||||
int initiReadAllReads(char *fileName)
|
||||
inline void exchage_kstring_t(kstring_t* a, kstring_t* b)
|
||||
{
|
||||
|
||||
format = check_file_format(fileName);
|
||||
|
||||
if (format == FASTQ)
|
||||
{
|
||||
_r_fp = fopen(fileName, "r");
|
||||
|
||||
if (_r_fp == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stdout,
|
||||
" Read files are in FASTQ format...\n");
|
||||
}
|
||||
else if (format == FASTQGZ)
|
||||
{
|
||||
int fd = open(fileName, O_CREAT | O_RDONLY, 0666);
|
||||
g_r_fp = gzdopen(fd, "rb");
|
||||
|
||||
fprintf(stdout,
|
||||
" Read files are in compressed FASTQ format...\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: the input read files must be FASTQ format (file extension: .fq or .fastq) or compressed FASTQ format (file extension: .fq.gz or .fastq.gz)!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
kstring_t tmp;
|
||||
tmp = *a;
|
||||
*a = *b;
|
||||
*b = tmp;
|
||||
}
|
||||
|
||||
#define BUFFER_SIZE 20000
|
||||
char Read_Buffer[BUFFER_SIZE];
|
||||
char true_flag[2];
|
||||
|
||||
|
||||
inline char *Input_line_from_file(char *seq)
|
||||
int get_read(kseq_t *s)
|
||||
{
|
||||
if (format == FASTQ)
|
||||
int l;
|
||||
|
||||
if ((l = kseq_read(seq)) >= 0)
|
||||
{
|
||||
return fgets(Read_Buffer, BUFFER_SIZE, _r_fp);
|
||||
|
||||
exchage_kstring_t(&seq->comment, &s->comment);
|
||||
exchage_kstring_t(&seq->name, &s->name);
|
||||
exchage_kstring_t(&seq->qual, &s->qual);
|
||||
exchage_kstring_t(&seq->seq, &s->seq);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq = gzgets(g_r_fp, seq, BUFFER_SIZE);
|
||||
|
||||
return (!gzeof(g_r_fp)) ? true_flag : NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline int get_whole_line(str_v* line)
|
||||
{
|
||||
while(Input_line_from_file(Read_Buffer))
|
||||
{
|
||||
append_str(line, Read_Buffer);
|
||||
|
||||
if (line->centext[line->length - 1] == '\n')
|
||||
{
|
||||
line->length--;
|
||||
line->centext[line->length] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int inputRead(Read *read)
|
||||
{
|
||||
int buffer_length;
|
||||
|
||||
if (get_whole_line(&read->name))
|
||||
{
|
||||
get_whole_line(&read->seq);
|
||||
Input_line_from_file(Read_Buffer);
|
||||
get_whole_line(&read->qual);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
+6
-64
@@ -4,73 +4,15 @@
|
||||
#include<stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "kseq.h"
|
||||
|
||||
|
||||
#define FASTQ 1
|
||||
#define FASTQGZ 2
|
||||
KSEQ_INIT(gzFile, gzread)
|
||||
|
||||
#define NAME_SZIE 25
|
||||
#define SEQ_SZIE 20000
|
||||
void init_kseq(char* file);
|
||||
void destory_kseq();
|
||||
int get_read(kseq_t *s);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char* centext;
|
||||
uint32_t length;
|
||||
uint32_t size;
|
||||
|
||||
}str_v;
|
||||
|
||||
|
||||
inline void init_str_v(str_v* buf, uint32_t length)
|
||||
{
|
||||
buf->size = length + 1;
|
||||
buf->length = 0;
|
||||
buf->centext = (char*)malloc(sizeof(char)*buf->size);
|
||||
}
|
||||
|
||||
|
||||
inline void append_str(str_v* buf, char* input)
|
||||
{
|
||||
int length = strlen(input);
|
||||
buf->length = buf->length + length;
|
||||
if (buf->length > buf->size)
|
||||
{
|
||||
buf->centext = (char*)realloc(buf->centext, buf->length + 1);
|
||||
}
|
||||
memcpy(buf->centext + buf->length - length, input, length);
|
||||
buf->centext[buf->length] = '\0';
|
||||
}
|
||||
|
||||
inline void clear_str(str_v* buf)
|
||||
{
|
||||
buf->length = 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
str_v name;
|
||||
str_v seq;
|
||||
str_v qual;
|
||||
|
||||
} Read;
|
||||
|
||||
inline void init_Read(Read* r)
|
||||
{
|
||||
init_str_v(&r->name, NAME_SZIE);
|
||||
init_str_v(&r->seq, SEQ_SZIE);
|
||||
init_str_v(&r->qual, SEQ_SZIE);
|
||||
}
|
||||
|
||||
inline void clear_read(Read* r)
|
||||
{
|
||||
clear_str(&r->name);
|
||||
clear_str(&r->seq);
|
||||
clear_str(&r->qual);
|
||||
}
|
||||
|
||||
|
||||
int initiReadAllReads(char *fileName);
|
||||
int inputRead(Read *read);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#ifndef KETOPT_H
|
||||
#define KETOPT_H
|
||||
|
||||
#include <string.h> /* for strchr() and strncmp() */
|
||||
|
||||
#define ko_no_argument 0
|
||||
#define ko_required_argument 1
|
||||
#define ko_optional_argument 2
|
||||
|
||||
typedef struct {
|
||||
int ind; /* equivalent to optind */
|
||||
int opt; /* equivalent to optopt */
|
||||
char *arg; /* equivalent to optarg */
|
||||
int longidx; /* index of a long option; or -1 if short */
|
||||
/* private variables not intended for external uses */
|
||||
int i, pos, n_args;
|
||||
} ketopt_t;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int has_arg;
|
||||
int val;
|
||||
} ko_longopt_t;
|
||||
|
||||
static ketopt_t KETOPT_INIT = { 1, 0, 0, -1, 1, 0, 0 };
|
||||
|
||||
static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */
|
||||
{
|
||||
int k;
|
||||
char *p = argv[j];
|
||||
for (k = 0; k < n; ++k)
|
||||
argv[j - k] = argv[j - k - 1];
|
||||
argv[j - k] = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line options and arguments
|
||||
*
|
||||
* This fuction has a similar interface to GNU's getopt_long(). Each call
|
||||
* parses one option and returns the option name. s->arg points to the option
|
||||
* argument if present. The function returns -1 when all command-line arguments
|
||||
* are parsed. In this case, s->ind is the index of the first non-option
|
||||
* argument.
|
||||
*
|
||||
* @param s status; shall be initialized to KETOPT_INIT on the first call
|
||||
* @param argc length of argv[]
|
||||
* @param argv list of command-line arguments; argv[0] is ignored
|
||||
* @param permute non-zero to move options ahead of non-option arguments
|
||||
* @param ostr option string
|
||||
* @param longopts long options
|
||||
*
|
||||
* @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if
|
||||
* argv[] is fully processed; '?' for an unknown option or an ambiguous
|
||||
* long option; ':' if an option argument is missing
|
||||
*/
|
||||
static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts)
|
||||
{
|
||||
int opt = -1, i0, j;
|
||||
if (permute) {
|
||||
while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0'))
|
||||
++s->i, ++s->n_args;
|
||||
}
|
||||
s->arg = 0, s->longidx = -1, i0 = s->i;
|
||||
if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') {
|
||||
s->ind = s->i - s->n_args;
|
||||
return -1;
|
||||
}
|
||||
if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */
|
||||
if (argv[s->i][2] == '\0') { /* a bare "--" */
|
||||
ketopt_permute(argv, s->i, s->n_args);
|
||||
++s->i, s->ind = s->i - s->n_args;
|
||||
return -1;
|
||||
}
|
||||
s->opt = 0, opt = '?', s->pos = -1;
|
||||
if (longopts) { /* parse long options */
|
||||
int k, n_exact = 0, n_partial = 0;
|
||||
const ko_longopt_t *o = 0, *o_exact = 0, *o_partial = 0;
|
||||
for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */
|
||||
for (k = 0; longopts[k].name != 0; ++k)
|
||||
if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) {
|
||||
if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k];
|
||||
else ++n_partial, o_partial = &longopts[k];
|
||||
}
|
||||
if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?';
|
||||
o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0;
|
||||
if (o) {
|
||||
s->opt = opt = o->val, s->longidx = o - longopts;
|
||||
if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1];
|
||||
if (o->has_arg == 1 && argv[s->i][j] == '\0') {
|
||||
if (s->i < argc - 1) s->arg = argv[++s->i];
|
||||
else opt = ':'; /* missing option argument */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { /* a short option */
|
||||
const char *p;
|
||||
if (s->pos == 0) s->pos = 1;
|
||||
opt = s->opt = argv[s->i][s->pos++];
|
||||
p = strchr((char*)ostr, opt);
|
||||
if (p == 0) {
|
||||
opt = '?'; /* unknown option */
|
||||
} else if (p[1] == ':') {
|
||||
if (argv[s->i][s->pos] == 0) {
|
||||
if (s->i < argc - 1) s->arg = argv[++s->i];
|
||||
else opt = ':'; /* missing option argument */
|
||||
} else s->arg = &argv[s->i][s->pos];
|
||||
s->pos = -1;
|
||||
}
|
||||
}
|
||||
if (s->pos < 0 || argv[s->i][s->pos] == 0) {
|
||||
++s->i, s->pos = 0;
|
||||
if (s->n_args > 0) /* permute */
|
||||
for (j = i0; j < s->i; ++j)
|
||||
ketopt_permute(argv, j, s->n_args);
|
||||
}
|
||||
s->ind = s->i - s->n_args;
|
||||
return opt;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
/* The MIT License
|
||||
|
||||
Copyright (c) 2008, 2009, 2011 Attractive Chaos <attractor@live.co.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Last Modified: 05MAR2012 */
|
||||
|
||||
#ifndef AC_KSEQ_H
|
||||
#define AC_KSEQ_H
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define KS_SEP_SPACE 0 // isspace(): \t, \n, \v, \f, \r
|
||||
#define KS_SEP_TAB 1 // isspace() && !' '
|
||||
#define KS_SEP_LINE 2 // line separator: "\n" (Unix) or "\r\n" (Windows)
|
||||
#define KS_SEP_MAX 2
|
||||
|
||||
#define __KS_TYPE(type_t) \
|
||||
typedef struct __kstream_t { \
|
||||
unsigned char *buf; \
|
||||
int begin, end, is_eof; \
|
||||
type_t f; \
|
||||
} kstream_t;
|
||||
|
||||
#define ks_err(ks) ((ks)->end == -1)
|
||||
#define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end)
|
||||
#define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0)
|
||||
|
||||
#define __KS_BASIC(type_t, __bufsize) \
|
||||
static inline kstream_t *ks_init(type_t f) \
|
||||
{ \
|
||||
kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \
|
||||
ks->f = f; \
|
||||
ks->buf = (unsigned char*)malloc(__bufsize); \
|
||||
return ks; \
|
||||
} \
|
||||
static inline void ks_destroy(kstream_t *ks) \
|
||||
{ \
|
||||
if (ks) { \
|
||||
free(ks->buf); \
|
||||
free(ks); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define __KS_GETC(__read, __bufsize) \
|
||||
static inline int ks_getc(kstream_t *ks) \
|
||||
{ \
|
||||
if (ks_err(ks)) return -3; \
|
||||
if (ks->is_eof && ks->begin >= ks->end) return -1; \
|
||||
if (ks->begin >= ks->end) { \
|
||||
ks->begin = 0; \
|
||||
ks->end = __read(ks->f, ks->buf, __bufsize); \
|
||||
if (ks->end == 0) { ks->is_eof = 1; return -1;} \
|
||||
if (ks->end == -1) { ks->is_eof = 1; return -3;}\
|
||||
} \
|
||||
return (int)ks->buf[ks->begin++]; \
|
||||
}
|
||||
|
||||
#ifndef KSTRING_T
|
||||
#define KSTRING_T kstring_t
|
||||
typedef struct __kstring_t {
|
||||
size_t l, m;
|
||||
char *s;
|
||||
} kstring_t;
|
||||
#endif
|
||||
|
||||
#ifndef kroundup32
|
||||
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
|
||||
#endif
|
||||
|
||||
#define __KS_GETUNTIL(__read, __bufsize) \
|
||||
static int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append) \
|
||||
{ \
|
||||
int gotany = 0; \
|
||||
if (dret) *dret = 0; \
|
||||
str->l = append? str->l : 0; \
|
||||
for (;;) { \
|
||||
int i; \
|
||||
if (ks_err(ks)) return -3; \
|
||||
if (ks->begin >= ks->end) { \
|
||||
if (!ks->is_eof) { \
|
||||
ks->begin = 0; \
|
||||
ks->end = __read(ks->f, ks->buf, __bufsize); \
|
||||
if (ks->end == 0) { ks->is_eof = 1; break; } \
|
||||
if (ks->end == -1) { ks->is_eof = 1; return -3; } \
|
||||
} else break; \
|
||||
} \
|
||||
if (delimiter == KS_SEP_LINE) { \
|
||||
for (i = ks->begin; i < ks->end; ++i) \
|
||||
if (ks->buf[i] == '\n') break; \
|
||||
} else if (delimiter > KS_SEP_MAX) { \
|
||||
for (i = ks->begin; i < ks->end; ++i) \
|
||||
if (ks->buf[i] == delimiter) break; \
|
||||
} else if (delimiter == KS_SEP_SPACE) { \
|
||||
for (i = ks->begin; i < ks->end; ++i) \
|
||||
if (isspace(ks->buf[i])) break; \
|
||||
} else if (delimiter == KS_SEP_TAB) { \
|
||||
for (i = ks->begin; i < ks->end; ++i) \
|
||||
if (isspace(ks->buf[i]) && ks->buf[i] != ' ') break; \
|
||||
} else i = 0; /* never come to here! */ \
|
||||
if (str->m - str->l < (size_t)(i - ks->begin + 1)) { \
|
||||
str->m = str->l + (i - ks->begin) + 1; \
|
||||
kroundup32(str->m); \
|
||||
str->s = (char*)realloc(str->s, str->m); \
|
||||
} \
|
||||
gotany = 1; \
|
||||
memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \
|
||||
str->l = str->l + (i - ks->begin); \
|
||||
ks->begin = i + 1; \
|
||||
if (i < ks->end) { \
|
||||
if (dret) *dret = ks->buf[i]; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if (!gotany && ks_eof(ks)) return -1; \
|
||||
if (str->s == 0) { \
|
||||
str->m = 1; \
|
||||
str->s = (char*)calloc(1, 1); \
|
||||
} else if (delimiter == KS_SEP_LINE && str->l > 1 && str->s[str->l-1] == '\r') --str->l; \
|
||||
str->s[str->l] = '\0'; \
|
||||
return str->l; \
|
||||
} \
|
||||
static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \
|
||||
{ return ks_getuntil2(ks, delimiter, str, dret, 0); }
|
||||
|
||||
#define KSTREAM_INIT(type_t, __read, __bufsize) \
|
||||
__KS_TYPE(type_t) \
|
||||
__KS_BASIC(type_t, __bufsize) \
|
||||
__KS_GETC(__read, __bufsize) \
|
||||
__KS_GETUNTIL(__read, __bufsize)
|
||||
|
||||
#define kseq_rewind(ks) ((ks)->last_char = (ks)->f->is_eof = (ks)->f->begin = (ks)->f->end = 0)
|
||||
|
||||
#define __KSEQ_BASIC(SCOPE, type_t) \
|
||||
SCOPE kseq_t *kseq_init(type_t fd) \
|
||||
{ \
|
||||
kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \
|
||||
s->f = ks_init(fd); \
|
||||
return s; \
|
||||
} \
|
||||
SCOPE void kseq_destroy(kseq_t *ks) \
|
||||
{ \
|
||||
if (!ks) return; \
|
||||
free(ks->name.s); free(ks->comment.s); free(ks->seq.s); free(ks->qual.s); \
|
||||
ks_destroy(ks->f); \
|
||||
free(ks); \
|
||||
}
|
||||
|
||||
/* Return value:
|
||||
>=0 length of the sequence (normal)
|
||||
-1 end-of-file
|
||||
-2 truncated quality string
|
||||
-3 error reading stream
|
||||
*/
|
||||
#define __KSEQ_READ(SCOPE) \
|
||||
SCOPE int kseq_read(kseq_t *seq) \
|
||||
{ \
|
||||
int c,r; \
|
||||
kstream_t *ks = seq->f; \
|
||||
if (seq->last_char == 0) { /* then jump to the next header line */ \
|
||||
while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '@'); \
|
||||
if (c < 0) return c; /* end of file or error*/ \
|
||||
seq->last_char = c; \
|
||||
} /* else: the first header char has been read in the previous call */ \
|
||||
seq->comment.l = seq->seq.l = seq->qual.l = 0; /* reset all members */ \
|
||||
if ((r=ks_getuntil(ks, 0, &seq->name, &c)) < 0) return r; /* normal exit: EOF or error */ \
|
||||
if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ \
|
||||
if (seq->seq.s == 0) { /* we can do this in the loop below, but that is slower */ \
|
||||
seq->seq.m = 256; \
|
||||
seq->seq.s = (char*)malloc(seq->seq.m); \
|
||||
} \
|
||||
while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '+' && c != '@') { \
|
||||
if (c == '\n') continue; /* skip empty lines */ \
|
||||
seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \
|
||||
ks_getuntil2(ks, KS_SEP_LINE, &seq->seq, 0, 1); /* read the rest of the line */ \
|
||||
} \
|
||||
if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \
|
||||
if (seq->seq.l + 1 >= seq->seq.m) { /* seq->seq.s[seq->seq.l] below may be out of boundary */ \
|
||||
seq->seq.m = seq->seq.l + 2; \
|
||||
kroundup32(seq->seq.m); /* rounded to the next closest 2^k */ \
|
||||
seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \
|
||||
} \
|
||||
seq->seq.s[seq->seq.l] = 0; /* null terminated string */ \
|
||||
if (c != '+') return seq->seq.l; /* FASTA */ \
|
||||
if (seq->qual.m < seq->seq.m) { /* allocate memory for qual in case insufficient */ \
|
||||
seq->qual.m = seq->seq.m; \
|
||||
seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \
|
||||
} \
|
||||
while ((c = ks_getc(ks)) >= 0 && c != '\n'); /* skip the rest of '+' line */ \
|
||||
if (c == -1) return -2; /* error: no quality string */ \
|
||||
while ((c = ks_getuntil2(ks, KS_SEP_LINE, &seq->qual, 0, 1) >= 0 && seq->qual.l < seq->seq.l)); \
|
||||
if (c == -3) return -3; /* stream error */ \
|
||||
seq->last_char = 0; /* we have not come to the next header line */ \
|
||||
if (seq->seq.l != seq->qual.l) return -2; /* error: qual string is of a different length */ \
|
||||
return seq->seq.l; \
|
||||
}
|
||||
|
||||
#define __KSEQ_TYPE(type_t) \
|
||||
typedef struct { \
|
||||
kstring_t name, comment, seq, qual; \
|
||||
int last_char; \
|
||||
kstream_t *f; \
|
||||
} kseq_t;
|
||||
|
||||
#define KSEQ_INIT2(SCOPE, type_t, __read) \
|
||||
KSTREAM_INIT(type_t, __read, 16384) \
|
||||
__KSEQ_TYPE(type_t) \
|
||||
__KSEQ_BASIC(SCOPE, type_t) \
|
||||
__KSEQ_READ(SCOPE)
|
||||
|
||||
#define KSEQ_INIT(type_t, __read) KSEQ_INIT2(static, type_t, __read)
|
||||
|
||||
#define KSEQ_DECLARE(type_t) \
|
||||
__KS_TYPE(type_t) \
|
||||
__KSEQ_TYPE(type_t) \
|
||||
extern kseq_t *kseq_init(type_t fd); \
|
||||
void kseq_destroy(kseq_t *ks); \
|
||||
int kseq_read(kseq_t *seq);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user