#ifndef REPEAT_H
#define REPEAT_H
#include "ue2common.h"
#include "repeat_internal.h"
#include "util/bitutils.h"
#ifdef __cplusplus
extern "C"
{
#endif
static really_inline
u64a repeatLastTop(const struct RepeatInfo *info,
const union RepeatControl *ctrl, const void *state);
static really_inline
u64a repeatNextMatch(const struct RepeatInfo *info,
const union RepeatControl *ctrl, const void *state,
u64a offset);
static really_inline
void repeatStore(const struct RepeatInfo *info, union RepeatControl *ctrl,
void *state, u64a offset, char is_alive);
enum RepeatMatch {
REPEAT_NOMATCH,
REPEAT_MATCH,
REPEAT_STALE
};
static really_inline
enum RepeatMatch repeatHasMatch(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
void repeatPack(char *dest, const struct RepeatInfo *info,
const union RepeatControl *ctrl, u64a offset);
void repeatUnpack(const char *src, const struct RepeatInfo *info, u64a offset,
union RepeatControl *ctrl);
u64a repeatLastTopRing(const struct RepeatInfo *info,
const union RepeatControl *ctrl);
u64a repeatLastTopRange(const union RepeatControl *ctrl,
const void *state);
u64a repeatLastTopBitmap(const union RepeatControl *ctrl);
u64a repeatLastTopTrailer(const struct RepeatInfo *info,
const union RepeatControl *ctrl);
u64a repeatLastTopSparseOptimalP(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state);
static really_inline
u64a repeatLastTop(const struct RepeatInfo *info,
const union RepeatControl *ctrl, const void *state) {
assert(info && ctrl && state);
switch ((enum RepeatType)info->type) {
case REPEAT_RING:
return repeatLastTopRing(info, ctrl);
case REPEAT_FIRST:
case REPEAT_LAST:
return ctrl->offset.offset;
case REPEAT_RANGE:
return repeatLastTopRange(ctrl, state);
case REPEAT_BITMAP:
return repeatLastTopBitmap(ctrl);
case REPEAT_SPARSE_OPTIMAL_P:
return repeatLastTopSparseOptimalP(info, ctrl, state);
case REPEAT_TRAILER:
return repeatLastTopTrailer(info, ctrl);
case REPEAT_ALWAYS:
return 0;
}
DEBUG_PRINTF("bad repeat type %u\n", info->type);
assert(0);
return 0;
}
static really_inline
u64a repeatNextMatchOffset(const struct RepeatInfo *info,
const union RepeatControl *ctrl, u64a offset) {
u64a first = ctrl->offset.offset + info->repeatMin;
if (offset < first) {
return first;
}
if (info->repeatMax == REPEAT_INF ||
offset < ctrl->offset.offset + info->repeatMax) {
return offset + 1;
}
return 0; }
u64a repeatNextMatchRing(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
u64a repeatNextMatchRange(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
u64a repeatNextMatchBitmap(const struct RepeatInfo *info,
const union RepeatControl *ctrl, u64a offset);
u64a repeatNextMatchSparseOptimalP(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
u64a repeatNextMatchTrailer(const struct RepeatInfo *info,
const union RepeatControl *ctrl, u64a offset);
static really_inline
u64a repeatNextMatch(const struct RepeatInfo *info,
const union RepeatControl *ctrl, const void *state,
u64a offset) {
assert(info && ctrl && state);
assert(ISALIGNED(info));
assert(ISALIGNED(ctrl));
switch ((enum RepeatType)info->type) {
case REPEAT_RING:
return repeatNextMatchRing(info, ctrl, state, offset);
case REPEAT_FIRST:
case REPEAT_LAST:
return repeatNextMatchOffset(info, ctrl, offset);
case REPEAT_RANGE:
return repeatNextMatchRange(info, ctrl, state, offset);
case REPEAT_BITMAP:
return repeatNextMatchBitmap(info, ctrl, offset);
case REPEAT_SPARSE_OPTIMAL_P:
return repeatNextMatchSparseOptimalP(info, ctrl, state, offset);
case REPEAT_TRAILER:
return repeatNextMatchTrailer(info, ctrl, offset);
case REPEAT_ALWAYS:
return offset + 1;
}
DEBUG_PRINTF("bad repeat type %u\n", info->type);
assert(0);
return 0;
}
static really_inline
void repeatStoreFirst(union RepeatControl *ctrl, u64a offset,
char is_alive) {
if (is_alive) {
return;
}
ctrl->offset.offset = offset;
}
static really_inline
void repeatStoreLast(union RepeatControl *ctrl, u64a offset,
UNUSED char is_alive) {
assert(!is_alive || offset >= ctrl->offset.offset);
ctrl->offset.offset = offset;
}
void repeatStoreRing(const struct RepeatInfo *info,
union RepeatControl *ctrl, void *state, u64a offset,
char is_alive);
void repeatStoreRange(const struct RepeatInfo *info,
union RepeatControl *ctrl, void *state, u64a offset,
char is_alive);
void repeatStoreBitmap(const struct RepeatInfo *info,
union RepeatControl *ctrl, u64a offset,
char is_alive);
void repeatStoreSparseOptimalP(const struct RepeatInfo *info,
union RepeatControl *ctrl, void *state,
u64a offset, char is_alive);
void repeatStoreTrailer(const struct RepeatInfo *info,
union RepeatControl *ctrl, u64a offset,
char is_alive);
static really_inline
void repeatStore(const struct RepeatInfo *info, union RepeatControl *ctrl,
void *state, u64a offset, char is_alive) {
assert(info && ctrl && state);
assert(ISALIGNED(info));
assert(ISALIGNED(ctrl));
assert(info->repeatMin <= info->repeatMax);
assert(info->repeatMax <= REPEAT_INF);
switch ((enum RepeatType)info->type) {
case REPEAT_RING:
repeatStoreRing(info, ctrl, state, offset, is_alive);
break;
case REPEAT_FIRST:
repeatStoreFirst(ctrl, offset, is_alive);
break;
case REPEAT_LAST:
repeatStoreLast(ctrl, offset, is_alive);
break;
case REPEAT_RANGE:
repeatStoreRange(info, ctrl, state, offset, is_alive);
break;
case REPEAT_BITMAP:
repeatStoreBitmap(info, ctrl, offset, is_alive);
break;
case REPEAT_SPARSE_OPTIMAL_P:
repeatStoreSparseOptimalP(info, ctrl, state, offset, is_alive);
break;
case REPEAT_TRAILER:
repeatStoreTrailer(info, ctrl, offset, is_alive);
break;
case REPEAT_ALWAYS:
break;
}
}
static really_inline
enum RepeatMatch repeatHasMatchFirst(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
u64a offset) {
if (offset < ctrl->offset.offset + info->repeatMin) {
return REPEAT_NOMATCH;
}
assert(info->repeatMax == REPEAT_INF);
return REPEAT_MATCH;
}
static really_inline
enum RepeatMatch repeatHasMatchLast(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
u64a offset) {
if (offset < ctrl->offset.offset + info->repeatMin) {
return REPEAT_NOMATCH;
}
assert(info->repeatMax < REPEAT_INF);
if (offset <= ctrl->offset.offset + info->repeatMax) {
return REPEAT_MATCH;
}
return REPEAT_STALE;
}
enum RepeatMatch repeatHasMatchRing(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
enum RepeatMatch repeatHasMatchRange(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
enum RepeatMatch repeatHasMatchSparseOptimalP(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset);
enum RepeatMatch repeatHasMatchBitmap(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
u64a offset);
enum RepeatMatch repeatHasMatchTrailer(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
u64a offset);
static really_inline
enum RepeatMatch repeatHasMatch(const struct RepeatInfo *info,
const union RepeatControl *ctrl,
const void *state, u64a offset) {
assert(info && ctrl && state);
assert(ISALIGNED(info));
assert(ISALIGNED(ctrl));
switch ((enum RepeatType)info->type) {
case REPEAT_RING:
return repeatHasMatchRing(info, ctrl, state, offset);
case REPEAT_FIRST:
return repeatHasMatchFirst(info, ctrl, offset);
case REPEAT_LAST:
return repeatHasMatchLast(info, ctrl, offset);
case REPEAT_RANGE:
return repeatHasMatchRange(info, ctrl, state, offset);
case REPEAT_BITMAP:
return repeatHasMatchBitmap(info, ctrl, offset);
case REPEAT_SPARSE_OPTIMAL_P:
return repeatHasMatchSparseOptimalP(info, ctrl, state, offset);
case REPEAT_TRAILER:
return repeatHasMatchTrailer(info, ctrl, offset);
case REPEAT_ALWAYS:
return REPEAT_MATCH;
}
assert(0);
return REPEAT_NOMATCH;
}
#ifdef __cplusplus
}
#endif
#endif