forked from AuroraMiddleware/gtk
a4512a4c95
When transitioning from internal to malloc, the strings were placed in the wrong order to g_strconcat(). This fixes an issue with undo where if you hit the boundary in just the right way, your undo stack will do unexpected things. Fixes #5506
172 lines
3.5 KiB
C
172 lines
3.5 KiB
C
#ifndef __GTK_ISTRING_PRIVATE_H__
|
|
#define __GTK_ISTRING_PRIVATE_H__
|
|
|
|
#include <glib.h>
|
|
#include <string.h>
|
|
|
|
typedef struct
|
|
{
|
|
guint n_bytes;
|
|
guint n_chars;
|
|
union {
|
|
char buf[24];
|
|
char *str;
|
|
} u;
|
|
} IString;
|
|
|
|
static inline gboolean
|
|
istring_is_inline (const IString *str)
|
|
{
|
|
return str->n_bytes <= (sizeof str->u.buf - 1);
|
|
}
|
|
|
|
static inline char *
|
|
istring_str (IString *str)
|
|
{
|
|
if (istring_is_inline (str))
|
|
return str->u.buf;
|
|
else
|
|
return str->u.str;
|
|
}
|
|
|
|
static inline void
|
|
istring_clear (IString *str)
|
|
{
|
|
if (istring_is_inline (str))
|
|
str->u.buf[0] = 0;
|
|
else
|
|
g_clear_pointer (&str->u.str, g_free);
|
|
|
|
str->n_bytes = 0;
|
|
str->n_chars = 0;
|
|
}
|
|
|
|
static inline void
|
|
istring_set (IString *str,
|
|
const char *text,
|
|
guint n_bytes,
|
|
guint n_chars)
|
|
{
|
|
if G_LIKELY (n_bytes <= (sizeof str->u.buf - 1))
|
|
{
|
|
memcpy (str->u.buf, text, n_bytes);
|
|
str->u.buf[n_bytes] = 0;
|
|
}
|
|
else
|
|
{
|
|
str->u.str = g_strndup (text, n_bytes);
|
|
}
|
|
|
|
str->n_bytes = n_bytes;
|
|
str->n_chars = n_chars;
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_empty (IString *str)
|
|
{
|
|
return str->n_bytes == 0;
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_ends_with_space (IString *str)
|
|
{
|
|
return g_ascii_isspace (istring_str (str)[str->n_bytes - 1]);
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_starts_with_space (IString *str)
|
|
{
|
|
return g_unichar_isspace (g_utf8_get_char (istring_str (str)));
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_contains_unichar (IString *str,
|
|
gunichar ch)
|
|
{
|
|
return g_utf8_strchr (istring_str (str), str->n_bytes, ch) != NULL;
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_only_contains_space (IString *str)
|
|
{
|
|
const char *iter;
|
|
|
|
for (iter = istring_str (str); *iter; iter = g_utf8_next_char (iter))
|
|
{
|
|
if (!g_unichar_isspace (g_utf8_get_char (iter)))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static inline gboolean
|
|
istring_contains_space (IString *str)
|
|
{
|
|
const char *iter;
|
|
|
|
for (iter = istring_str (str); *iter; iter = g_utf8_next_char (iter))
|
|
{
|
|
if (g_unichar_isspace (g_utf8_get_char (iter)))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static inline void
|
|
istring_prepend (IString *str,
|
|
IString *other)
|
|
{
|
|
if G_LIKELY (str->n_bytes + other->n_bytes < sizeof str->u.buf - 1)
|
|
{
|
|
memmove (str->u.buf + other->n_bytes, str->u.buf, str->n_bytes);
|
|
memcpy (str->u.buf, other->u.buf, other->n_bytes);
|
|
str->n_bytes += other->n_bytes;
|
|
str->n_chars += other->n_chars;
|
|
str->u.buf[str->n_bytes] = 0;
|
|
}
|
|
else
|
|
{
|
|
char *old = NULL;
|
|
|
|
if (!istring_is_inline (str))
|
|
old = str->u.str;
|
|
|
|
str->u.str = g_strconcat (istring_str (other), istring_str (str), NULL);
|
|
str->n_bytes += other->n_bytes;
|
|
str->n_chars += other->n_chars;
|
|
|
|
g_free (old);
|
|
}
|
|
}
|
|
|
|
static inline void
|
|
istring_append (IString *str,
|
|
IString *other)
|
|
{
|
|
const char *text = istring_str (other);
|
|
guint n_bytes = other->n_bytes;
|
|
guint n_chars = other->n_chars;
|
|
|
|
if G_LIKELY (istring_is_inline (str))
|
|
{
|
|
if G_LIKELY (str->n_bytes + n_bytes <= (sizeof str->u.buf - 1))
|
|
memcpy (str->u.buf + str->n_bytes, text, n_bytes);
|
|
else
|
|
str->u.str = g_strconcat (str->u.buf, text, NULL);
|
|
}
|
|
else
|
|
{
|
|
str->u.str = g_realloc (str->u.str, str->n_bytes + n_bytes + 1);
|
|
memcpy (str->u.str + str->n_bytes, text, n_bytes);
|
|
}
|
|
|
|
str->n_bytes += n_bytes;
|
|
str->n_chars += n_chars;
|
|
|
|
istring_str (str)[str->n_bytes] = 0;
|
|
}
|
|
|
|
#endif /* __GTK_ISTRING_PRIVATE_H__ */
|