mirror of
https://salsa.debian.org/dskoll/remind.git
synced 2026-04-16 06:18:47 +02:00
180 lines
6.4 KiB
C
180 lines
6.4 KiB
C
/***************************************************************/
|
|
/* */
|
|
/* DEDUPE.C */
|
|
/* */
|
|
/* Code to suppress duplicate reminders */
|
|
/* */
|
|
/* This file is part of REMIND. */
|
|
/* Copyright (C) 1992-2026 by Dianne Skoll */
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/* */
|
|
/***************************************************************/
|
|
|
|
#include "config.h"
|
|
#include "types.h"
|
|
#include "globals.h"
|
|
#include "protos.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
|
|
typedef struct dedupe_entry {
|
|
struct hash_link link;
|
|
int trigger_date;
|
|
int trigger_time;
|
|
char const *body;
|
|
} DedupeEntry;
|
|
|
|
static hash_table DedupeTable;
|
|
|
|
static unsigned int DedupeHashFunc(void const *x)
|
|
{
|
|
DedupeEntry const *e = (DedupeEntry const *) x;
|
|
unsigned int hashval = (unsigned int) e->trigger_date;
|
|
if (e->trigger_time != NO_TIME) {
|
|
hashval += (unsigned int) e->trigger_time;
|
|
}
|
|
hashval += HashVal_preservecase(e->body);
|
|
return hashval;
|
|
}
|
|
|
|
static int CompareDedupes(void const *x, void const *y)
|
|
{
|
|
DedupeEntry const *a = (DedupeEntry const *) x;
|
|
DedupeEntry const *b = (DedupeEntry const *) y;
|
|
if (a->trigger_date != b->trigger_date) return a->trigger_date - b->trigger_date;
|
|
if (a->trigger_time != b->trigger_time) return a->trigger_time - b->trigger_time;
|
|
return strcmp(a->body, b->body);
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* FreeDedupeEntry */
|
|
/* */
|
|
/* Free a DedupeEntry object */
|
|
/* */
|
|
/***************************************************************/
|
|
static void
|
|
FreeDedupeEntry(DedupeEntry *e)
|
|
{
|
|
if (e->body) {
|
|
free((char *) e->body);
|
|
}
|
|
free(e);
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* FindDedupeEntry */
|
|
/* */
|
|
/* Check if we have a dedupe entry for a given date and body */
|
|
/* */
|
|
/***************************************************************/
|
|
static DedupeEntry *
|
|
FindDedupeEntry(int trigger_date, int trigger_time, char const *body)
|
|
{
|
|
DedupeEntry *e;
|
|
DedupeEntry candidate;
|
|
candidate.body = body;
|
|
candidate.trigger_date = trigger_date;
|
|
candidate.trigger_time = trigger_time;
|
|
e = hash_table_find(&DedupeTable, &candidate);
|
|
return e;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* InsertDedupeEntry */
|
|
/* */
|
|
/* Insert a dedupe entry for given date and body. */
|
|
/* */
|
|
/***************************************************************/
|
|
static void
|
|
InsertDedupeEntry(int trigger_date, int trigger_time, char const *body)
|
|
{
|
|
DedupeEntry *e;
|
|
|
|
e = malloc(sizeof(DedupeEntry));
|
|
if (!e) {
|
|
return; /* No error checking... what can we do? */
|
|
}
|
|
e->trigger_date = trigger_date;
|
|
e->trigger_time = trigger_time;
|
|
e->body = strdup(body);
|
|
if (!e->body) {
|
|
free(e);
|
|
return;
|
|
}
|
|
|
|
hash_table_insert(&DedupeTable, e);
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* ShouldDedupe */
|
|
/* */
|
|
/* Returns 1 if we've already issued this exact reminder; 0 */
|
|
/* otherwise. If it returns 0, remembers that we have seen */
|
|
/* the reminder */
|
|
/* */
|
|
/***************************************************************/
|
|
int
|
|
ShouldDedupe(int trigger_date, int trigger_time, char const *body)
|
|
{
|
|
DedupeEntry const *e = FindDedupeEntry(trigger_date, trigger_time, body);
|
|
|
|
if (e) {
|
|
return 1;
|
|
}
|
|
InsertDedupeEntry(trigger_date, trigger_time, body);
|
|
return 0;
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* ClearDedupeTable */
|
|
/* */
|
|
/* Free all the storage used by the dedupe table */
|
|
/* */
|
|
/***************************************************************/
|
|
void
|
|
ClearDedupeTable(void)
|
|
{
|
|
DedupeEntry *e, *next;
|
|
|
|
e = hash_table_next(&DedupeTable, NULL);
|
|
while(e) {
|
|
next = hash_table_next(&DedupeTable, e);
|
|
hash_table_delete_no_resize(&DedupeTable, e);
|
|
FreeDedupeEntry(e);
|
|
e = next;
|
|
}
|
|
hash_table_free(&DedupeTable);
|
|
InitDedupeTable();
|
|
}
|
|
|
|
/***************************************************************/
|
|
/* */
|
|
/* InitDedupeTable */
|
|
/* */
|
|
/* Initialize the dedupe table at program startup */
|
|
/* */
|
|
/***************************************************************/
|
|
void
|
|
InitDedupeTable(void)
|
|
{
|
|
if (hash_table_init(&DedupeTable,
|
|
offsetof(DedupeEntry, link),
|
|
DedupeHashFunc, CompareDedupes) < 0) {
|
|
fprintf(ErrFp, "Unable to initialize function hash table: Out of memory. Exiting.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
void
|
|
dump_dedupe_hash_stats(void)
|
|
{
|
|
hash_table_dump_stats(&DedupeTable, ErrFp);
|
|
}
|