⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multi_file.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>

#include <windows.h> /* for CharNext() */
#include "registry.h" /* for get_file_mode() */
#include "config.h"

#define MULTI_FILE_C
#include "multi_file.h"

/************* type and function definition **************/

typedef struct {
	__int64 length;
	__int64 offset;
	int   fd;
	char *path;
	int   padding[2];
} MF_FILE_INFO;
	

typedef struct {
	__int64  total;
	int count;
	int index;
	MF_FILE_INFO *info;
} MF_PRIVATE_DATA;

MULTI_FILE *open_multi_file(const char *path);

static int mf_close(void *multi_file);
static __int64 mf_tell(void *multi_file);
static __int64 mf_seek(void *multi_file, __int64 offset, int origin);
static int mf_read(void *multi_file, void *buf, int length);
static __int64 sf_tell(void *multi_file);
static __int64 sf_seek(void *multi_file, __int64 offset, int origin);
static int sf_read(void *multi_file, void *buf, int length);

static int mf_count(void *multi_file);
static __int64 mf_border(void *multi_file, int index);

static int try_next(char *path);

/******************** implementation ********************/

MULTI_FILE *open_multi_file(const char *path)
{
	__int64 len;
	
	MULTI_FILE *r;
	MF_PRIVATE_DATA *prv;
	int fd;

	int i,n;
	char *work;
	void *tmp;

	int mode;
	
	r = (MULTI_FILE *)calloc(1, sizeof(MULTI_FILE));
	if(r == NULL){
		return NULL;
	}

	prv = (MF_PRIVATE_DATA *)calloc(1, sizeof(MF_PRIVATE_DATA));
	if(prv == NULL){
		free(r);
		return NULL;
	}

	fd = _open(path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
	if(fd < 0){
		free(prv);
		free(r);
		return NULL;
	}

	n = strlen(path)+1;
	work = (char *)malloc(n);
	if(work == NULL){
		_close(fd);
		free(prv);
		free(r);
		return NULL;
	}
	memcpy(work, path, n);
	
	prv->info = (MF_FILE_INFO *)malloc(sizeof(MF_FILE_INFO));
	if(prv->info == NULL){
		free(work);
		_close(fd);
		free(prv);
		free(r);
		return NULL;
	}

	mode = get_file_mode();

	while(fd >= 0){
		tmp = realloc(prv->info, sizeof(MF_FILE_INFO)*(prv->count+1));
		if(tmp == NULL){
			_close(fd);
			fd = -1;
			break;
		}
		prv->info = (MF_FILE_INFO *)tmp;

		len = _lseeki64(fd, 0, SEEK_END);
		_lseeki64(fd, 0, SEEK_SET);
		_close(fd);
		
		i = prv->count;

		prv->info[i].length = len;
		prv->info[i].offset = prv->total;
		prv->info[i].fd = -1;
		prv->info[i].path = malloc(n);
		if(prv->info[i].path == NULL){
			break;
		}
		memcpy(prv->info[i].path, work, n);
		
		prv->total += len;

		prv->count += 1;

		if(mode & M2V_CONFIG_MULTI_FILE){
			fd = try_next(work);
		}else{
			fd = -1;
		}
	}

	if(prv->count == 0){
		free(prv->info);
		free(work);
		if(fd >= 0){
			_close(fd);
		}
		free(prv);
		free(r);
		return NULL;
	}

	free(work);

	r->private_data = prv;
	r->close = mf_close;
	if(prv->count == 1){
		r->tell = sf_tell;
		r->seek = sf_seek;
		r->read = sf_read;
		prv->info[0].fd = _open(prv->info[0].path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
	}else{
		r->tell = mf_tell;
		r->seek = mf_seek;
		r->read = mf_read;
	}
	r->count = mf_count;
	r->border = mf_border;
	
	return r;
}

static int mf_close(void *multi_file)
{
	MULTI_FILE *p;
	MF_PRIVATE_DATA *prv;
	
	int i;

	p = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)p->private_data;
	if(prv == NULL){
		return 0;
	}
	
	for(i=0;i<prv->count;i++){
		if(prv->info[i].fd >= 0){
			_close(prv->info[i].fd);
			prv->info[i].fd = -1;
		}
		if(prv->info[i].path){
			free(prv->info[i].path);
			prv->info[i].path = NULL;
		}
	}

	free(prv->info);
	free(prv);
	memset(p, 0, sizeof(MULTI_FILE));
	free(p);

	return 1;
}

static __int64 mf_tell(void *multi_file)
{
	__int64 r;

	MULTI_FILE *p;
	MF_PRIVATE_DATA *prv;

	int i;
	
	p = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)p->private_data;

	if(prv == NULL){
		return 0;
	}

	i = prv->index;
	if(i == prv->count){
		return prv->total;
	}

	r = prv->info[i].offset;
	if(prv->info[i].fd >= 0){
		r += _telli64(prv->info[i].fd);
	}

	return r;
}

