1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
6
* Moonlight List (moonlight-list@lists.ximian.com)
8
* Copyright 2007 Novell, Inc. (http://www.novell.com)
10
* See the LICENSE file included with the distribution for details.
18
#include <glib/gstdio.h>
23
#include <sys/types.h>
39
* Finds the midpoint between positive integer values, @lo and @hi.
41
* Notes: Typically expressed as '(@lo + @hi) / 2', this is incorrect
42
* when @lo and @hi are sufficiently large enough that combining them
43
* would overflow their integer type. To work around this, we use the
44
* formula, '@lo + ((@hi - @lo) / 2)', thus preventing this problem
47
* Returns the midpoint between @lo and @hi (rounded down).
49
#define MID(lo, hi) (lo + ((hi - lo) >> 1))
53
bsearch (GPtrArray *array, bool stable, GCompareFunc cmp, void *item)
55
register guint lo, hi;
62
lo = 0, hi = array->len;
66
if ((c = cmp (&item, &array->pdata[m])) > 0) {
83
g_ptr_array_insert_sorted (GPtrArray *array, GCompareFunc cmp, void *item)
85
guint index = bsearch (array, true, cmp, item);
87
g_ptr_array_insert (array, index, item);
91
g_ptr_array_insert (GPtrArray *array, guint index, void *item)
96
if (index >= array->len) {
97
g_ptr_array_add (array, item);
101
g_ptr_array_set_size (array, array->len + 1);
103
dest = ((guint8 *) array->pdata) + (sizeof (void *) * (index + 1));
104
src = ((guint8 *) array->pdata) + (sizeof (void *) * index);
105
n = array->len - index - 1;
107
memmove (dest, src, (sizeof (void *) * n));
108
array->pdata[index] = item;
112
write_all (int fd, char *buf, size_t len)
119
n = write (fd, buf + nwritten, len - nwritten);
120
} while (n == -1 && errno == EINTR);
126
} while (nwritten < len);
132
ExtractFile (unzFile zip, int fd)
140
if ((nread = unzReadCurrentFile (zip, buf, sizeof (buf))) > 0) {
141
if ((n = write_all (fd, buf, nread)) == -1)
146
if (nread != 0 || n == -1 || fsync (fd) == -1) {
159
MakeTempDir (char *tmpdir)
165
if ((n = strlen (tmpdir)) < 6) {
170
xxx = tmpdir + (n - 6);
171
if (strcmp (xxx, "XXXXXX") != 0) {
177
if (!(path = mktemp (tmpdir)))
180
if (g_mkdir (tmpdir, 0700) != -1)
183
if (errno != EEXIST) {
184
// don't bother trying again...
188
// that path already exists, try a new one...
189
strcpy (xxx, "XXXXXX");
191
} while (attempts < 100);
198
rmdir_real (GString *path)
205
if (!(dir = opendir (path->str)))
208
g_string_append_c (path, G_DIR_SEPARATOR);
211
while ((dent = readdir (dir))) {
212
if (!strcmp (dent->d_name, ".") || !strcmp (dent->d_name, ".."))
215
g_string_truncate (path, len);
216
g_string_append (path, dent->d_name);
218
if (lstat (path->str, &st) == -1)
221
if (S_ISDIR (st.st_mode))
224
g_unlink (path->str);
229
g_string_truncate (path, len - 1);
231
return g_rmdir (path->str);
235
// Creates a temporary directory, based on the @filename template
237
// Returns: a g-allocated string name that points to the created
238
// directory, or NULL on failure
241
CreateTempDir (const char *filename)
246
if (!(name = strrchr (filename, '/')))
251
buf = g_strdup_printf ("%s.XXXXXX", name);
252
path = g_build_filename (g_get_tmp_dir (), buf, NULL);
255
if (!MakeTempDir (path)) {
264
RemoveDir (const char *dir)
269
path = g_string_new (dir);
270
rv = rmdir_real (path);
271
g_string_free (path, true);
277
CopyFileTo (const char *filename, int fd)
283
if ((in = open (filename, O_RDONLY)) == -1)
288
nread = read (in, buf, sizeof (buf));
289
} while (nread == -1 && errno == EINTR);
297
if (write_all (fd, buf, nread) == -1)
301
if (fsync (fd) == -1)
318
measuring_context_create (void)
320
cairo_surface_t* surf = cairo_image_surface_create (CAIRO_FORMAT_A1, 1, 1);
321
return cairo_create (surf);
325
measuring_context_destroy (cairo_t *cr)
327
cairo_surface_destroy (cairo_get_target (cr));
333
read_internal (int fd, char *buf, size_t n)
338
nread = read (fd, buf, n);
339
} while (nread == -1 && errno == EINTR);
345
TextStream::TextStream ()
355
TextStream::~TextStream ()
360
if (cd != (GIConv) -1) {
366
#define BOM ((gunichar2) 0xFEFF)
367
#define ANTIBOM ((gunichar2) 0xFFFE)
378
static const char *encoding_names[] = { "UTF-16BE", "UTF-16LE", "UTF-32BE", "UTF-32LE", "UTF-8" };
382
TextStream::OpenBuffer (const char *buf, int size)
386
textbufptr = textbuf = (char *) buf;
392
return ReadBOM (false);
396
TextStream::OpenFile (const char *filename, bool force)
403
if ((fd = open (filename, O_RDONLY)) == -1)
406
return ReadBOM (force);
410
TextStream::ReadBOM (bool force)
412
Encoding encoding = UNKNOWN;
416
// prefetch the first chunk of data in order to determine encoding
417
if ((nread = ReadInternal (buffer, sizeof (buffer))) == -1) {
427
memcpy (&bom, buffer, 2);
441
memcpy (&bom, buffer + 2, 2);
442
if (bom == ANTIBOM) {
446
} else if (bom == BOM) {
462
if (encoding == UNKNOWN) {
472
if (encoding != UTF8 && (cd = g_iconv_open ("UTF-8", encoding_names[encoding])) == (GIConv) -1) {
491
if (cd != (GIConv) -1) {
504
return eof && buflen == 0;
508
TextStream::Read (char *buf, size_t n)
510
size_t inleft = buflen;
511
char *inbuf = bufptr;
518
if (cd != (GIConv) -1) {
519
if (g_iconv (cd, &inbuf, &inleft, &outbuf, &outleft) == (size_t) -1) {
522
// not enough space available in the output buffer
525
// incomplete multibyte character sequence
528
// illegal multibyte sequence
531
// unknown error, fail
536
r = MIN (inleft, outleft);
537
memcpy (outbuf, inbuf, r);
544
if (outleft == 0 || eof)
549
memmove (buffer, inbuf, inleft);
551
inbuf = buffer + inleft;
552
if ((nread = ReadInternal (inbuf, sizeof (buffer) - inleft)) <= 0) {
561
if (eof && cd != (GIConv) -1)
562
g_iconv (cd, NULL, NULL, &outbuf, &outleft);
569
return (outbuf - buf);
573
TextStream::ReadInternal (char *buffer, ssize_t size)
576
return read_internal (fd, buffer, size);
578
ssize_t nread = size;
583
if (textbufptr + size > textbuf + textbufsize) {
585
nread = textbuf + textbufsize - textbufptr;
587
memcpy (buffer, textbufptr, nread);
596
GArray *double_garray_from_str (const char *s, gint max)
598
char *next = (char *)s;
599
GArray *values = g_array_sized_new (false, true, sizeof (double), max > 0 ? max : 16);
601
guint end = max > 0 ? max : G_MAXINT;
603
while (next && values->len < end) {
604
while (g_ascii_isspace (*next) || *next == ',')
605
next = g_utf8_next_char (next);
610
coord = g_ascii_strtod (prev, &next);
611
if (errno != 0 || next == prev)
614
g_array_append_val (values, coord);
619
while (values->len < (guint) max) {
621
g_array_append_val (values, coord);