summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/expandedstring.c
blob: 4e279a3aa16f82dbbeb4ffcb8cd2d2f9c30115fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*-------------------------------------------------------------------------
 *
 * expandedstring.c
 *	  Expand a varlena into a StringInfo.
 *
 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  src/backend/utils/adt/expandeddatum.c
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "fmgr.h"
#include "utils/expandedstring.h"
#include "utils/memutils.h"

static Size ESI_get_flat_size(ExpandedObjectHeader *eohptr);
static void ESI_flatten_into(ExpandedObjectHeader *eohptr,
				 void *result, Size allocated_size);

static const ExpandedObjectMethods ESI_methods =
{
	ESI_get_flat_size,
	ESI_flatten_into
};

/*
 * Construct an expanded datum consisting of an empty StringInfo.
 *
 * Caller must ensure that CurrentMemoryContext points to a context with
 * a suitable lifetime.
 */
ExpandedStringInfoHeader *
GetExpandedStringInfo(void)
{
	ExpandedStringInfoHeader *esih;
	MemoryContext	objcxt;
	MemoryContext	oldcxt;

	objcxt = AllocSetContextCreate(CurrentMemoryContext,
								   "stringinfo expanded object",
								   ALLOCSET_SMALL_MINSIZE,
								   ALLOCSET_SMALL_INITSIZE,
								   ALLOCSET_DEFAULT_MAXSIZE);

	oldcxt = MemoryContextSwitchTo(objcxt);	
	esih = palloc(sizeof(ExpandedStringInfoHeader));
	EOH_init_header(&esih->hdr, &ESI_methods, objcxt);
	initStringInfo(&esih->buf);
	MemoryContextSwitchTo(oldcxt);

	return esih;
}

/*
 * The space required to flatten a StringInfo back to a plain old varlena is
 * just the number of bytes we have in the buffer, plus the size of a 4-byte
 * header.  Even if the buffer is short, we can't flatten to a packed
 * representation.
 */
static Size
ESI_get_flat_size(ExpandedObjectHeader *eohptr)
{
	ExpandedStringInfoHeader *esih = (ExpandedStringInfoHeader *) eohptr;

	return VARHDRSZ + esih->buf.len;
}

/*
 * Flattening a StringInfo just involves copying the data into the allocated
 * space.
 */
static void
ESI_flatten_into(ExpandedObjectHeader *eohptr,
				 void *result, Size allocated_size)
{
	ExpandedStringInfoHeader *esih = (ExpandedStringInfoHeader *) eohptr;

	Assert(allocated_size == VARHDRSZ + esih->buf.len);
	memcpy(VARDATA(result), esih->buf.data, esih->buf.len);
	SET_VARSIZE(result, VARHDRSZ + esih->buf.len);
}