static __int64 mf_seek(void *multi_file, __int64 offset, int origin)
{
	int i;
	__int64 r;
	
	MULTI_FILE *p;
	MF_PRIVATE_DATA *prv;

	p = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)p->private_data;

	if(prv == NULL){
		return 0;
	}

	i = prv->index;
	
	switch(origin){
	case SEEK_SET:
		r = offset;
		break;
	case SEEK_CUR:
		if(i == prv->count){
			r = offset + prv->total;
		}else{
			r = offset + prv->info[i].offset;
			if(prv->info[i].fd >= 0){
				r += _telli64(prv->info[i].fd);
			}
		}
		break;
	case SEEK_END:
		r = offset + prv->total;
		break;
	default:
		r = offset;
	}

	if(r < 0){
		r = 0;
	}else if(r > prv->total){
		r = prv->total;
	}

	if(i < prv->count){
		if( (r < prv->info[i].offset) || (prv->info[i].offset + prv->info[i].length <= r) ){
			if(prv->info[i].fd >= 0){
				_close(prv->info[i].fd);
				prv->info[i].fd = -1;
			}
		}
	}

	for(i=0;i<prv->count;i++){
		if( (prv->info[i].offset <= r) && (r < (prv->info[i].offset + prv->info[i].length)) ){
			prv->index = i;
			if(prv->info[i].fd < 0){
				prv->info[i].fd = _open(prv->info[i].path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
			}
			if(prv->info[i].fd < 0){
				return prv->info[i].offset;
			}
			_lseeki64(prv->info[i].fd, r - prv->info[i].offset, SEEK_SET);
			return r;
		}
	}

	prv->index = prv->count;

	return prv->total;
}

static int mf_read(void *multi_file, void *buf, int length)
{
	int i,n,r;
	unsigned char *p;

	MULTI_FILE *mf;
	MF_PRIVATE_DATA *prv;

	mf = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)mf->private_data;

	if(prv == NULL){
		return 0;
	}

	if(prv->index >= prv->count){
		return 0;
	}

	r = 0;
	p = (unsigned char *)buf;
	while(length){
		
		i = prv->index;
		
		if(prv->info[i].fd < 0){
			prv->info[i].fd = _open(prv->info[i].path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
		}
		if(prv->info[i].fd < 0){
			break;
		}
		
		n = _read(prv->info[i].fd, p, length);
		
		if(n == 0){
			
			_close(prv->info[i].fd);
			prv->info[i].fd = -1;
			
			i += 1;
			prv->index = i;
			
			if(i >= prv->count){
				break;
			}

		}else{
			
			r += n;	
			p += n;
			length -= n;
			
		}
	}

	return r;
}

static __int64 sf_tell(void *multi_file)
{
	MULTI_FILE *p;
	MF_PRIVATE_DATA *prv;

	p = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)p->private_data;

	if(prv == NULL){
		return 0;
	}

	return _telli64(prv->info[0].fd);
}

static __int64 sf_seek(void *multi_file, __int64 offset, int origin)
{
	MULTI_FILE *p;
	MF_PRIVATE_DATA *prv;

	p = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)p->private_data;

	if(prv == NULL){
		return 0;
	}

	return _lseeki64(prv->info[0].fd, offset, origin);
}

static int sf_read(void *multi_file, void *buf, int length)
{
	int n,r;
	unsigned char *p;
	MULTI_FILE *mf;
	MF_PRIVATE_DATA *prv;

	mf = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)mf->private_data;

	if(prv == NULL){
		return 0;
	}

	r = 0;
	p = (unsigned char *)buf;
	while(length){
		n = _read(prv->info[0].fd, p, length);
		if(n == 0){
			break;
		}
		r += n;
		p += n;
		length -= n;
	}

	return r;
}

static int mf_count(void *multi_file)
{
	MULTI_FILE *mf;
	MF_PRIVATE_DATA *prv;

	mf = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)mf->private_data;

	if(prv == NULL){
		return 0;
	}

	return prv->count;
}

static __int64 mf_border(void *multi_file, int index)
{
	MULTI_FILE *mf;
	MF_PRIVATE_DATA *prv;

	mf = (MULTI_FILE *)multi_file;
	prv = (MF_PRIVATE_DATA *)mf->private_data;

	if(prv == NULL){
		return 0;
	}

	if(index < 0){
		index = 0;
	}else if(index >= prv->count){
		index = prv->count - 1;
	}

	return prv->info[index].offset + prv->info[index].length;
}

static int try_next(char *path)
{
	char *p;
	char *suffix;
	char *base;
	char *tail;

	int need_more;

	// detect suffix
	p = path;
	suffix = NULL;
	base = NULL;
	while(*p){
		if(*p == '.'){
			suffix = p;
		}
		if(*p == '\\'){
			suffix = NULL;
			base = p+1;
		}
		p = CharNext(p);
	}

	if(suffix == NULL){
		suffix = p;
	}
	if(base == NULL){
		base = path;
	}

	// retrieve position of the last digits char
	p = base;
	tail = NULL;
	while(p < suffix){
		if(isdigit(*p)){
			tail = p;
		}
		p = CharNext(p);
	}

	if(tail == NULL){ // path has no digits char
		return -1;
	}

	// increment digits
	need_more = 1;
	p = tail;
	while(need_more){
		
		if(p < base){ /* give up */
			return -1;
		}
		if(!isdigit(*p)){ /* give up */
			return -1;
		}
			
		if(*p == '9'){
			p -= 1;
			continue;
		}

		p[0] += 1;
		while(p < tail){
			p[1] = '0';
			p += 1;
		}
		need_more = 0;
	}

	return _open(path, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -