gimpwire.c 10.5 KB
Newer Older
1 2
/* LIBGIMP - The GIMP Library
 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
Manish Singh's avatar
Manish Singh committed
3 4
 *
 * This library is free software; you can redistribute it and/or
Marc Lehmann's avatar
Marc Lehmann committed
5
 * modify it under the terms of the GNU Lesser General Public
Manish Singh's avatar
Manish Singh committed
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8 9
 *
 * This library is distributed in the hope that it will be useful,
10 11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Manish Singh's avatar
Manish Singh committed
12 13
 * Library General Public License for more details.
 *
Marc Lehmann's avatar
Marc Lehmann committed
14
 * You should have received a copy of the GNU Lesser General Public
15 16 17
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
18 19 20 21
 */

#include "config.h"

Elliot Lee's avatar
Elliot Lee committed
22 23 24 25
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
26
#ifdef HAVE_SYS_PARAM_H
Elliot Lee's avatar
Elliot Lee committed
27
#include <sys/param.h>
28
#endif
Elliot Lee's avatar
Elliot Lee committed
29
#include <sys/types.h>
30
#ifdef HAVE_UNISTD_H
Elliot Lee's avatar
Elliot Lee committed
31
#include <unistd.h>
32 33
#endif

34 35
#include <glib.h>

36
#ifdef G_OS_WIN32
37 38 39 40
#include <process.h>
#include <io.h>
#endif

Elliot Lee's avatar
Elliot Lee committed
41 42 43 44 45 46 47
#include "gimpwire.h"


typedef struct _WireHandler  WireHandler;

struct _WireHandler
{
48 49 50
  guint32         type;
  WireReadFunc    read_func;
  WireWriteFunc   write_func;
Elliot Lee's avatar
Elliot Lee committed
51 52 53 54
  WireDestroyFunc destroy_func;
};


55 56 57 58
static void      wire_init    (void);
static guint     wire_hash    (guint32 *key);
static gboolean  wire_compare (guint32 *a,
			       guint32 *b);
Elliot Lee's avatar
Elliot Lee committed
59 60


61 62
static GHashTable    *wire_ht         = NULL;
static WireIOFunc     wire_read_func  = NULL;
63 64
static WireIOFunc     wire_write_func = NULL;
static WireFlushFunc  wire_flush_func = NULL;
65
static gboolean       wire_error_val  = FALSE;
Elliot Lee's avatar
Elliot Lee committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82


