<commit_before>#ifndef __IMAP_PARSER_H
#define __IMAP_PARSER_H

#include "array.h"

/* FIXME: we don't have ']' here due to FETCH BODY[] handling failing
   with it.. also '%' and '*' are banned due to LIST, and '\' due to it being
   in flags. oh well.. */
#define IS_ATOM_SPECIAL(c) \
	((c) == '(' || (c) == ')' || (c) == '{' || \
	 (c) == '"' || (c) <= 32 || (c) == 0x7f)

enum imap_parser_flags {
	/* Set this flag if you wish to read only size of literal argument
	   and not convert literal into string. Useful when you need to deal
	   with large literal sizes. The literal must be the last read
	   parameter. */
	IMAP_PARSE_FLAG_LITERAL_SIZE	= 0x01,
	/* Don't remove '\' chars from string arguments */
	IMAP_PARSE_FLAG_NO_UNESCAPE	= 0x02,
	/* Return literals as IMAP_ARG_LITERAL instead of IMAP_ARG_STRING */
	IMAP_PARSE_FLAG_LITERAL_TYPE	= 0x04
};

enum imap_arg_type {
	IMAP_ARG_NIL = 0,
	IMAP_ARG_ATOM,
	IMAP_ARG_STRING,
	IMAP_ARG_LIST,

	/* literals are returned as IMAP_ARG_STRING by default */
	IMAP_ARG_LITERAL,
	IMAP_ARG_LITERAL_SIZE,
	IMAP_ARG_LITERAL_SIZE_NONSYNC,

	IMAP_ARG_EOL /* end of argument list */
};

struct imap_parser;

ARRAY_DEFINE_TYPE(imap_arg_list, struct imap_arg);
struct imap_arg {
	enum imap_arg_type type;
        struct imap_arg *parent; /* always of type IMAP_ARG_LIST */

	union {
		const char *str;
		uoff_t literal_size;
		ARRAY_TYPE(imap_arg_list) list;
	} _data;
};

#define IMAP_ARG_STR(arg) \
	((arg)->type == IMAP_ARG_NIL ? NULL : \
	 (arg)->type == IMAP_ARG_ATOM || (arg)->type == IMAP_ARG_STRING || \
	 (arg)->type == IMAP_ARG_LITERAL ? \
	 (arg)->_data.str : _imap_arg_str_error(arg))

#define IMAP_ARG_STR_NONULL(arg) \
	((arg)->type == IMAP_ARG_ATOM || (arg)->type == IMAP_ARG_STRING || \
	 (arg)->type == IMAP_ARG_LITERAL ? \
	 (arg)->_data.str : _imap_arg_str_error(arg))

#define IMAP_ARG_LITERAL_SIZE(arg) \
	(((arg)->type == IMAP_ARG_LITERAL_SIZE || \
	 (arg)->type == IMAP_ARG_LITERAL_SIZE_NONSYNC) ? \
	 (arg)->_data.literal_size : _imap_arg_literal_size_error(arg))

#define IMAP_ARG_LIST(arg) \
	((arg)->type == IMAP_ARG_LIST ? \
	 &(arg)->_data.list : _imap_arg_list_error(arg))
#define IMAP_ARG_LIST_ARGS(arg) \<commit_msg>Added IMAP_ARG_TYPE_IS_STRING()<commit_after>#ifndef __IMAP_PARSER_H
#define __IMAP_PARSER_H

#include "array.h"

/* FIXME: we don't have ']' here due to FETCH BODY[] handling failing
   with it.. also '%' and '*' are banned due to LIST, and '\' due to it being
   in flags. oh well.. */
#define IS_ATOM_SPECIAL(c) \
	((c) == '(' || (c) == ')' || (c) == '{' || \
	 (c) == '"' || (c) <= 32 || (c) == 0x7f)

enum imap_parser_flags {
	/* Set this flag if you wish to read only size of literal argument
	   and not convert literal into string. Useful when you need to deal
	   with large literal sizes. The literal must be the last read
	   parameter. */
	IMAP_PARSE_FLAG_LITERAL_SIZE	= 0x01,
	/* Don't remove '\' chars from string arguments */
	IMAP_PARSE_FLAG_NO_UNESCAPE	= 0x02,
	/* Return literals as IMAP_ARG_LITERAL instead of IMAP_ARG_STRING */
	IMAP_PARSE_FLAG_LITERAL_TYPE	= 0x04
};

enum imap_arg_type {
	IMAP_ARG_NIL = 0,
	IMAP_ARG_ATOM,
	IMAP_ARG_STRING,
	IMAP_ARG_LIST,

	/* literals are returned as IMAP_ARG_STRING by default */
	IMAP_ARG_LITERAL,
	IMAP_ARG_LITERAL_SIZE,
	IMAP_ARG_LITERAL_SIZE_NONSYNC,

	IMAP_ARG_EOL /* end of argument list */
};

struct imap_parser;

ARRAY_DEFINE_TYPE(imap_arg_list, struct imap_arg);
struct imap_arg {
	enum imap_arg_type type;
        struct imap_arg *parent; /* always of type IMAP_ARG_LIST */

	union {
		const char *str;
		uoff_t literal_size;
		ARRAY_TYPE(imap_arg_list) list;
	} _data;
};

#define IMAP_ARG_TYPE_IS_STRING(type) \
	((type) == IMAP_ARG_ATOM || (type) == IMAP_ARG_STRING || \
	 (type) == IMAP_ARG_LITERAL)

#define IMAP_ARG_STR(arg) \
	((arg)->type == IMAP_ARG_NIL ? NULL : \
	 IMAP_ARG_TYPE_IS_STRING((arg)->type) ? \
	 (arg)->_data.str : _imap_arg_str_error(arg))

#define IMAP_ARG_STR_NONULL(arg) \
	((arg)->type == IMAP_ARG_ATOM || (arg)->type == IMAP_ARG_STRING || \
	 (arg)->type == IMAP_ARG_LITERAL ? \
	 (arg)->_data.str : _imap_arg_str_error(arg))

#define IMAP_ARG_LITERAL_SIZE(arg) \
	(((arg)->type == IMAP_ARG_LITERAL_SIZE || \
	 (arg)->type == IMAP_ARG_LITERAL_SIZE_NONSYNC) ? \
	 (arg)->_data.literal_size : _imap_arg_literal_size_error(arg))

#define IMAP_ARG_LIST(arg) \
	((arg)->type == IMAP_ARG_LIST ? \
	 &(arg)->_data.list : _imap_arg_list_error(arg))
#define IMAP_ARG_LIST_ARGS(arg) \
{'fraction_non_alphanumeric': 0.13850291349170776, 'fraction_numerical': 0.0062752129090094125, 'mean_word_length': 4.281656804733728, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4121065', 'n_tokens_mistral': 1877, 'n_tokens_neox': 1817, 'n_words': 384}