<commit_before>// Copyright 2013-2014 EMBL-EBI
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdlib.h>
#include <string.h> 

#include "wiggleIterator.h"

typedef struct bedReaderData_st {
	char  *filename;
	FILE * file;
	char * chrom;
	int stop;
} BedReaderData;

void BedReaderPop(WiggleIterator * wi) {
	BedReaderData * data = (BedReaderData *) wi->data;
	char line[5000];
	char chrom[1000];
	char sign;
	int start, finish;

	if (wi->done)
		return;

	while (fgets(line, 5000, data->file)) {
		if (line[0] == '#' || line[0] == EOF)
			continue;

		sscanf(line, "%s\t%i\t%i\t%*s\t%c", chrom, &start, &finish, &sign);

		if (strcmp(chrom, wi->chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && start < wi->start)) {
			fprintf(stderr, "Bed file %s is not sorted!\n", data->filename);
			exit(1);
		}

		if (sign == '+')
			wi->strand = 1;
		else if (sign == '-')
			wi->strand = -1;
		else
			wi->strand = 0;

		// Conversion from 0 to 1-based...
		wi->start = start + 1;
		wi->finish = finish + 1;

		// The reason for creating a new string instead of simply 
		// overwriting is that other functions may still be pointin
		// at the old label
		if (wi->chrom[0] == '\0' || strcmp(wi->chrom, chrom)) {
			wi->chrom = (char *) calloc(strlen(chrom), sizeof(char));
			strcpy(wi->chrom, chrom);
		}

		if (data->stop > 0) {
			if ((wi->start >= data->stop && strcmp(wi->chrom, data->chrom) == 0) || strcmp(wi->chrom, data->chrom) > 0) {
				wi->done = true;
				return;
			} else if (wi->finish > data->stop) {
				wi->finish = data->stop;
			}
		}

		return;
	} 

	fclose(data->file);
	data->file = NULL;
	wi->done = true;
}

void BedReaderSeek(WiggleIterator * wi, const char * chrom, int start, int finish) {
	BedReaderData * data = (BedReaderData*) wi->data;

	data->stop = finish;
	data->chrom = chrom;

	if (!data->file || strcmp(chrom, wi->chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && start < wi->start)) {
		if (data->file)
			fclose(data->file);
		if (!(data->file = fopen(data->filename, "r"))) {
			fprintf(stderr, "Could not open input file %s\n", data->filename);
			exit(1);
		}
		wi->done = false;
		pop(wi);
	}

	while (!wi->done && (strcmp(wi->chrom, chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && wi->finish < start))) 
		pop(wi);

	if (!wi->done && strcmp(chrom, wi->chrom) == 0 && wi->start < start)
		wi->start = start;
}

WiggleIterator * BedReader(char * filename) {
	BedReaderData * data = (BedReaderData *) calloc(1, sizeof(BedReaderData));
	data->filename = filename;
	data->stop = -1;
	if (!(data->file = fopen(filename, "r"))) {
		fprintf(stderr, "Could not open bed file %s\n", filename);
		exit(1);
	}
	WiggleIterator * res = newWiggleIterator(data, &BedReaderPop, &BedReaderSeek, 0);
	res->overlaps = true;
	return res;
}
<commit_msg>Improved unsorted error message to include coords<commit_after>// Copyright 2013-2014 EMBL-EBI
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stdlib.h>
#include <string.h> 

#include "wiggleIterator.h"

typedef struct bedReaderData_st {
	char  *filename;
	FILE * file;
	char * chrom;
	int stop;
} BedReaderData;

void BedReaderPop(WiggleIterator * wi) {
	BedReaderData * data = (BedReaderData *) wi->data;
	char line[5000];
	char chrom[1000];
	char sign;
	int start, finish;

	if (wi->done)
		return;

	while (fgets(line, 5000, data->file)) {
		if (line[0] == '#' || line[0] == EOF)
			continue;

		sscanf(line, "%s\t%i\t%i\t%*s\t%c", chrom, &start, &finish, &sign);

		if (strcmp(chrom, wi->chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && start < wi->start)) {
			fprintf(stderr, "Bed file %s is not sorted!\nPosition %s:%i is before %s:%i\n", data->filename, chrom, start, wi->chrom, wi->start);
			exit(1);
		}

		if (sign == '+')
			wi->strand = 1;
		else if (sign == '-')
			wi->strand = -1;
		else
			wi->strand = 0;

		// Conversion from 0 to 1-based...
		wi->start = start + 1;
		wi->finish = finish + 1;

		// The reason for creating a new string instead of simply 
		// overwriting is that other functions may still be pointin
		// at the old label
		if (wi->chrom[0] == '\0' || strcmp(wi->chrom, chrom)) {
			wi->chrom = (char *) calloc(strlen(chrom), sizeof(char));
			strcpy(wi->chrom, chrom);
		}

		if (data->stop > 0) {
			if ((wi->start >= data->stop && strcmp(wi->chrom, data->chrom) == 0) || strcmp(wi->chrom, data->chrom) > 0) {
				wi->done = true;
				return;
			} else if (wi->finish > data->stop) {
				wi->finish = data->stop;
			}
		}

		return;
	} 

	fclose(data->file);
	data->file = NULL;
	wi->done = true;
}

void BedReaderSeek(WiggleIterator * wi, const char * chrom, int start, int finish) {
	BedReaderData * data = (BedReaderData*) wi->data;

	data->stop = finish;
	data->chrom = chrom;

	if (!data->file || strcmp(chrom, wi->chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && start < wi->start)) {
		if (data->file)
			fclose(data->file);
		if (!(data->file = fopen(data->filename, "r"))) {
			fprintf(stderr, "Could not open input file %s\n", data->filename);
			exit(1);
		}
		wi->done = false;
		pop(wi);
	}

	while (!wi->done && (strcmp(wi->chrom, chrom) < 0 || (strcmp(chrom, wi->chrom) == 0 && wi->finish < start))) 
		pop(wi);

	if (!wi->done && strcmp(chrom, wi->chrom) == 0 && wi->start < start)
		wi->start = start;
}

WiggleIterator * BedReader(char * filename) {
	BedReaderData * data = (BedReaderData *) calloc(1, sizeof(BedReaderData));
	data->filename = filename;
	data->stop = -1;
	if (!(data->file = fopen(filename, "r"))) {
		fprintf(stderr, "Could not open bed file %s\n", filename);
		exit(1);
	}
	WiggleIterator * res = newWiggleIterator(data, &BedReaderPop, &BedReaderSeek, 0);
	res->overlaps = true;
	return res;
}

{'fraction_non_alphanumeric': 0.1775014979029359, 'fraction_numerical': 0.015278609946075494, 'mean_word_length': 3.416005291005291, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 129, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3987186', 'n_tokens_mistral': 2676, 'n_tokens_neox': 2342, 'n_words': 690}