aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/eol.h
blob: 2b426a5d7f3ca8d30bab67219502300382215612 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
 * Copyright (C) 2012-2023 Robin Haberkorn
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#pragma once

#include <glib.h>

#include "sciteco.h"

const gchar *teco_eol_get_seq(gint eol_mode);

typedef struct teco_eol_reader_t teco_eol_reader_t;

struct teco_eol_reader_t {
	gsize read_len;
	guint offset;
	gsize block_len;
	gint last_char;

	gint eol_style;
	gboolean eol_style_inconsistent;

	GIOStatus (*read_cb)(teco_eol_reader_t *ctx, gsize *read_len, GError **error);

	/*
	 * NOTE: This wastes some bytes for "memory" readers,
	 * but avoids inheritance.
	 */
	union {
		struct {
			gchar buffer[1024];
			GIOChannel *channel;
		} gio;

		struct {
			gchar *buffer;
			gsize len;
		} mem;
	};
};

void teco_eol_reader_init_gio(teco_eol_reader_t *ctx, GIOChannel *channel);
void teco_eol_reader_init_mem(teco_eol_reader_t *ctx, gchar *buffer, gsize len);

/** @memberof teco_eol_reader_t */
static inline void
teco_eol_reader_set_channel(teco_eol_reader_t *ctx, GIOChannel *channel)
{
	if (ctx->gio.channel)
		g_io_channel_unref(ctx->gio.channel);
	ctx->gio.channel = channel;
	if (ctx->gio.channel)
		g_io_channel_ref(ctx->gio.channel);
}

GIOStatus teco_eol_reader_convert(teco_eol_reader_t *ctx, gchar **ret, gsize *data_len, GError **error);
GIOStatus teco_eol_reader_convert_all(teco_eol_reader_t *ctx, gchar **ret, gsize *out_len, GError **error);

void teco_eol_reader_clear(teco_eol_reader_t *ctx);

G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(teco_eol_reader_t, teco_eol_reader_clear);

typedef struct teco_eol_writer_t teco_eol_writer_t;

struct teco_eol_writer_t {
	enum {
		TECO_EOL_STATE_START = 0,
		TECO_EOL_STATE_WRITE_LF
	} state;
	gchar last_c;
	const gchar *eol_seq;
	gsize eol_seq_len;

	gssize (*write_cb)(teco_eol_writer_t *ctx, const gchar *buffer, gsize buffer_len, GError **error);

	union {
		struct {
			GIOChannel *channel;
		} gio;

		struct {
			GString *str;
		} mem;
	};
};

void teco_eol_writer_init_gio(teco_eol_writer_t *ctx, gint eol_mode, GIOChannel *channel);
void teco_eol_writer_init_mem(teco_eol_writer_t *ctx, gint eol_mode, GString *str);

/** @memberof teco_eol_writer_t */
static inline void
teco_eol_writer_set_channel(teco_eol_writer_t *ctx, GIOChannel *channel)
{
	if (ctx->gio.channel)
		g_io_channel_unref(ctx->gio.channel);
	ctx->gio.channel = channel;
	if (ctx->gio.channel)
		g_io_channel_ref(ctx->gio.channel);
}

gssize teco_eol_writer_convert(teco_eol_writer_t *ctx, const gchar *buffer,
                               gsize buffer_len, GError **error);

void teco_eol_writer_clear(teco_eol_writer_t *ctx);

G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(teco_eol_writer_t, teco_eol_writer_clear);