/* rfc822-gmime-filter-flowed.c generated by valac 0.56.3, the Vala compiler
 * generated from rfc822-gmime-filter-flowed.vala, do not modify */

/*
 * Copyright 2016 Software Freedom Conservancy Inc.
 * Copyright 2016 Michael James Gratton <mike@vee.net>
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later). See the COPYING file in this distribution.
 */

#include <gmime/gmime.h>
#include <glib-object.h>
#include <glib.h>
#include "geary-engine.h"

#define GEARY_RF_C822_TYPE_FILTER_FLOWED (geary_rf_c822_filter_flowed_get_type ())
#define GEARY_RF_C822_FILTER_FLOWED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed))
#define GEARY_RF_C822_FILTER_FLOWED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowedClass))
#define GEARY_RF_C822_IS_FILTER_FLOWED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEARY_RF_C822_TYPE_FILTER_FLOWED))
#define GEARY_RF_C822_IS_FILTER_FLOWED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEARY_RF_C822_TYPE_FILTER_FLOWED))
#define GEARY_RF_C822_FILTER_FLOWED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowedClass))

typedef struct _GearyRFC822FilterFlowed GearyRFC822FilterFlowed;
typedef struct _GearyRFC822FilterFlowedClass GearyRFC822FilterFlowedClass;
typedef struct _GearyRFC822FilterFlowedPrivate GearyRFC822FilterFlowedPrivate;
enum  {
	GEARY_RF_C822_FILTER_FLOWED_0_PROPERTY,
	GEARY_RF_C822_FILTER_FLOWED_NUM_PROPERTIES
};
static GParamSpec* geary_rf_c822_filter_flowed_properties[GEARY_RF_C822_FILTER_FLOWED_NUM_PROPERTIES];

struct _GearyRFC822FilterFlowed {
	GMimeFilter parent_instance;
	GearyRFC822FilterFlowedPrivate * priv;
};

struct _GearyRFC822FilterFlowedClass {
	GMimeFilterClass parent_class;
};

struct _GearyRFC822FilterFlowedPrivate {
	gchar quote_marker;
	gboolean delsp;
	gboolean saw_space;
	gboolean in_prefix;
	guint quote_level;
	guint sig_level;
};

static gint GearyRFC822FilterFlowed_private_offset;
static gpointer geary_rf_c822_filter_flowed_parent_class = NULL;

VALA_EXTERN GType geary_rf_c822_filter_flowed_get_type (void) G_GNUC_CONST ;
VALA_EXTERN GearyRFC822FilterFlowed* geary_rf_c822_filter_flowed_new (gboolean to_html,
                                                          gboolean delsp);
VALA_EXTERN GearyRFC822FilterFlowed* geary_rf_c822_filter_flowed_construct (GType object_type,
                                                                gboolean to_html,
                                                                gboolean delsp);
static void geary_rf_c822_filter_flowed_real_reset (GMimeFilter* base);
static GMimeFilter* geary_rf_c822_filter_flowed_real_copy (GMimeFilter* base);
static void geary_rf_c822_filter_flowed_real_filter (GMimeFilter* base,
                                              guint8* inbuf,
                                              gsize inbuf_length1,
                                              gsize prespace,
                                              guint8** processed_buffer,
                                              gsize* processed_buffer_length1,
                                              gsize* outprespace);
static void geary_rf_c822_filter_flowed_real_complete (GMimeFilter* base,
                                                guint8* inbuf,
                                                gsize inbuf_length1,
                                                gsize prespace,
                                                guint8** processed_buffer,
                                                gsize* processed_buffer_length1,
                                                gsize* outprespace);
static void geary_rf_c822_filter_flowed_finalize (GObject * obj);
static GType geary_rf_c822_filter_flowed_get_type_once (void);

static inline gpointer
geary_rf_c822_filter_flowed_get_instance_private (GearyRFC822FilterFlowed* self)
{
	return G_STRUCT_MEMBER_P (self, GearyRFC822FilterFlowed_private_offset);
}

GearyRFC822FilterFlowed*
geary_rf_c822_filter_flowed_construct (GType object_type,
                                       gboolean to_html,
                                       gboolean delsp)
{
	GearyRFC822FilterFlowed * self = NULL;
	gchar _tmp0_ = '\0';
	self = (GearyRFC822FilterFlowed*) g_object_new (object_type, NULL);
	if (to_html) {
		_tmp0_ = GEARY_RF_C822_UTILS_QUOTE_MARKER;
	} else {
		_tmp0_ = '>';
	}
	self->priv->quote_marker = _tmp0_;
	self->priv->delsp = delsp;
	return self;
}

