📄 varlena.c
字号:
/*------------------------------------------------------------------------- * * varlena.c * Functions for the variable-length built-in types. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.48.2.1 1999/08/02 05:24:58 scrappy Exp $ * *------------------------------------------------------------------------- */#include <ctype.h>#include "postgres.h"#include "mb/pg_wchar.h"#include "utils/builtins.h"static int text_cmp(text *arg1, text *arg2);/***************************************************************************** * USER I/O ROUTINES * *****************************************************************************/#define VAL(CH) ((CH) - '0')#define DIG(VAL) ((VAL) + '0')/* * byteain - converts from printable representation of byte array * * Non-printable characters must be passed as '\nnn' (octal) and are * converted to internal form. '\' must be passed as '\\'. * elog(ERROR, ...) if bad form. * * BUGS: * The input is scaned twice. * The error checking of input is minimal. */text *byteain(char *inputText){ char *tp; char *rp; int byte; text *result; if (inputText == NULL) elog(ERROR, "Bad input string for type bytea"); for (byte = 0, tp = inputText; *tp != '\0'; byte++) if (*tp++ == '\\') { if (*tp == '\\') tp++; else if (!isdigit(*tp++) || !isdigit(*tp++) || !isdigit(*tp++)) elog(ERROR, "Bad input string for type bytea"); } tp = inputText; byte += VARHDRSZ; result = (text *) palloc(byte); result->vl_len = byte; /* varlena? */ rp = result->vl_dat; while (*tp != '\0') if (*tp != '\\' || *++tp == '\\') *rp++ = *tp++; else { byte = VAL(*tp++); byte <<= 3; byte += VAL(*tp++); byte <<= 3; *rp++ = byte + VAL(*tp++); } return result;}/* * byteaout - converts to printable representation of byte array * * Non-printable characters are inserted as '\nnn' (octal) and '\' as * '\\'. * * NULL vlena should be an error--returning string with NULL for now. */char *byteaout(text *vlena){ char *result; char *vp; char *rp; int val; /* holds unprintable chars */ int i; int len; if (vlena == NULL) { result = (char *) palloc(2); result[0] = '-'; result[1] = '\0'; return result; } vp = vlena->vl_dat; len = 1; /* empty string has 1 char */ for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++) if (*vp == '\\') len += 2; else if (isascii(*vp) && isprint(*vp)) len++; else len += VARHDRSZ; rp = result = (char *) palloc(len); vp = vlena->vl_dat; for (i = vlena->vl_len - VARHDRSZ; i != 0; i--) if (*vp == '\\') { vp++; *rp++ = '\\'; *rp++ = '\\'; } else if (isascii(*vp) && isprint(*vp)) *rp++ = *vp++; else { val = *vp++; *rp = '\\'; rp += 3; *rp-- = DIG(val & 07); val >>= 3; *rp-- = DIG(val & 07); val >>= 3; *rp = DIG(val & 03); rp += 3; } *rp = '\0'; return result;}/* * textin - converts "..." to internal representation */text *textin(char *inputText){ text *result; int len; if (inputText == NULL) return NULL; len = strlen(inputText) + VARHDRSZ; result = (text *) palloc(len); VARSIZE(result) = len; memmove(VARDATA(result), inputText, len - VARHDRSZ);#ifdef CYR_RECODE convertstr(VARDATA(result), len - VARHDRSZ, 0);#endif return result;}/* * textout - converts internal representation to "..." */char *textout(text *vlena){ int len; char *result; if (vlena == NULL) { result = (char *) palloc(2); result[0] = '-'; result[1] = '\0'; return result; } len = VARSIZE(vlena) - VARHDRSZ; result = (char *) palloc(len + 1); memmove(result, VARDATA(vlena), len); result[len] = '\0';#ifdef CYR_RECODE convertstr(result, len, 1);#endif return result;}/* ========== PUBLIC ROUTINES ========== *//* * textlen - * returns the logical length of a text* * (which is less than the VARSIZE of the text*) */int32textlen(text *t){#ifdef MULTIBYTE unsigned char *s; int len, l, wl;#endif if (!PointerIsValid(t)) elog(ERROR, "Null input to textlen");#ifdef MULTIBYTE len = 0; s = VARDATA(t); l = VARSIZE(t) - VARHDRSZ; while (l > 0) { wl = pg_mblen(s); l -= wl; s += wl; len++; } return (len);#else return VARSIZE(t) - VARHDRSZ;#endif} /* textlen() *//* * textoctetlen - * returns the physical length of a text* * (which is less than the VARSIZE of the text*) */int32textoctetlen(text *t){ if (!PointerIsValid(t)) elog(ERROR, "Null input to textoctetlen"); return VARSIZE(t) - VARHDRSZ;} /* textoctetlen() *//* * textcat - * takes two text* and returns a text* that is the concatentation of * the two. * * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96. * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10. * Allocate space for output in all cases. * XXX - thomas 1997-07-10 */text *textcat(text *t1, text *t2){ int len1, len2, len; char *ptr; text *result; if (!PointerIsValid(t1) || !PointerIsValid(t2)) return NULL; len1 = (VARSIZE(t1) - VARHDRSZ); if (len1 < 0) len1 = 0; while (len1 > 0 && VARDATA(t1)[len1 - 1] == '\0') len1--; len2 = (VARSIZE(t2) - VARHDRSZ); if (len2 < 0) len2 = 0; while (len2 > 0 && VARDATA(t2)[len2 - 1] == '\0') len2--; len = len1 + len2 + VARHDRSZ; result = palloc(len); /* Set size of result string... */ VARSIZE(result) = len; /* Fill data field of result string... */ ptr = VARDATA(result); if (len1 > 0) memcpy(ptr, VARDATA(t1), len1); if (len2 > 0) memcpy(ptr + len1, VARDATA(t2), len2); return result;} /* textcat() *//* * text_substr() * Return a substring starting at the specified position. * - thomas 1997-12-31 * * Input: * - string * - starting position (is one-based) * - string length * * If the starting position is zero or less, then return from the start of the string * adjusting the length to be consistant with the "negative start" per SQL92. * If the length is less than zero, return the remaining string. * * Note that the arguments operate on octet length, * so not aware of multi-byte character sets. * * Added multi-byte support. * - Tatsuo Ishii 1998-4-21 * Changed behavior if starting position is less than one to conform to SQL92 behavior. * Formerly returned the entire string; now returns a portion. * - Thomas Lockhart 1998-12-10 */text *text_substr(text *string, int32 m, int32 n){ text *ret; int len;#ifdef MULTIBYTE int i; char *p;#endif if (string == (text *) NULL) return string; len = VARSIZE(string) - VARHDRSZ;#ifdef MULTIBYTE len = pg_mbstrlen_with_len(VARDATA(string), len);#endif /* starting position after the end of the string? */ if (m > len) { m = 1; n = 0; } /* * starting position before the start of the string? then offset into * the string per SQL92 spec... */ else if (m < 1) { n += (m - 1); m = 1; } /* m will now become a zero-based starting position */ m--; if (((m + n) > len) || (n < 0)) n = (len - m);#ifdef MULTIBYTE p = VARDATA(string); for (i = 0; i < m; i++) p += pg_mblen(p); m = p - VARDATA(string); for (i = 0; i < n; i++) p += pg_mblen(p); n = p - (VARDATA(string) + m);#endif ret = (text *) palloc(VARHDRSZ + n); VARSIZE(ret) = VARHDRSZ + n; memcpy(VARDATA(ret), VARDATA(string) + m, n); return ret;} /* text_substr() *//* * textpos - * Return the position of the specified substring. * Implements the SQL92 POSITION() function. * Ref: A Guide To The SQL Standard, Date & Darwen, 1997 * - thomas 1997-07-27 * * Added multi-byte support. * - Tatsuo Ishii 1998-4-21 */int32textpos(text *t1, text *t2){ int pos; int px, p; int len1, len2; pg_wchar *p1, *p2;#ifdef MULTIBYTE pg_wchar *ps1, *ps2;#endif if (!PointerIsValid(t1) || !PointerIsValid(t2)) return 0; if (VARSIZE(t2) <= 0) return 1; len1 = (VARSIZE(t1) - VARHDRSZ); len2 = (VARSIZE(t2) - VARHDRSZ);#ifdef MULTIBYTE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -