X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fxml%2Frepr-io.cpp;h=10f6101b656df3c10039b7c6707291921824a8a7;hb=6d2cc960e9ee6f4c6b649049951b32f750786a6d;hp=02aca4dc6786730a5ccf28169d733acc54097d11;hpb=549019d17748f165f3c71e0e5e5072cd5f9a7141;p=inkscape.git diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index 02aca4dc6..10f6101b6 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -16,7 +16,7 @@ # include #endif - +#include #include "xml/repr.h" #include "xml/attribute-record.h" @@ -51,8 +51,9 @@ class XmlSource public: XmlSource() : filename(0), + encoding(0), fp(0), - first(false), + firstFewLen(0), dummy("x"), instr(0), gzin(0) @@ -61,29 +62,90 @@ public: virtual ~XmlSource() { close(); + if ( encoding ) { + g_free(encoding); + encoding = 0; + } } - void setFile( char const * filename ); - - static int readCb( void * context, char * buffer, int len); - static int closeCb(void * context); + int setFile( char const * filename ); + static int readCb( void * context, char * buffer, int len ); + static int closeCb( void * context ); + char const* getEncoding() const { return encoding; } int read( char * buffer, int len ); int close(); private: const char* filename; + char* encoding; FILE* fp; - bool first; + unsigned char firstFew[4]; + int firstFewLen; Inkscape::URI dummy; Inkscape::IO::UriInputStream* instr; Inkscape::IO::GzipInputStream* gzin; }; -void XmlSource::setFile( char const * filename ) { +int XmlSource::setFile(char const *filename) +{ + int retVal = -1; + this->filename = filename; + fp = Inkscape::IO::fopen_utf8name(filename, "r"); - first = true; + if ( fp ) { + // First peek in the file to see what it is + memset( firstFew, 0, sizeof(firstFew) ); + + size_t some = fread( firstFew, 1, 4, fp ); + if ( fp ) { + // first check for compression + if ( (some >= 2) && (firstFew[0] == 0x1f) && (firstFew[1] == 0x8b) ) { + //g_message(" the file being read is gzip'd. extract it"); + fclose(fp); + fp = 0; + fp = Inkscape::IO::fopen_utf8name(filename, "r"); + instr = new Inkscape::IO::UriInputStream(fp, dummy); + gzin = new Inkscape::IO::GzipInputStream(*instr); + + memset( firstFew, 0, sizeof(firstFew) ); + some = 0; + int single = 0; + while ( some < 4 && single >= 0 ) + { + single = gzin->get(); + if ( single >= 0 ) { + firstFew[some++] = 0x0ff & single; + } else { + break; + } + } + } + + int encSkip = 0; + if ( (some >= 2) &&(firstFew[0] == 0xfe) && (firstFew[1] == 0xff) ) { + encoding = g_strdup("UTF-16BE"); + encSkip = 2; + } else if ( (some >= 2) && (firstFew[0] == 0xff) && (firstFew[1] == 0xfe) ) { + encoding = g_strdup("UTF-16LE"); + encSkip = 2; + } else if ( (some >= 3) && (firstFew[0] == 0xef) && (firstFew[1] == 0xbb) && (firstFew[2] == 0xbf) ) { + encoding = g_strdup("UTF-8"); + encSkip = 3; + } + + if ( encSkip ) { + memmove( firstFew, firstFew + encSkip, (some - encSkip) ); + some -= encSkip; + } + + firstFewLen = some; + retVal = 0; // no error + } + } + + return retVal; } @@ -111,33 +173,14 @@ int XmlSource::read( char *buffer, int len ) int retVal = 0; size_t got = 0; - if ( first ) { - first = false; - char tmp[] = {0,0}; - size_t some = fread( tmp, 1, 2, fp ); - - if ( (some >= 2) && (tmp[0] == 0x1f) && ((unsigned char)(tmp[1]) == 0x8b) ) { - //g_message(" the file being read is gzip'd. extract it"); - fclose(fp); - fp = 0; - fp = Inkscape::IO::fopen_utf8name(filename, "r"); - instr = new Inkscape::IO::UriInputStream(fp, dummy); - gzin = new Inkscape::IO::GzipInputStream(*instr); - int single = 0; - while ( (int)got < len && single >= 0 ) - { - single = gzin->get(); - if ( single >= 0 ) { - buffer[got++] = 0x0ff & single; - } else { - break; - } - } - //g_message(" extracted %d bytes this pass", got ); - } else { - memcpy( buffer, tmp, some ); - got = some; + if ( firstFewLen > 0 ) { + int some = (len < firstFewLen) ? len : firstFewLen; + memcpy( buffer, firstFew, some ); + if ( len < firstFewLen ) { + memmove( firstFew, firstFew + some, (firstFewLen - some) ); } + firstFewLen -= some; + got = some; } else if ( gzin ) { int single = 0; while ( (int)got < len && single >= 0 ) @@ -149,18 +192,15 @@ int XmlSource::read( char *buffer, int len ) break; } } - //g_message(" extracted %d bytes this pass b", got ); } else { got = fread( buffer, 1, len, fp ); } if ( feof(fp) ) { retVal = got; - } - else if ( ferror(fp) ) { + } else if ( ferror(fp) ) { retVal = -1; - } - else { + } else { retVal = got; } @@ -213,43 +253,35 @@ sp_repr_read_file (const gchar * filename, const gchar *default_ns) Inkscape::IO::dump_fopen_call( filename, "N" ); - XmlSource src; - src.setFile(filename); - - xmlDocPtr doubleDoc = xmlReadIO( XmlSource::readCb, - XmlSource::closeCb, - &src, - localFilename, - NULL, //"UTF-8", - XML_PARSE_NOENT ); - - #ifdef HAVE_LIBWMF if (strlen (localFilename) > 4) { if ( (strcmp (localFilename + strlen (localFilename) - 4,".wmf") == 0) - || (strcmp (localFilename + strlen (localFilename) - 4,".WMF") == 0)) + || (strcmp (localFilename + strlen (localFilename) - 4,".WMF") == 0)) { doc = sp_wmf_convert (localFilename); - else - doc = xmlParseFile (localFilename); - } - else { - doc = xmlParseFile (localFilename); + } } -#else /* !HAVE_LIBWMF */ - //doc = xmlParseFile (localFilename); -#endif /* !HAVE_LIBWMF */ +#endif // !HAVE_LIBWMF - //rdoc = sp_repr_do_read (doc, default_ns); - rdoc = sp_repr_do_read (doubleDoc, default_ns); - if (doc) - xmlFreeDoc (doc); + if ( !doc ) { + XmlSource src; - if ( localFilename != NULL ) - g_free (localFilename); + if ( (src.setFile(filename) == 0) ) { + doc = xmlReadIO( XmlSource::readCb, + XmlSource::closeCb, + &src, + localFilename, + src.getEncoding(), + XML_PARSE_NOENT ); + } + } - if ( doubleDoc != NULL ) - { - xmlFreeDoc( doubleDoc ); + rdoc = sp_repr_do_read( doc, default_ns ); + if ( doc ) { + xmlFreeDoc( doc ); + } + + if ( localFilename ) { + g_free( localFilename ); } return rdoc; @@ -574,7 +606,7 @@ repr_quote_write (Writer &out, const gchar * val) namespace { typedef std::map LocalNameMap; -typedef std::map NSMap; +typedef std::map, Inkscape::compare_quark_ids> NSMap; gchar const *qname_local_name(Glib::QueryQuark qname) { static LocalNameMap local_name_map; @@ -593,7 +625,8 @@ gchar const *qname_local_name(Glib::QueryQuark qname) { } void add_ns_map_entry(NSMap &ns_map, Glib::QueryQuark prefix) { - using Inkscape::Util::SharedCStringPtr; + using Inkscape::Util::ptr_shared; + using Inkscape::Util::share_unsafe; static const Glib::QueryQuark xml_prefix("xml"); @@ -602,12 +635,12 @@ void add_ns_map_entry(NSMap &ns_map, Glib::QueryQuark prefix) { if (prefix.id()) { gchar const *uri=sp_xml_ns_prefix_uri(g_quark_to_string(prefix)); if (uri) { - ns_map.insert(NSMap::value_type(prefix, SharedCStringPtr::coerce(uri))); + ns_map.insert(NSMap::value_type(prefix, share_unsafe(uri))); } else if ( prefix != xml_prefix ) { g_warning("No namespace known for normalized prefix %s", g_quark_to_string(prefix)); } } else { - ns_map.insert(NSMap::value_type(prefix, SharedCStringPtr())); + ns_map.insert(NSMap::value_type(prefix, ptr_shared())); } } } @@ -636,7 +669,7 @@ void populate_ns_map(NSMap &ns_map, Node &repr) { void sp_repr_write_stream_root_element (Node *repr, Writer &out, gboolean add_whitespace, gchar const *default_ns) { - using Inkscape::Util::SharedCStringPtr; + using Inkscape::Util::ptr_shared; g_assert(repr != NULL); Glib::QueryQuark xml_prefix=g_quark_from_static_string("xml"); @@ -652,7 +685,7 @@ sp_repr_write_stream_root_element (Node *repr, Writer &out, gboolean add_whitesp for ( NSMap::iterator iter=ns_map.begin() ; iter != ns_map.end() ; ++iter ) { Glib::QueryQuark prefix=(*iter).first; - SharedCStringPtr ns_uri=(*iter).second; + ptr_shared ns_uri=(*iter).second; if (prefix.id()) { if ( prefix != xml_prefix ) {