GearyRFC822FilterFlowed*
geary_rf_c822_filter_flowed_new (gboolean to_html,
                                 gboolean delsp)
{
	return geary_rf_c822_filter_flowed_construct (GEARY_RF_C822_TYPE_FILTER_FLOWED, to_html, delsp);
}

static void
geary_rf_c822_filter_flowed_real_reset (GMimeFilter* base)
{
	GearyRFC822FilterFlowed * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed);
	self->priv->saw_space = FALSE;
	self->priv->in_prefix = TRUE;
	self->priv->quote_level = (guint) 0;
	self->priv->sig_level = (guint) 0;
}

static GMimeFilter*
geary_rf_c822_filter_flowed_real_copy (GMimeFilter* base)
{
	GearyRFC822FilterFlowed * self;
	GearyRFC822FilterFlowed* new_filter = NULL;
	GearyRFC822FilterFlowed* _tmp0_;
	GMimeFilter* result;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed);
	_tmp0_ = geary_rf_c822_filter_flowed_new (self->priv->quote_marker == GEARY_RF_C822_UTILS_QUOTE_MARKER, self->priv->delsp);
	new_filter = _tmp0_;
	new_filter->priv->saw_space = self->priv->saw_space;
	new_filter->priv->in_prefix = self->priv->in_prefix;
	new_filter->priv->quote_level = self->priv->quote_level;
	new_filter->priv->sig_level = self->priv->sig_level;
	result = G_TYPE_CHECK_INSTANCE_CAST (new_filter, g_mime_filter_get_type (), GMimeFilter);
	return result;
}

