uristream.cpp revision fb57113b7d8b482fcaf4e63fd3d11a6123a4e251
/**
* Our base String stream classes. We implement these to
* be based on Glib::ustring
*
* Authors:
* Bob Jamison <rjamison@titan.com>
*
* Copyright (C) 2004 Inkscape.org
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "uristream.h"
#include "sys.h"
#include <string>
#include <cstring>
#ifdef WIN32
// For now to get at is_os_wide().
# include "extension/internal/win32.h"
using Inkscape::Extension::Internal::PrintWin32;
#endif
namespace Inkscape
{
namespace IO
{
/*
* URI scheme types
*/
#define SCHEME_NONE 0
#define SCHEME_FILE 1
#define SCHEME_DATA 2
/*
* A temporary modification of Jon Cruz's portable fopen().
* Simplified a bit, since we will always use binary
*/
#define FILE_READ 1
#define FILE_WRITE 2
static FILE *fopen_utf8name( char const *utf8name, int mode )
{
FILE *fp = NULL;
if (!utf8name)
{
return NULL;
}
if (mode!=FILE_READ && mode!=FILE_WRITE)
{
return NULL;
}
#ifndef WIN32
gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL );
if ( filename ) {
if (mode == FILE_READ)
fp = std::fopen(filename, "rb");
else
fp = std::fopen(filename, "wb");
g_free(filename);
}
#else
if ( PrintWin32::is_os_wide() ) {
gunichar2 *wideName = g_utf8_to_utf16( utf8name, -1, NULL, NULL, NULL );
if ( wideName ) {
if (mode == FILE_READ)
fp = _wfopen( (wchar_t*)wideName, L"rb" );
else
fp = _wfopen( (wchar_t*)wideName, L"wb" );
g_free( wideName );
} else {
gchar *safe = Inkscape::IO::sanitizeString(utf8name);
g_message("Unable to convert filename from UTF-8 to UTF-16 [%s]", safe);
g_free(safe);
}
} else {
gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL );
if ( filename ) {
if (mode == FILE_READ)
fp = std::fopen(filename, "rb");
else
fp = std::fopen(filename, "wb");
g_free(filename);
}
}
#endif
return fp;
}
//#########################################################################
//# U R I I N P U T S T R E A M / R E A D E R
//#########################################################################
/**
*
*/
UriInputStream::UriInputStream(Inkscape::URI &source)
throw (StreamException): uri(source)
{
//get information from uri
char const *schemestr = uri.getScheme();
scheme = SCHEME_FILE;
if (!schemestr || strncmp("file", schemestr, 4)==0)
scheme = SCHEME_FILE;
else if (strncmp("data", schemestr, 4)==0)
scheme = SCHEME_DATA;
//printf("in schemestr:'%s' scheme:'%d'\n", schemestr, scheme);
gchar *cpath = NULL;
switch (scheme) {
case SCHEME_FILE:
cpath = uri.toNativeFilename();
//printf("in cpath:'%s'\n", cpath);
inf = fopen_utf8name(cpath, FILE_READ);
//inf = fopen(cpath, "rb");
g_free(cpath);
if (!inf) {
Glib::ustring err = "UriInputStream cannot open file ";
err += cpath;
throw StreamException(err);
}
break;
case SCHEME_DATA:
data = (unsigned char *) uri.getPath();
//printf("in data:'%s'\n", data);
dataPos = 0;
dataLen = strlen((const char *)data);
break;
}
closed = false;
}
/**
*
*/
UriInputStream::UriInputStream(FILE *source, Inkscape::URI &uri)
throw (StreamException): inf(source),
uri(uri)
{
scheme = SCHEME_FILE;
if (!inf) {
Glib::ustring err = "UriInputStream passed NULL";
throw StreamException(err);
}
closed = false;
}
/**
*
*/
UriInputStream::~UriInputStream() throw(StreamException)
{
close();
}
/**
* Returns the number of bytes that can be read (or skipped over) from
* this input stream without blocking by the next caller of a method for
* this input stream.
*/
int UriInputStream::available() throw(StreamException)
{
return 0;
}
/**
* Closes this input stream and releases any system resources
* associated with the stream.
*/
void UriInputStream::close() throw(StreamException)
{
if (closed)
return;
switch (scheme) {
case SCHEME_FILE:
if (!inf)
return;
fflush(inf);
fclose(inf);
inf=NULL;
break;
case SCHEME_DATA:
//do nothing
break;
}//switch
closed = true;
}
/**
* Reads the next byte of data from the input stream. -1 if EOF
*/
int UriInputStream::get() throw(StreamException)
{
int retVal = -1;
if (!closed)
{
switch (scheme) {
case SCHEME_FILE:
if (!inf || feof(inf))
{
retVal = -1;
}
else
{
retVal = fgetc(inf);
}
break;
case SCHEME_DATA:
if (dataPos >= dataLen)
{
retVal = -1;
}
else
{
retVal = data[dataPos++];
}
break;
}//switch
}
return retVal;
}
/**
*
*/
UriReader::UriReader(Inkscape::URI &uri)
throw (StreamException)
{
inputStream = new UriInputStream(uri);
}
/**
*
*/
UriReader::~UriReader() throw (StreamException)
{
delete inputStream;
}
/**
*
*/
int UriReader::available() throw(StreamException)
{
return inputStream->available();
}
/**
*
*/
void UriReader::close() throw(StreamException)
{
inputStream->close();
}
/**
*
*/
gunichar UriReader::get() throw(StreamException)
{
gunichar ch = (gunichar)inputStream->get();
return ch;
}
//#########################################################################
//# U R I O U T P U T S T R E A M / W R I T E R
//#########################################################################
/**
* Temporary kludge
*/
UriOutputStream::UriOutputStream(FILE* fp, Inkscape::URI &destination)
throw (StreamException): closed(false),
ownsFile(false),
outf(fp),
uri(destination),
scheme(SCHEME_FILE)
{
if (!outf) {
Glib::ustring err = "UriOutputStream given null file ";
throw StreamException(err);
}
}
/**
*
*/
UriOutputStream::UriOutputStream(Inkscape::URI &destination)
throw (StreamException): closed(false),
ownsFile(true),
outf(NULL),
uri(destination),
scheme(SCHEME_FILE)
{
//get information from uri
char const *schemestr = uri.getScheme();
if (!schemestr || strncmp("file", schemestr, 4)==0)
scheme = SCHEME_FILE;
else if (strncmp("data", schemestr, 4)==0)
scheme = SCHEME_DATA;
//printf("out schemestr:'%s' scheme:'%d'\n", schemestr, scheme);
gchar *cpath = NULL;
switch (scheme) {
case SCHEME_FILE:
cpath = uri.toNativeFilename();
//printf("out path:'%s'\n", cpath);
outf = fopen_utf8name(cpath, FILE_WRITE);
//outf = fopen(cpath, "wb");
g_free(cpath);
if (!outf) {
Glib::ustring err = "UriOutputStream cannot open file ";
err += cpath;
throw StreamException(err);
}
break;
case SCHEME_DATA:
data = "data:";
break;
}//switch
}
/**
*
*/
UriOutputStream::~UriOutputStream() throw(StreamException)
{
close();
}
/**
* Closes this output stream and releases any system resources
* associated with this stream.
*/
void UriOutputStream::close() throw(StreamException)
{
if (closed)
return;
switch (scheme) {
case SCHEME_FILE:
if (!outf)
return;
fflush(outf);
if ( ownsFile )
fclose(outf);
outf=NULL;
break;
case SCHEME_DATA:
uri = URI(data.raw().c_str());
break;
}//switch
closed = true;
}
/**
* Flushes this output stream and forces any buffered output
* bytes to be written out.
*/
void UriOutputStream::flush() throw(StreamException)
{
if (closed)
return;
switch (scheme) {
case SCHEME_FILE:
if (!outf)
return;
fflush(outf);
break;
case SCHEME_DATA:
//nothing
break;
}//switch
}
/**
* Writes the specified byte to this output stream.
*/
void UriOutputStream::put(int ch) throw(StreamException)
{
if (closed)
return;
unsigned char uch;
gunichar gch;
switch (scheme) {
case SCHEME_FILE:
if (!outf)
return;
uch = (unsigned char)(ch & 0xff);
if (fputc(uch, outf) == EOF) {
Glib::ustring err = "ERROR writing to file ";
throw StreamException(err);
}
//fwrite(uch, 1, 1, outf);
break;
case SCHEME_DATA:
gch = (gunichar) ch;
data.push_back(gch);
break;
}//switch
}
/**
*
*/
UriWriter::UriWriter(Inkscape::URI &uri)
throw (StreamException)
{
outputStream = new UriOutputStream(uri);
}
/**
*
*/
UriWriter::~UriWriter() throw (StreamException)
{
delete outputStream;
}
/**
*
*/
void UriWriter::close() throw(StreamException)
{
outputStream->close();
}
/**
*
*/
void UriWriter::flush() throw(StreamException)
{
outputStream->flush();
}
/**
*
*/
void UriWriter::put(gunichar ch) throw(StreamException)
{
int ich = (int)ch;
outputStream->put(ich);
}
} // namespace IO
} // namespace Inkscape
//#########################################################################
//# E N D O F F I L E
//#########################################################################