#include "utils/float.h"
#include "utils/formatting.h"
#include "utils/int8.h"
+#include "utils/memutils.h"
#include "utils/numeric.h"
#include "utils/pg_locale.h"
*/
typedef struct
{
- char *name; /* suffix string */
+ const char *name; /* suffix string */
int len, /* suffix length */
id, /* used in node->suffix */
- type; /* prefix / postfix */
+ type; /* prefix / postfix */
} KeySuffix;
/* ----------
typedef struct
{
- int type; /* NODE_TYPE_XXX, see below */
- const KeyWord *key; /* if type is ACTION */
+ uint8 type; /* NODE_TYPE_XXX, see below */
char character[MAX_MULTIBYTE_CHAR_LEN + 1]; /* if type is CHAR */
- int suffix; /* keyword prefix/suffix code, if any */
+ uint8 suffix; /* keyword prefix/suffix code, if any */
+ const KeyWord *key; /* if type is ACTION */
} FormatNode;
#define NODE_TYPE_END 1
* For simplicity, the cache entries are fixed-size, so they allow for the
* worst case of a FormatNode for each byte in the picture string.
*
- * The max number of entries in the caches is DCH_CACHE_ENTRIES
+ * The CACHE_SIZE constants are computed to make sizeof(DCHCacheEntry) and
+ * sizeof(NUMCacheEntry) be powers of 2, or just less than that, so that
+ * we don't waste too much space by palloc'ing them individually. Be sure
+ * to adjust those macros if you add fields to those structs.
+ *
+ * The max number of entries in each cache is DCH_CACHE_ENTRIES
* resp. NUM_CACHE_ENTRIES.
* ----------
*/
-#define NUM_CACHE_SIZE 64
-#define NUM_CACHE_ENTRIES 20
-#define DCH_CACHE_SIZE 128
+#define DCH_CACHE_OVERHEAD \
+ MAXALIGN(sizeof(bool) + sizeof(int))
+#define NUM_CACHE_OVERHEAD \
+ MAXALIGN(sizeof(bool) + sizeof(int) + sizeof(NUMDesc))
+
+#define DCH_CACHE_SIZE \
+ ((2048 - DCH_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
+#define NUM_CACHE_SIZE \
+ ((1024 - NUM_CACHE_OVERHEAD) / (sizeof(FormatNode) + sizeof(char)) - 1)
+
#define DCH_CACHE_ENTRIES 20
+#define NUM_CACHE_ENTRIES 20
typedef struct
{
} NUMCacheEntry;
/* global cache for date/time format pictures */
-static DCHCacheEntry DCHCache[DCH_CACHE_ENTRIES];
+static DCHCacheEntry *DCHCache[DCH_CACHE_ENTRIES];
static int n_DCHCache = 0; /* current number of entries */
static int DCHCounter = 0; /* aging-event counter */
/* global cache for number format pictures */
-static NUMCacheEntry NUMCache[NUM_CACHE_ENTRIES];
+static NUMCacheEntry *NUMCache[NUM_CACHE_ENTRIES];
static int n_NUMCache = 0; /* current number of entries */
static int NUMCounter = 0; /* aging-event counter */
*****************************************************************************/
/* ----------
- * Suffixes:
+ * Suffixes (FormatNode.suffix is an OR of these codes)
* ----------
*/
#define DCH_S_FM 0x01
{
DCHCacheEntry *ent;
- /* counter overflow check - paranoia? */
+ /* handle counter overflow by resetting all ages */
if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
{
DCHCounter = 0;
- for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
- ent->age = (++DCHCounter);
+ for (int i = 0; i < n_DCHCache; i++)
+ DCHCache[i]->age = (++DCHCounter);
}
/*
*/
if (n_DCHCache >= DCH_CACHE_ENTRIES)
{
- DCHCacheEntry *old = DCHCache + 0;
+ DCHCacheEntry *old = DCHCache[0];
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);
#endif
if (old->valid)
{
- for (ent = DCHCache + 1; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
+ for (int i = 1; i < DCH_CACHE_ENTRIES; i++)
{
+ ent = DCHCache[i];
if (!ent->valid)
{
old = ent;
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);
#endif
- ent = DCHCache + n_DCHCache;
+ Assert(DCHCache[n_DCHCache] == NULL);
+ DCHCache[n_DCHCache] = ent = (DCHCacheEntry *)
+ MemoryContextAllocZero(TopMemoryContext, sizeof(DCHCacheEntry));
ent->valid = false;
StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1);
ent->age = (++DCHCounter);
static DCHCacheEntry *
DCH_cache_search(const char *str)
{
- int i;
- DCHCacheEntry *ent;
-
- /* counter overflow check - paranoia? */
+ /* handle counter overflow by resetting all ages */
if (DCHCounter >= (INT_MAX - DCH_CACHE_ENTRIES))
{
DCHCounter = 0;
- for (ent = DCHCache; ent < (DCHCache + DCH_CACHE_ENTRIES); ent++)
- ent->age = (++DCHCounter);
+ for (int i = 0; i < n_DCHCache; i++)
+ DCHCache[i]->age = (++DCHCounter);
}
- for (i = 0, ent = DCHCache; i < n_DCHCache; i++, ent++)
+ for (int i = 0; i < n_DCHCache; i++)
{
+ DCHCacheEntry *ent = DCHCache[i];
+
if (ent->valid && strcmp(ent->str, str) == 0)
{
ent->age = (++DCHCounter);
{
NUMCacheEntry *ent;
- /* counter overflow check - paranoia? */
+ /* handle counter overflow by resetting all ages */
if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
{
NUMCounter = 0;
- for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
- ent->age = (++NUMCounter);
+ for (int i = 0; i < n_NUMCache; i++)
+ NUMCache[i]->age = (++NUMCounter);
}
/*
*/
if (n_NUMCache >= NUM_CACHE_ENTRIES)
{
- NUMCacheEntry *old = NUMCache + 0;
+ NUMCacheEntry *old = NUMCache[0];
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "Cache is full (%d)", n_NUMCache);
#endif
if (old->valid)
{
- for (ent = NUMCache + 1; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
+ for (int i = 1; i < NUM_CACHE_ENTRIES; i++)
{
+ ent = NUMCache[i];
if (!ent->valid)
{
old = ent;
#ifdef DEBUG_TO_FROM_CHAR
elog(DEBUG_elog_output, "NEW (%d)", n_NUMCache);
#endif
- ent = NUMCache + n_NUMCache;
+ Assert(NUMCache[n_NUMCache] == NULL);
+ NUMCache[n_NUMCache] = ent = (NUMCacheEntry *)
+ MemoryContextAllocZero(TopMemoryContext, sizeof(NUMCacheEntry));
ent->valid = false;
StrNCpy(ent->str, str, NUM_CACHE_SIZE + 1);
ent->age = (++NUMCounter);
static NUMCacheEntry *
NUM_cache_search(const char *str)
{
- int i;
- NUMCacheEntry *ent;
-
- /* counter overflow check - paranoia? */
+ /* handle counter overflow by resetting all ages */
if (NUMCounter >= (INT_MAX - NUM_CACHE_ENTRIES))
{
NUMCounter = 0;
- for (ent = NUMCache; ent < (NUMCache + NUM_CACHE_ENTRIES); ent++)
- ent->age = (++NUMCounter);
+ for (int i = 0; i < n_NUMCache; i++)
+ NUMCache[i]->age = (++NUMCounter);
}
- for (i = 0, ent = NUMCache; i < n_NUMCache; i++, ent++)
+ for (int i = 0; i < n_NUMCache; i++)
{
+ NUMCacheEntry *ent = NUMCache[i];
+
if (ent->valid && strcmp(ent->str, str) == 0)
{
ent->age = (++NUMCounter);