imap-sort.c revision 04d0cb8d447c468c6128f03c90a5f4b43c644d42
/* Copyright (C) 2002 Timo Sirainen */
/* Implementation of draft-ietf-imapext-sort-10 sorting algorithm.
Pretty messy code actually, adding any sort types requires care.
This is pretty fast however and takes only as much memory as needed to be
reasonably fast. */
#include "common.h"
#include "buffer.h"
#include "hash.h"
#include "ostream.h"
#include "str.h"
#include "imap-base-subject.h"
#include "mail-storage.h"
#include "message-address.h"
#include "imap-sort.h"
#include <stdlib.h>
#define MAX_WANTED_HEADERS 10
#define STRBUF_SIZE 1024
#define IS_SORT_STRING(type) \
#define IS_SORT_TIME(type) \
struct sort_context {
struct mail_search_context *search_ctx;
struct mailbox_transaction_context *t;
struct hash_table *string_table;
};
static enum mail_sort_type
{
if (*input == MAIL_SORT_REVERSE)
else {
if (reverse) {
}
}
}
}
return mask;
}
static enum mail_sort_type
const enum mail_sort_type *sort2,
unsigned int *count)
{
enum mail_sort_type mask = 0;
*count = 0;
if (*sort1 != MAIL_SORT_REVERSE)
}
return mask;
}
static enum mail_fetch_field
const char *wanted_headers[MAX_WANTED_HEADERS])
{
unsigned int i;
enum mail_fetch_field fields;
/* figure out what data we'd like to cache */
ctx->sort_element_size = sizeof(unsigned int);
ctx->cache_mask = 0;
if (IS_SORT_STRING(type)) {
ctx->sort_element_size += sizeof(const char *);
/* cache the second rule as well, if available */
if (ctx->cache_mask != 0) {
break;
}
} else if (IS_SORT_TIME(type)) {
break;
} else if (type == MAIL_SORT_SIZE) {
break;
}
}
fields = 0;
/* @UNSAFE */
i = 0;
wanted_headers[i++] = "cc";
wanted_headers[i++] = "from";
wanted_headers[i++] = "to";
wanted_headers[i++] = "subject";
wanted_headers[i] = NULL;
0, str_hash,
}
return fields;
}
{
}
struct mail_search_arg *args,
const enum mail_sort_type *sort_program)
{
const char *wanted_headers[MAX_WANTED_HEADERS];
struct sort_context *ctx;
unsigned int count;
int ret;
/* normalize sorting program */
/* remove the common part from sort program, we already know input is
sorted that much so we don't have to worry about it. */
return -1;
if (count > 0) {
sizeof(ctx->sort_program) -
}
/* initialize searching */
ctx->search_ctx =
return -1;
}
(size_t)-1);
}
return ret;
}
{
char *value;
return NULL;
if (*str == '\0')
return "";
}
return value;
}
{
struct message_address *addr;
const char *str;
return NULL;
(const unsigned char *) str,
}
{
const char *str;
time_t t;
if (t != ctx->last_arrival) {
ctx->last_arrival = t;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
if (changed)
}
{
/* @UNSAFE */
unsigned char *buf;
unsigned int id;
time_t t;
const char *str;
t_push();
if (ctx->common_mask != 0)
t = ctx->last_arrival;
else
}
else
}
else
}
else {
}
pos += sizeof(const char *);
}
else {
}
pos += sizeof(const char *);
}
else {
}
pos += sizeof(const char *);
}
else {
}
}
pos += sizeof(const char *);
}
t_pop();
}
static struct sort_context *qsort_context;
{
else {
return NULL;
}
}
struct sort_context *ctx)
{
time_t t;
return 0;
switch (type) {
case MAIL_SORT_ARRIVAL:
case MAIL_SORT_DATE:
if (t == (time_t)-1)
t = 0;
return t;
default:
i_unreached();
return 0;
}
}
/* use memcpy() to avoid any alignment problems */
return t;
}
struct sort_context *ctx)
{
return 0;
}
/* use memcpy() to avoid any alignment problems */
return size;
}
struct sort_context *ctx)
{
const char *str;
enum mail_sort_type type2;
int pos;
return NULL;
switch (type) {
case MAIL_SORT_SUBJECT:
return NULL;
case MAIL_SORT_CC:
break;
case MAIL_SORT_FROM:
break;
case MAIL_SORT_TO:
break;
default:
i_unreached();
}
return str;
}
/* figure out where it is. pretty ugly. */
if (type2 == 0)
pos = 0;
else if (IS_SORT_TIME(type2))
else if (type2 == MAIL_SORT_SIZE)
else {
if (type == MAIL_SORT_SUBJECT)
pos = sizeof(const char *);
pos = sizeof(const char *);
else
pos = 0;
}
/* use memcpy() to avoid any alignment problems */
return str;
}
{
enum mail_sort_type *sorting;
t_push();
ret = 0;
if (*sorting == MAIL_SORT_REVERSE) {
continue;
}
switch (*sorting) {
case MAIL_SORT_ARRIVAL:
case MAIL_SORT_DATE: {
break;
}
case MAIL_SORT_SIZE: {
break;
}
case MAIL_SORT_CC:
case MAIL_SORT_FROM:
case MAIL_SORT_TO:
case MAIL_SORT_SUBJECT:
break;
default:
i_unreached();
}
if (reverse) {
if (ret > 0)
ret = -1;
else if (ret < 0)
ret = 1;
}
}
t_pop();
}
{
unsigned char *arr;
qsort_context = ctx;
if (count == 0)
return;
/* flush */
}
}
}
}