You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
304 lines
8.2 KiB
304 lines
8.2 KiB
/* -*- C -*-
|
|
* File: libraw_datastream.h
|
|
* Copyright 2008-2009 Alex Tutubalin <lexa@lexa.ru>
|
|
* Created: Sun Jan 18 13:07:35 2009
|
|
*
|
|
* LibRaw Data stream interface
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef __LIBRAW_DATASTREAM_H
|
|
#define __LIBRAW_DATASTREAM_H
|
|
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#ifndef __cplusplus
|
|
|
|
struct LibRaw_abstract_datastream;
|
|
|
|
#else // __cplusplus
|
|
|
|
#include "libraw_const.h"
|
|
|
|
class LibRaw_buffer_datastream;
|
|
|
|
class LibRaw_abstract_datastream
|
|
{
|
|
public:
|
|
LibRaw_abstract_datastream(){substream=0;};
|
|
virtual ~LibRaw_abstract_datastream(void){if(substream) delete substream;}
|
|
virtual int valid(){return 0;}
|
|
// file input emulation
|
|
virtual int read(void *,size_t, size_t ){ return -1;}
|
|
virtual int seek(off_t o, int whence){return -1;}
|
|
virtual int tell(){return -1;}
|
|
virtual int get_char(){return -1;}
|
|
virtual char* gets(char *, int){ return NULL;}
|
|
virtual int scanf_one(const char *, void *){return -1;}
|
|
virtual int eof(){return -1;}
|
|
|
|
virtual const char* fname(){ return NULL;};
|
|
virtual int subfile_open(const char*){ return EINVAL;}
|
|
virtual void subfile_close(){}
|
|
virtual int tempbuffer_open(void*, size_t);
|
|
virtual void tempbuffer_close()
|
|
{
|
|
if(substream) delete substream;
|
|
substream = NULL;
|
|
}
|
|
|
|
protected:
|
|
LibRaw_abstract_datastream *substream;
|
|
};
|
|
|
|
|
|
class LibRaw_file_datastream : public LibRaw_abstract_datastream
|
|
{
|
|
public:
|
|
LibRaw_file_datastream(const char *fname)
|
|
{
|
|
if(fname)
|
|
{filename = fname; f = fopen(fname,"rb");}
|
|
else
|
|
{filename=0;f=0;}
|
|
sav=0;
|
|
}
|
|
|
|
virtual ~LibRaw_file_datastream() {if(f)fclose(f); if(sav)fclose(sav);}
|
|
|
|
virtual int valid() { return f?1:0;}
|
|
|
|
#define CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0)
|
|
virtual int read(void * ptr,size_t size, size_t nmemb)
|
|
{
|
|
CHK();
|
|
return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f));
|
|
}
|
|
virtual int eof()
|
|
{
|
|
CHK();
|
|
return substream?substream->eof():feof(f);
|
|
}
|
|
virtual int seek(off_t o, int whence)
|
|
{
|
|
CHK();
|
|
return substream?substream->seek(o,whence):fseek(f,o,whence);
|
|
}
|
|
virtual int tell()
|
|
{
|
|
CHK();
|
|
return substream?substream->tell():ftell(f);
|
|
}
|
|
virtual int get_char()
|
|
{
|
|
CHK();
|
|
return substream?substream->get_char():fgetc(f);
|
|
}
|
|
virtual char* gets(char *str, int sz)
|
|
{
|
|
CHK();
|
|
return substream?substream->gets(str,sz):fgets(str,sz,f);
|
|
}
|
|
virtual int scanf_one(const char *fmt, void*val)
|
|
{
|
|
CHK();
|
|
return substream?substream->scanf_one(fmt,val):fscanf(f,fmt,val);
|
|
}
|
|
|
|
virtual const char *fname() { return filename; }
|
|
|
|
// secondary
|
|
virtual int subfile_open(const char *fn)
|
|
{
|
|
if(sav) return EBUSY;
|
|
sav = f;
|
|
f = fopen(fn,"rb");
|
|
if(!f)
|
|
{
|
|
f = sav;
|
|
sav = NULL;
|
|
return ENOENT;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
virtual void subfile_close()
|
|
{
|
|
if(!sav) return;
|
|
fclose(f);
|
|
f = sav;
|
|
sav = 0;
|
|
}
|
|
|
|
private:
|
|
FILE *f,*sav;
|
|
const char *filename;
|
|
};
|
|
#undef CHK
|
|
|
|
class LibRaw_buffer_datastream : public LibRaw_abstract_datastream
|
|
{
|
|
public:
|
|
LibRaw_buffer_datastream(void *buffer, size_t bsize)
|
|
{
|
|
buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize;
|
|
}
|
|
virtual ~LibRaw_buffer_datastream(){}
|
|
virtual int valid() { return buf?1:0;}
|
|
virtual int read(void * ptr,size_t sz, size_t nmemb)
|
|
{
|
|
if(substream) return substream->read(ptr,sz,nmemb);
|
|
size_t to_read = sz*nmemb;
|
|
if(to_read > streamsize - streampos)
|
|
to_read = streamsize-streampos;
|
|
if(to_read<1)
|
|
return 0;
|
|
memmove(ptr,buf+streampos,to_read);
|
|
streampos+=to_read;
|
|
return int((to_read+sz-1)/sz);
|
|
}
|
|
|
|
virtual int eof()
|
|
{
|
|
if(substream) return substream->eof();
|
|
return streampos >= streamsize;
|
|
}
|
|
|
|
virtual int seek(off_t o, int whence)
|
|
{
|
|
if(substream) return substream->seek(o,whence);
|
|
switch(whence)
|
|
{
|
|
case SEEK_SET:
|
|
if(o<0)
|
|
streampos = 0;
|
|
else if (size_t(o) > streamsize)
|
|
streampos = streamsize;
|
|
else
|
|
streampos = size_t(o);
|
|
return 0;
|
|
case SEEK_CUR:
|
|
if(o<0)
|
|
{
|
|
if(size_t(-o) >= streampos)
|
|
streampos = 0;
|
|
else
|
|
streampos += o;
|
|
}
|
|
else if (o>0)
|
|
{
|
|
if(o+streampos> streamsize)
|
|
streampos = streamsize;
|
|
else
|
|
streampos += o;
|
|
}
|
|
return 0;
|
|
case SEEK_END:
|
|
if(o>0)
|
|
streampos = streamsize;
|
|
else if ( size_t(-o) > streamsize)
|
|
streampos = 0;
|
|
else
|
|
streampos = streamsize+o;
|
|
return 0;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
virtual int tell()
|
|
{
|
|
if(substream) return substream->tell();
|
|
return int(streampos);
|
|
}
|
|
|
|
virtual int get_char()
|
|
{
|
|
if(substream) return substream->get_char();
|
|
if(streampos>=streamsize)
|
|
return -1;
|
|
return buf[streampos++];
|
|
}
|
|
virtual char* gets(char *s, int sz)
|
|
{
|
|
if (substream) return substream->gets(s,sz);
|
|
unsigned char *psrc,*pdest,*str;
|
|
str = (unsigned char *)s;
|
|
psrc = buf+streampos;
|
|
pdest = str;
|
|
while ( (size_t(psrc - buf) < streamsize)
|
|
&&
|
|
((pdest-str)<sz)
|
|
)
|
|
{
|
|
*pdest = *psrc;
|
|
if(*psrc == '\n')
|
|
break;
|
|
psrc++;
|
|
pdest++;
|
|
}
|
|
if(size_t(psrc-buf) < streamsize)
|
|
psrc++;
|
|
if((pdest-str)<sz)
|
|
*(++pdest)=0;
|
|
streampos = psrc - buf;
|
|
return s;
|
|
}
|
|
virtual int scanf_one(const char *fmt, void* val)
|
|
{
|
|
if(substream) return substream->scanf_one(fmt,val);
|
|
int scanf_res;
|
|
if(streampos>streamsize) return 0;
|
|
scanf_res = sscanf((char*)(buf+streampos),fmt,val);
|
|
if(scanf_res>0)
|
|
{
|
|
int xcnt=0;
|
|
while(streampos<streamsize)
|
|
{
|
|
streampos++;
|
|
xcnt++;
|
|
if(buf[streampos] == 0
|
|
|| buf[streampos]==' '
|
|
|| buf[streampos]=='\t'
|
|
|| buf[streampos]=='\n'
|
|
|| xcnt>24)
|
|
break;
|
|
}
|
|
}
|
|
return scanf_res;
|
|
}
|
|
private:
|
|
unsigned char *buf;
|
|
size_t streampos,streamsize;
|
|
};
|
|
|
|
inline int LibRaw_abstract_datastream::tempbuffer_open(void *buf, size_t size)
|
|
{
|
|
if(substream) return EBUSY;
|
|
substream = new LibRaw_buffer_datastream(buf,size);
|
|
return substream?0:EINVAL;
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|