/* ** The cvsgui protocol used by WinCvs ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 of the License, or (at your option) any later version. ** ** This library 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public ** License along with this library; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * gimpwire.c from the GIMP modified for the cvsgui project by : * Alexandre Parenteau --- November 1999 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "cvsgui_wire.h" #ifndef WIN32 # include # include # include #else # pragma warning (disable : 4786) #endif #include #if TARGET_RT_MAC_MACHO # define STD_STL std:: // probable transitory problem with MWERKS on Mach-O #else # define STD_STL std:: #endif #ifdef WIN32 static int read(pipe_t fd, void *buf, int count) { DWORD dread; if(!ReadFile(fd,buf,count,&dread,NULL)) { DWORD err = GetLastError(); errno = EINVAL; return -1; } return dread; } static int write(pipe_t fd, const void *buf, int count) { DWORD dwrite; if(!WriteFile(fd,buf,count,&dwrite,NULL)) { errno = EINVAL; return -1; } return dwrite; } #endif typedef struct _WireHandler WireHandler; struct _WireHandler { guint32 type; WireReadFunc read_func; WireWriteFunc write_func; WireDestroyFunc destroy_func; }; static WireIOFunc wire_read_func = NULL; static WireIOFunc wire_write_func = NULL; static WireFlushFunc wire_flush_func = NULL; static int wire_error_val = FALSE; struct CAllHandlers { public: CAllHandlers() {} ~CAllHandlers() { STD_STL map::iterator i; for(i = wire_ht.begin(); i != wire_ht.end(); ++i) { WireHandler *handler = (*i).second; free(handler); } } STD_STL map wire_ht; } sHandlers; void wire_register (guint32 type, WireReadFunc read_func, WireWriteFunc write_func, WireDestroyFunc destroy_func) { WireHandler *handler; STD_STL map::iterator i = sHandlers.wire_ht.find(type); if(i == sHandlers.wire_ht.end()) handler = (WireHandler *)malloc(sizeof(WireHandler)); else handler = (*i).second; handler->type = type; handler->read_func = read_func; handler->write_func = write_func; handler->destroy_func = destroy_func; sHandlers.wire_ht.insert(STD_STL map::value_type(type, handler)); } void wire_set_reader (WireIOFunc read_func) { wire_read_func = read_func; } void wire_set_writer (WireIOFunc write_func) { wire_write_func = write_func; } void wire_set_flusher (WireFlushFunc flush_func) { wire_flush_func = flush_func; } int wire_read (pipe_t fd, guint8 *buf, gulong count) { if (wire_read_func) { if (!(* wire_read_func) (fd, buf, count)) { //g_print ("wire_read: error\n"); wire_error_val = TRUE; return FALSE; } } else { int bytes; while (count > 0) { do { bytes = read (fd, (char*) buf, count); } while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR))); if (bytes == -1) { //g_print ("wire_read: error\n"); wire_error_val = TRUE; return FALSE; } if (bytes == 0) { //g_print ("wire_read: unexpected EOF (plug-in crashed?)\n"); wire_error_val = TRUE; return FALSE; } count -= bytes; buf += bytes; } } return TRUE; } int wire_write (pipe_t fd, guint8 *buf, gulong count) { if (wire_write_func) { if (!(* wire_write_func) (fd, buf, count)) { //g_print ("wire_write: error\n"); wire_error_val = TRUE; return FALSE; } } else { int bytes; while (count > 0) { do { bytes = write (fd, (char*) buf, count); } while ((bytes == -1) && ((errno == EAGAIN) || (errno == EINTR))); if (bytes == -1) { //g_print ("wire_write: error\n"); wire_error_val = TRUE; return FALSE; } count -= bytes; buf += bytes; } } return TRUE; } int wire_flush (pipe_t fd) { if (wire_flush_func) return (* wire_flush_func) (fd); return FALSE; } int wire_error () { return wire_error_val; } void wire_clear_error () { wire_error_val = FALSE; } int wire_read_msg (pipe_t fd, WireMessage *msg) { WireHandler *handler; if (wire_error_val) return !wire_error_val; if (!wire_read_int32 (fd, &msg->type, 1)) return FALSE; STD_STL map::iterator i = sHandlers.wire_ht.find(msg->type); if(i == sHandlers.wire_ht.end()) return FALSE; handler = (*i).second; (* handler->read_func) (fd, msg); return !wire_error_val; } int wire_write_msg (pipe_t fd, WireMessage *msg) { WireHandler *handler; if (wire_error_val) return !wire_error_val; STD_STL map::iterator i = sHandlers.wire_ht.find(msg->type); if(i == sHandlers.wire_ht.end()) return FALSE; handler = (*i).second; if (!wire_write_int32 (fd, &msg->type, 1)) return FALSE; (* handler->write_func) (fd, msg); return !wire_error_val; } void wire_destroy (WireMessage *msg) { WireHandler *handler; STD_STL map::iterator i = sHandlers.wire_ht.find(msg->type); if(i == sHandlers.wire_ht.end()) return; handler = (*i).second; (* handler->destroy_func) (msg); } int wire_read_int32 (pipe_t fd, guint32 *data, gint count) { if (count > 0) { if (!wire_read_int8 (fd, (guint8*) data, count * 4)) return FALSE; while (count--) { *data = ntohl (*data); data++; } } return TRUE; } int wire_read_int16 (pipe_t fd, guint16 *data, gint count) { if (count > 0) { if (!wire_read_int8 (fd, (guint8*) data, count * 2)) return FALSE; while (count--) { *data = ntohs (*data); data++; } } return TRUE; } int wire_read_int8 (pipe_t fd, guint8 *data, gint count) { return wire_read (fd, data, count); } int wire_read_double (pipe_t fd, gdouble *data, gint count) { char *str; int i; for (i = 0; i < count; i++) { if (!wire_read_string (fd, &str, 1)) return FALSE; sscanf (str, "%le", &data[i]); free (str); } return TRUE; } int wire_read_string (pipe_t fd, gchar **data, gint count) { guint32 tmp; int i; for (i = 0; i < count; i++) { if (!wire_read_int32 (fd, &tmp, 1)) return FALSE; if (tmp > 0) { data[i] = (gchar *)malloc(tmp * sizeof(gchar)); if (!wire_read_int8 (fd, (guint8*) data[i], tmp)) { free (data[i]); return FALSE; } } else { data[i] = NULL; } } return TRUE; } int wire_write_int32 (pipe_t fd, guint32 *data, gint count) { guint32 tmp; int i; if (count > 0) { for (i = 0; i < count; i++) { tmp = htonl (data[i]); if (!wire_write_int8 (fd, (guint8*) &tmp, 4)) return FALSE; } } return TRUE; } int wire_write_int16 (pipe_t fd, guint16 *data, gint count) { guint16 tmp; int i; if (count > 0) { for (i = 0; i < count; i++) { tmp = htons (data[i]); if (!wire_write_int8 (fd, (guint8*) &tmp, 2)) return FALSE; } } return TRUE; } int wire_write_int8 (pipe_t fd, guint8 *data, gint count) { return wire_write (fd, data, count); } int wire_write_double (pipe_t fd, gdouble *data, gint count) { gchar *t, buf[128]; int i; t = buf; for (i = 0; i < count; i++) { sprintf (buf, "%0.50e", data[i]); if (!wire_write_string (fd, &t, 1)) return FALSE; } return TRUE; } int wire_write_string (pipe_t fd, gchar **data, gint count) { guint32 tmp; int i; for (i = 0; i < count; i++) { if (data[i]) tmp = strlen (data[i]) + 1; else tmp = 0; if (!wire_write_int32 (fd, &tmp, 1)) return FALSE; if (tmp > 0) if (!wire_write_int8 (fd, (guint8*) data[i], tmp)) return FALSE; } return TRUE; }