static void
geary_rf_c822_filter_flowed_real_filter (GMimeFilter* base,
                                         guint8* inbuf,
                                         gsize inbuf_length1,
                                         gsize prespace,
                                         guint8** processed_buffer,
                                         gsize* processed_buffer_length1,
                                         gsize* outprespace)
{
	GearyRFC822FilterFlowed * self;
	guint8* _vala_processed_buffer = NULL;
	gsize _vala_processed_buffer_length1 = 0;
	gsize _vala_outprespace = 0UL;
	guint out_index = 0U;
	guint8* _tmp25_;
	gint _tmp25__length1;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed);
	g_mime_filter_set_size (G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter), (gsize) ((inbuf_length1 + self->priv->quote_level) + 2), FALSE);
	out_index = (guint) 0;
	{
		guint i = 0U;
		i = (guint) 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				guint8 c = 0U;
				guint8 _tmp2_;
				if (!_tmp0_) {
					guint _tmp1_;
					_tmp1_ = i;
					i = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(i < ((guint) inbuf_length1))) {
					break;
				}
				_tmp2_ = inbuf[i];
				c = _tmp2_;
				if (self->priv->in_prefix) {
					if (c == ((guint8) '>')) {
						guint _tmp3_;
						_tmp3_ = self->priv->quote_level;
						self->priv->quote_level = _tmp3_ + 1;
						continue;
					}
					{
						guint j = 0U;
						j = (guint) 0;
						{
							gboolean _tmp4_ = FALSE;
							_tmp4_ = TRUE;
							while (TRUE) {
								guint8* _tmp6_;
								gint _tmp6__length1;
								guint _tmp7_;
								gchar _tmp8_;
								if (!_tmp4_) {
									guint _tmp5_;
									_tmp5_ = j;
									j = _tmp5_ + 1;
								}
								_tmp4_ = FALSE;
								if (!(j < self->priv->quote_level)) {
									break;
								}
								_tmp6_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
								_tmp6__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
								_tmp7_ = out_index;
								out_index = _tmp7_ + 1;
								_tmp8_ = self->priv->quote_marker;
								_tmp6_[_tmp7_] = (guint8) _tmp8_;
							}
						}
					}
					self->priv->in_prefix = FALSE;
					if (c == ((guint8) ' ')) {
						continue;
					}
				}
				switch (c) {
					case ' ':
					{
						if (self->priv->saw_space) {
							guint8* _tmp9_;
							gint _tmp9__length1;
							guint _tmp10_;
							_tmp9_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
							_tmp9__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
							_tmp10_ = out_index;
							out_index = _tmp10_ + 1;
							_tmp9_[_tmp10_] = (guint8) ' ';
							self->priv->sig_level = (guint) 0;
						}
						self->priv->saw_space = TRUE;
						break;
					}
					case '\n':
					{
						gboolean _tmp11_ = FALSE;
						if (self->priv->saw_space) {
							_tmp11_ = self->priv->sig_level != ((guint) 2);
						} else {
							_tmp11_ = FALSE;
						}
						if (_tmp11_) {
							if (!self->priv->delsp) {
								guint8* _tmp12_;
								gint _tmp12__length1;
								guint _tmp13_;
								_tmp12_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
								_tmp12__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
								_tmp13_ = out_index;
								out_index = _tmp13_ + 1;
								_tmp12_[_tmp13_] = (guint8) ' ';
							}
						} else {
							guint8* _tmp16_;
							gint _tmp16__length1;
							guint _tmp17_;
							guint8 _tmp18_;
							if (self->priv->saw_space) {
								guint8* _tmp14_;
								gint _tmp14__length1;
								guint _tmp15_;
								_tmp14_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
								_tmp14__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
								_tmp15_ = out_index;
								out_index = _tmp15_ + 1;
								_tmp14_[_tmp15_] = (guint8) ' ';
							}
							_tmp16_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
							_tmp16__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
							_tmp17_ = out_index;
							out_index = _tmp17_ + 1;
							_tmp18_ = c;
							_tmp16_[_tmp17_] = _tmp18_;
						}
						self->priv->in_prefix = TRUE;
						self->priv->quote_level = (guint) 0;
						self->priv->saw_space = FALSE;
						self->priv->sig_level = (guint) 0;
						break;
					}
					default:
					{
						guint8* _tmp21_;
						gint _tmp21__length1;
						guint _tmp22_;
						guint8 _tmp23_;
						guint _tmp24_ = 0U;
						if (self->priv->saw_space) {
							guint8* _tmp19_;
							gint _tmp19__length1;
							guint _tmp20_;
							_tmp19_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
							_tmp19__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
							_tmp20_ = out_index;
							out_index = _tmp20_ + 1;
							_tmp19_[_tmp20_] = (guint8) ' ';
						}
						_tmp21_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
						_tmp21__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
						_tmp22_ = out_index;
						out_index = _tmp22_ + 1;
						_tmp23_ = c;
						_tmp21_[_tmp22_] = _tmp23_;
						if (c == ((guint8) '-')) {
							_tmp24_ = self->priv->sig_level + 1;
						} else {
							_tmp24_ = (guint) 0;
						}
						self->priv->sig_level = _tmp24_;
						self->priv->saw_space = FALSE;
						break;
					}
				}
			}
		}
	}
	_tmp25_ = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outbuf;
	_tmp25__length1 = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outsize;
	_vala_processed_buffer = _tmp25_ + 0;
	_vala_processed_buffer_length1 = ((gint) out_index) - 0;
	_vala_outprespace = G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter)->outpre;
	if (processed_buffer) {
		*processed_buffer = _vala_processed_buffer;
	}
	if (processed_buffer_length1) {
		*processed_buffer_length1 = _vala_processed_buffer_length1;
	}
	if (outprespace) {
		*outprespace = _vala_outprespace;
	}
}

static void
geary_rf_c822_filter_flowed_real_complete (GMimeFilter* base,
                                           guint8* inbuf,
                                           gsize inbuf_length1,
                                           gsize prespace,
                                           guint8** processed_buffer,
                                           gsize* processed_buffer_length1,
                                           gsize* outprespace)
{
	GearyRFC822FilterFlowed * self;
	guint8* _vala_processed_buffer = NULL;
	gsize _vala_processed_buffer_length1 = 0;
	gsize _vala_outprespace = 0UL;
	guint8* _tmp0_ = NULL;
	gsize _tmp1_ = 0;
	gsize _tmp2_ = 0UL;
	self = G_TYPE_CHECK_INSTANCE_CAST (base, GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed);
	g_mime_filter_filter (G_TYPE_CHECK_INSTANCE_CAST (self, g_mime_filter_get_type (), GMimeFilter), inbuf, (gsize) inbuf_length1, prespace, &_tmp0_, &_tmp1_, &_tmp2_);
	_vala_processed_buffer = _tmp0_;
	_vala_processed_buffer_length1 = _tmp1_;
	_vala_outprespace = _tmp2_;
	if (processed_buffer) {
		*processed_buffer = _vala_processed_buffer;
	}
	if (processed_buffer_length1) {
		*processed_buffer_length1 = _vala_processed_buffer_length1;
	}
	if (outprespace) {
		*outprespace = _vala_outprespace;
	}
}