void
wire_register (guint32         type,
	       WireReadFunc    read_func,
	       WireWriteFunc   write_func,
	       WireDestroyFunc destroy_func)
{
  WireHandler *handler;

  if (!wire_ht)
    wire_init ();

  handler = g_hash_table_lookup (wire_ht, &type);
  if (!handler)
    handler = g_new (WireHandler, 1);

83 84 85
  handler->type         = type;
  handler->read_func    = read_func;
  handler->write_func   = write_func;
Elliot Lee's avatar
Elliot Lee committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
  handler->destroy_func = destroy_func;

  g_hash_table_insert (wire_ht, &handler->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;
}

109
gboolean
110 111
wire_read (GIOChannel *channel,
	   guint8     *buf,
112 113
	   gsize       count,
           gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
114 115 116
{
  if (wire_read_func)
    {
117
      if (!(* wire_read_func) (channel, buf, count, user_data))
Elliot Lee's avatar
Elliot Lee committed
118
	{
119
	  g_warning ("%s: wire_read: error", g_get_prgname ());
Elliot Lee's avatar
Elliot Lee committed
120 121 122 123 124 125
	  wire_error_val = TRUE;
	  return FALSE;
	}
    }
  else
    {
126 127 128
      GIOStatus  status;
      GError    *error = NULL;
      gsize      bytes;
Elliot Lee's avatar
Elliot Lee committed
129 130 131

      while (count > 0)
	{
132 133 134
	  do
	    {
	      bytes = 0;
135 136 137 138
	      status = g_io_channel_read_chars (channel,
						(gchar *) buf, count,
						&bytes,
						&error);
139
	    }
140
	  while (status == G_IO_STATUS_AGAIN);
Elliot Lee's avatar
Elliot Lee committed
141

142
	  if (status != G_IO_STATUS_NORMAL)
Elliot Lee's avatar
Elliot Lee committed
143
	    {
144 145 146 147 148 149 150 151 152 153 154 155
	      if (error)
		{
		  g_warning ("%s: wire_read(): error: %s",
			     g_get_prgname (), error->message);
		  g_error_free (error);
		}
	      else
		{
		  g_warning ("%s: wire_read(): error",
			     g_get_prgname ());
		}

Elliot Lee's avatar
Elliot Lee committed
156 157 158 159
	      wire_error_val = TRUE;
	      return FALSE;
	    }

160
	  if (bytes == 0)
Elliot Lee's avatar
Elliot Lee committed
161
	    {
162
	      g_warning ("%s: wire_read(): unexpected EOF", g_get_prgname ());
Elliot Lee's avatar
Elliot Lee committed
163 164 165 166 167 168 169 170 171 172 173 174
	      wire_error_val = TRUE;
	      return FALSE;
	    }

	  count -= bytes;
	  buf += bytes;
	}
    }

  return TRUE;
}

175
gboolean
176 177
wire_write (GIOChannel *channel,
	    guint8     *buf,
178 179
	    gsize       count,
            gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
180 181 182
{
  if (wire_write_func)
    {
183
      if (!(* wire_write_func) (channel, buf, count, user_data))
Elliot Lee's avatar
Elliot Lee committed
184
	{
185
	  g_warning ("%s: wire_write: error", g_get_prgname ());
Elliot Lee's avatar
Elliot Lee committed
186 187 188 189 190 191
	  wire_error_val = TRUE;
	  return FALSE;
	}
    }
  else
    {
192 193 194
      GIOStatus  status;
      GError    *error = NULL;
      gsize      bytes;
Elliot Lee's avatar
Elliot Lee committed
195 196 197

      while (count > 0)
	{
198 199 200
	  do
	    {
	      bytes = 0;
201 202 203 204
	      status = g_io_channel_write_chars (channel,
						 (gchar *) buf, count,
						 &bytes,
						 &error);
205
	    }
206
	  while (status == G_IO_STATUS_AGAIN);
Elliot Lee's avatar
Elliot Lee committed
207

208
	  if (status != G_IO_STATUS_NORMAL)
Elliot Lee's avatar
Elliot Lee committed
209
	    {
210 211 212 213 214 215 216 217 218 219 220 221
	      if (error)
		{
		  g_warning ("%s: wire_write(): error: %s",
			     g_get_prgname (), error->message);
		  g_error_free (error);
		}
	      else
		{
		  g_warning ("%s: wire_write(): error",
			     g_get_prgname ());
		}

Elliot Lee's avatar
Elliot Lee committed
222 223 224 225 226 227 228 229 230 231 232 233
	      wire_error_val = TRUE;
	      return FALSE;
	    }

	  count -= bytes;
	  buf += bytes;
	}
    }

  return TRUE;
}

234
gboolean
235 236
wire_flush (GIOChannel *channel,
            gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
237 238
{
  if (wire_flush_func)
239
    return (* wire_flush_func) (channel, user_data);
240

Elliot Lee's avatar
Elliot Lee committed
241 242 243
  return FALSE;
}

244 245
gboolean
wire_error (void)
Elliot Lee's avatar
Elliot Lee committed
246 247 248 249 250
{
  return wire_error_val;
}

void
251
wire_clear_error (void)
Elliot Lee's avatar
Elliot Lee committed
252 253 254 255
{
  wire_error_val = FALSE;
}

256
gboolean
257
wire_read_msg (GIOChannel  *channel,
258 259
	       WireMessage *msg,
               gpointer     user_data)
Elliot Lee's avatar
Elliot Lee committed
260 261 262 263 264 265
{
  WireHandler *handler;

  if (wire_error_val)
    return !wire_error_val;

266
  if (! wire_read_int32 (channel, &msg->type, 1, user_data))
Elliot Lee's avatar
Elliot Lee committed
267 268 269 270
    return FALSE;

  handler = g_hash_table_lookup (wire_ht, &msg->type);
  if (!handler)
271
    g_error ("could not find handler for message: %d", msg->type);
Elliot Lee's avatar
Elliot Lee committed
272

273
  (* handler->read_func) (channel, msg, user_data);
Elliot Lee's avatar
Elliot Lee committed
274 275 276 277

  return !wire_error_val;
}

278
gboolean
279
wire_write_msg (GIOChannel  *channel,
280 281
		WireMessage *msg,
                gpointer     user_data)
Elliot Lee's avatar
Elliot Lee committed
282 283 284 285 286 287 288 289
{
  WireHandler *handler;

  if (wire_error_val)
    return !wire_error_val;

  handler = g_hash_table_lookup (wire_ht, &msg->type);
  if (!handler)
290
    g_error ("could not find handler for message: %d", msg->type);
Elliot Lee's avatar
Elliot Lee committed
291

292
  if (! wire_write_int32 (channel, &msg->type, 1, user_data))
Elliot Lee's avatar
Elliot Lee committed
293 294
    return FALSE;

295
  (* handler->write_func) (channel, msg, user_data);
Elliot Lee's avatar
Elliot Lee committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

  return !wire_error_val;
}

void
wire_destroy (WireMessage *msg)
{
  WireHandler *handler;

  handler = g_hash_table_lookup (wire_ht, &msg->type);
  if (!handler)
    g_error ("could not find handler for message: %d\n", msg->type);

  (* handler->destroy_func) (msg);
}

312
gboolean
313 314
wire_read_int32 (GIOChannel *channel,
		 guint32    *data,
315 316
		 gint        count,
                 gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
317 318 319
{
  if (count > 0)
    {
320
      if (! wire_read_int8 (channel, (guint8 *) data, count * 4, user_data))
Elliot Lee's avatar
Elliot Lee committed
321 322 323 324
	return FALSE;

      while (count--)
	{
Manish Singh's avatar
Manish Singh committed
325
	  *data = g_ntohl (*data);
Elliot Lee's avatar
Elliot Lee committed
326 327 328 329 330 331 332
	  data++;
	}
    }

  return TRUE;
}

333
gboolean
334 335
wire_read_int16 (GIOChannel *channel,
		 guint16    *data,
336 337
		 gint        count,
                 gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
338 339 340
{
  if (count > 0)
    {
341
      if (! wire_read_int8 (channel, (guint8 *) data, count * 2, user_data))
Elliot Lee's avatar
Elliot Lee committed
342 343 344 345
	return FALSE;

      while (count--)
	{
Manish Singh's avatar
Manish Singh committed
346
	  *data = g_ntohs (*data);
Elliot Lee's avatar
Elliot Lee committed
347 348 349 350 351 352 353
	  data++;
	}
    }

  return TRUE;
}

354
gboolean
355 356
wire_read_int8 (GIOChannel *channel,
		guint8     *data,
357 358
		gint        count,
                gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
359
{
360
  return wire_read (channel, data, count, user_data);
Elliot Lee's avatar
Elliot Lee committed
361 362
}

363
gboolean
364 365
wire_read_double (GIOChannel *channel,
		  gdouble    *data,
366 367
		  gint        count,
                  gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
368
{
369 370 371
  gdouble *t;
  guint8   tmp[8];
  gint     i;
372
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
373 374
  gint     j;
  guint8   swap;
375 376
#endif

377 378
  t = (gdouble *) tmp;

Elliot Lee's avatar
Elliot Lee committed
379 380
  for (i = 0; i < count; i++)
    {
381 382
      if (! wire_read_int8 (channel, tmp, 8, user_data))
        return FALSE;
383 384

#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
385 386 387 388 389 390
      for (j = 0; j < 4; j++)
        {
          swap = tmp[j];
          tmp[j] = tmp[7 - j];
          tmp[7 - j] = swap;
        }
391 392
#endif

393
      data[i] = *t;
Elliot Lee's avatar
Elliot Lee committed
394 395 396 397 398
    }

  return TRUE;
}

399
gboolean
400 401
wire_read_string (GIOChannel  *channel,
		  gchar      **data,
402 403
		  gint         count,
                  gpointer     user_data)
Elliot Lee's avatar
Elliot Lee committed
404 405
{
  guint32 tmp;
406
  gint    i;
Elliot Lee's avatar
Elliot Lee committed
407 408 409

  for (i = 0; i < count; i++)
    {
410
      if (!wire_read_int32 (channel, &tmp, 1, user_data))
Elliot Lee's avatar
Elliot Lee committed
411 412 413 414 415
	return FALSE;

      if (tmp > 0)
	{
	  data[i] = g_new (gchar, tmp);
416
	  if (! wire_read_int8 (channel, (guint8 *) data[i], tmp, user_data))
Manish Singh's avatar
Manish Singh committed
417 418 419 420
	    {
	      g_free (data[i]);
	      return FALSE;
	    }
Elliot Lee's avatar
Elliot Lee committed
421 422 423 424 425 426 427 428 429 430
	}
      else
	{
	  data[i] = NULL;
	}
    }

  return TRUE;
}

431
gboolean
432 433
wire_write_int32 (GIOChannel *channel,
		  guint32    *data,
434 435
		  gint        count,
                  gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
436 437
{
  guint32 tmp;
438
  gint    i;
Elliot Lee's avatar
Elliot Lee committed
439 440 441 442 443

  if (count > 0)
    {
      for (i = 0; i < count; i++)
	{
Manish Singh's avatar
Manish Singh committed
444
	  tmp = g_htonl (data[i]);
445
	  if (! wire_write_int8 (channel, (guint8 *) &tmp, 4, user_data))
Elliot Lee's avatar
Elliot Lee committed
446 447 448 449 450 451 452
	    return FALSE;
	}
    }

  return TRUE;
}

453
gboolean
454 455
wire_write_int16 (GIOChannel *channel,
		  guint16    *data,
456 457
		  gint        count,
                  gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
458 459
{
  guint16 tmp;
460
  gint    i;
Elliot Lee's avatar
Elliot Lee committed
461 462 463 464 465

  if (count > 0)
    {
      for (i = 0; i < count; i++)
	{
Manish Singh's avatar
Manish Singh committed
466
	  tmp = g_htons (data[i]);
467
	  if (! wire_write_int8 (channel, (guint8 *) &tmp, 2, user_data))
Elliot Lee's avatar
Elliot Lee committed
468 469 470 471 472 473 474
	    return FALSE;
	}
    }

  return TRUE;
}

475
gboolean
476 477
wire_write_int8 (GIOChannel *channel,
		 guint8     *data,
478 479
		 gint        count,
                 gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
480
{
481
  return wire_write (channel, data, count, user_data);
Elliot Lee's avatar
Elliot Lee committed
482 483
}

484
gboolean
485 486
wire_write_double (GIOChannel *channel,
		   gdouble    *data,
487 488
		   gint        count,
                   gpointer    user_data)
Elliot Lee's avatar
Elliot Lee committed
489
{
490 491
  gdouble *t;
  guint8   tmp[8];
492 493
  gint     i;
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
494 495
  gint     j;
  guint8   swap;
496 497
#endif

498 499
  t = (gdouble *) tmp;

Elliot Lee's avatar
Elliot Lee committed
500 501
  for (i = 0; i < count; i++)
    {
502
      *t = data[i];
503 504

#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
505 506 507 508 509 510
      for (j = 0; j < 4; j++)
        {
          swap = tmp[j];
          tmp[j] = tmp[7 - j];
          tmp[7 - j] = swap;
        }
511 512
#endif

513
      if (! wire_write_int8 (channel, tmp, 8, user_data))
Elliot Lee's avatar
Elliot Lee committed
514
	return FALSE;
515 516 517

#if 0
      {
518
	gint k;
519 520 521

	g_print ("Wire representation of %f:\t", data[i]);

522
	for (k = 0; k < 8; k++)
523
	  {
524
	    g_print ("%02x ", tmp[k]);
525 526 527 528 529
	  }

	g_print ("\n");
      }
#endif
Elliot Lee's avatar
Elliot Lee committed
530 531 532 533 534
    }

  return TRUE;
}

535
gboolean
536 537
wire_write_string (GIOChannel  *channel,
		   gchar      **data,
538 539
		   gint         count,
                   gpointer     user_data)
Elliot Lee's avatar
Elliot Lee committed
540 541
{
  guint32 tmp;
542
  gint    i;
Elliot Lee's avatar
Elliot Lee committed
543 544 545 546 547 548 549 550

  for (i = 0; i < count; i++)
    {
      if (data[i])
	tmp = strlen (data[i]) + 1;
      else
	tmp = 0;

551
      if (! wire_write_int32 (channel, &tmp, 1, user_data))
Elliot Lee's avatar
Elliot Lee committed
552 553
	return FALSE;
      if (tmp > 0)
554
	if (! wire_write_int8 (channel, (guint8 *) data[i], tmp, user_data))
Elliot Lee's avatar
Elliot Lee committed
555 556 557 558 559 560 561
	  return FALSE;
    }

  return TRUE;
}

static void
562
wire_init (void)
Elliot Lee's avatar
Elliot Lee committed
563 564 565 566 567 568 569 570 571 572 573 574 575 576
{
  if (!wire_ht)
    {
      wire_ht = g_hash_table_new ((GHashFunc) wire_hash,
				  (GCompareFunc) wire_compare);
    }
}

static guint
wire_hash (guint32 *key)
{
  return *key;
}

577
static gboolean
Elliot Lee's avatar
Elliot Lee committed
578 579 580 581 582
wire_compare (guint32 *a,
	      guint32 *b)
{
  return (*a == *b);
}