static void
geary_rf_c822_filter_flowed_class_init (GearyRFC822FilterFlowedClass * klass,
                                        gpointer klass_data)
{
	geary_rf_c822_filter_flowed_parent_class = g_type_class_peek_parent (klass);
	g_type_class_adjust_private_offset (klass, &GearyRFC822FilterFlowed_private_offset);
	((GMimeFilterClass *) klass)->reset = (void (*) (GMimeFilter*)) geary_rf_c822_filter_flowed_real_reset;
	((GMimeFilterClass *) klass)->copy = (GMimeFilter* (*) (GMimeFilter*)) geary_rf_c822_filter_flowed_real_copy;
	((GMimeFilterClass *) klass)->filter = (void (*) (GMimeFilter*, guint8*, gsize, gsize, guint8**, gsize*, gsize*)) geary_rf_c822_filter_flowed_real_filter;
	((GMimeFilterClass *) klass)->complete = (void (*) (GMimeFilter*, guint8*, gsize, gsize, guint8**, gsize*, gsize*)) geary_rf_c822_filter_flowed_real_complete;
	G_OBJECT_CLASS (klass)->finalize = geary_rf_c822_filter_flowed_finalize;
}

static void
geary_rf_c822_filter_flowed_instance_init (GearyRFC822FilterFlowed * self,
                                           gpointer klass)
{
	self->priv = geary_rf_c822_filter_flowed_get_instance_private (self);
	self->priv->saw_space = FALSE;
	self->priv->in_prefix = FALSE;
	self->priv->quote_level = (guint) 0;
	self->priv->sig_level = (guint) 0;
}

static void
geary_rf_c822_filter_flowed_finalize (GObject * obj)
{
	GearyRFC822FilterFlowed * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, GEARY_RF_C822_TYPE_FILTER_FLOWED, GearyRFC822FilterFlowed);
	G_OBJECT_CLASS (geary_rf_c822_filter_flowed_parent_class)->finalize (obj);
}

/**
 * Filter to correctly handle flowed text as described in RFC 3676.
 *
 * This class assumes that CRLF sequences have been replaced with a
 * single LF character.
 *
 * The character `Geary.RFC822.Utils.QUOTE_MARKER` will be output as the
 * quote character instead of `>` if the `to_html` constructor
 * argument is set to `true`.
 */
 G_GNUC_NO_INLINE static GType
geary_rf_c822_filter_flowed_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (GearyRFC822FilterFlowedClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) geary_rf_c822_filter_flowed_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GearyRFC822FilterFlowed), 0, (GInstanceInitFunc) geary_rf_c822_filter_flowed_instance_init, NULL };
	GType geary_rf_c822_filter_flowed_type_id;
	geary_rf_c822_filter_flowed_type_id = g_type_register_static (g_mime_filter_get_type (), "GearyRFC822FilterFlowed", &g_define_type_info, 0);
	GearyRFC822FilterFlowed_private_offset = g_type_add_instance_private (geary_rf_c822_filter_flowed_type_id, sizeof (GearyRFC822FilterFlowedPrivate));
	return geary_rf_c822_filter_flowed_type_id;
}

GType
geary_rf_c822_filter_flowed_get_type (void)
{
	static gsize geary_rf_c822_filter_flowed_type_id__once = 0;
	if (g_once_init_enter (&geary_rf_c822_filter_flowed_type_id__once)) {
		GType geary_rf_c822_filter_flowed_type_id;
		geary_rf_c822_filter_flowed_type_id = geary_rf_c822_filter_flowed_get_type_once ();
		g_once_init_leave (&geary_rf_c822_filter_flowed_type_id__once, geary_rf_c822_filter_flowed_type_id);
	}
	return geary_rf_c822_filter_flowed_type_id__once;
}

