From e3f5bc3492efa1fa6d20491bb3134c9b32f30b7d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 21 Sep 2001 15:27:38 +0000
Subject: [PATCH] Fix type_maximum_size() to give the right answer in MULTIBYTE
 cases. Avoid use of prototype-less function pointers in MB code.

---
 src/backend/utils/adt/format_type.c | 19 ++++++++++++---
 src/backend/utils/mb/mbutils.c      | 32 ++++++++++++++----------
 src/backend/utils/mb/wchar.c        | 25 +++++++++++++------
 src/include/mb/pg_wchar.h           | 38 ++++++++++++++++++-----------
 4 files changed, 76 insertions(+), 38 deletions(-)

diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 3f209d63b88..59b516556c9 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.14 2001/08/09 18:28:18 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.15 2001/09/21 15:27:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,10 @@
 #include "utils/builtins.h"
 #include "utils/numeric.h"
 #include "utils/syscache.h"
+#ifdef MULTIBYTE
+#include "mb/pg_wchar.h"
+#endif
+
 
 #define MAX_INT32_LEN 11
 #define _textin(str) DirectFunctionCall1(textin, CStringGetDatum(str))
@@ -249,9 +253,9 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
 
 
 /*
- * type_maximum_size --- determine maximum length of a varlena column
+ * type_maximum_size --- determine maximum width of a varlena column
  *
- * If the max length is indeterminate, return -1.  In particular, we return
+ * If the max width is indeterminate, return -1.  In particular, we return
  * -1 for any type not known to this routine.  We assume the caller has
  * already determined that the type is a varlena type, so it's not
  * necessary to look up the type's pg_type tuple here.
@@ -271,7 +275,14 @@ type_maximum_size(Oid type_oid, int32 typemod)
 		case BPCHAROID:
 		case VARCHAROID:
 			/* typemod includes varlena header */
+#ifdef MULTIBYTE
+			/* typemod is in characters not bytes */
+			return (typemod - VARHDRSZ) *
+				pg_encoding_max_length(GetDatabaseEncoding())
+				+ VARHDRSZ;
+#else
 			return typemod;
+#endif
 
 		case NUMERICOID:
 			/* precision (ie, max # of digits) is in upper bits of typmod */
@@ -291,7 +302,7 @@ type_maximum_size(Oid type_oid, int32 typemod)
 				+ 2 * sizeof(int32);
 	}
 
-	/* Unknown type, or unlimited-length type such as 'text' */
+	/* Unknown type, or unlimited-width type such as 'text' */
 	return -1;
 }
 
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 4f15529aedf..177cd3a1d6f 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -3,7 +3,7 @@
  * client encoding and server internal encoding.
  * (currently mule internal code (mic) is used)
  * Tatsuo Ishii
- * $Id: mbutils.c,v 1.22 2001/09/09 01:15:11 ishii Exp $
+ * $Id: mbutils.c,v 1.23 2001/09/21 15:27:38 tgl Exp $
  */
 #include "postgres.h"
 
@@ -24,10 +24,10 @@
 static pg_enc2name	*ClientEncoding = &pg_enc2name_tbl[ PG_SQL_ASCII ];
 static pg_enc2name	*DatabaseEncoding = &pg_enc2name_tbl[ PG_SQL_ASCII ];
 
-static void	(*client_to_mic) ();	/* something to MIC */
-static void	(*client_from_mic) ();	/* MIC to something */
-static void	(*server_to_mic) ();	/* something to MIC */
-static void	(*server_from_mic) ();	/* MIC to something */
+static to_mic_converter client_to_mic;	/* something to MIC */
+static from_mic_converter client_from_mic;	/* MIC to something */
+static to_mic_converter server_to_mic;	/* something to MIC */
+static from_mic_converter server_from_mic;	/* MIC to something */
 
 /*
  * find encoding table entry by encoding
@@ -60,7 +60,9 @@ pg_get_enconv_by_encoding(int encoding)
  * appropriate function found, set to 0.
  */
 int
-pg_find_encoding_converters(int src, int dest, void (**src_to_mic)(), void (**dest_from_mic)())
+pg_find_encoding_converters(int src, int dest,
+							to_mic_converter *src_to_mic,
+							from_mic_converter *dest_from_mic)
 {
 	if (src == dest)
 	{							/* src == dest? */
@@ -132,7 +134,7 @@ pg_set_client_encoding(int encoding)
  * returns the current client encoding
  */
 int
-pg_get_client_encoding()
+pg_get_client_encoding(void)
 {
 	Assert(ClientEncoding);
 	return (ClientEncoding->encoding);
@@ -142,7 +144,7 @@ pg_get_client_encoding()
  * returns the current client encoding name
  */
 const char *
-pg_get_client_encoding_name()
+pg_get_client_encoding_name(void)
 {
 	Assert(ClientEncoding);
 	return (ClientEncoding->name);
@@ -176,7 +178,9 @@ pg_get_client_encoding_name()
  * in the length of the string --- is this enough?  */
 
 unsigned char *
-pg_do_encoding_conversion(unsigned char *src, int len, void (*src_to_mic)(), void (*dest_from_mic)())
+pg_do_encoding_conversion(unsigned char *src, int len,
+						  to_mic_converter src_to_mic,
+						  from_mic_converter dest_from_mic)
 {
 	unsigned char *result = src;
 	unsigned char *buf;
@@ -212,7 +216,8 @@ pg_convert(PG_FUNCTION_ARGS)
 	Name	s = PG_GETARG_NAME(1);
 	int encoding = pg_char_to_encoding(NameStr(*s));
 	int db_encoding = DatabaseEncoding->encoding;
-	void (*src)(), (*dest)();
+	to_mic_converter src;
+	from_mic_converter dest;
 	unsigned char	*result;
 	text	*retval;
 
@@ -253,7 +258,8 @@ pg_convert2(PG_FUNCTION_ARGS)
 	int src_encoding = pg_char_to_encoding(src_encoding_name);
 	char *dest_encoding_name = NameStr(*PG_GETARG_NAME(2));
 	int dest_encoding = pg_char_to_encoding(dest_encoding_name);
-	void (*src)(), (*dest)();
+	to_mic_converter src;
+	from_mic_converter dest;
 	unsigned char	*result;
 	text	*retval;
 
@@ -446,14 +452,14 @@ SetDatabaseEncoding(int encoding)
 }
 
 int
-GetDatabaseEncoding()
+GetDatabaseEncoding(void)
 {
 	Assert(DatabaseEncoding);
 	return (DatabaseEncoding->encoding);
 }
 
 const char *
-GetDatabaseEncodingName()
+GetDatabaseEncodingName(void)
 {
 	Assert(DatabaseEncoding);
 	return (DatabaseEncoding->name);
diff --git a/src/backend/utils/mb/wchar.c b/src/backend/utils/mb/wchar.c
index 114b7f26234..2da50bdd175 100644
--- a/src/backend/utils/mb/wchar.c
+++ b/src/backend/utils/mb/wchar.c
@@ -1,21 +1,21 @@
 /*
  * conversion functions between pg_wchar and multi-byte streams.
  * Tatsuo Ishii
- * $Id: wchar.c,v 1.20 2001/09/11 04:50:36 ishii Exp $
+ * $Id: wchar.c,v 1.21 2001/09/21 15:27:38 tgl Exp $
  *
  * WIN1250 client encoding updated by Pavel Behal
  *
  */
 /* can be used in either frontend or backend */
-#include "postgres_fe.h"
-#include "mb/pg_wchar.h"
-
 #ifdef FRONTEND
-	#define Assert(condition)
+#include "postgres_fe.h"
+#define Assert(condition)
 #else
-	#include "postgres.h"
+#include "postgres.h"
 #endif
 
+#include "mb/pg_wchar.h"
+
 
 /*
  * conversion to pg_wchar is done by "table driven."
@@ -499,6 +499,17 @@ pg_encoding_mblen(int encoding, const unsigned char *mbstr)
 			((*pg_wchar_table[PG_SQL_ASCII].mblen) (mbstr)));
 }
 
+/*
+ * fetch maximum length of a char encoding
+ */
+int
+pg_encoding_max_length(int encoding)
+{
+	Assert(PG_VALID_ENCODING(encoding));
+
+	return pg_wchar_table[encoding].maxmblen;
+}
+
 #ifndef FRONTEND
 /*
  * Verify mbstr to make sure that it has a valid character sequence.
@@ -517,7 +528,7 @@ pg_verifymbstr(const unsigned char *mbstr, int len)
 	int	slen = 0;
 
 	/* we do not check single byte encodings */
-	if (pg_wchar_table[GetDatabaseEncoding()].maxmblen <= 1)
+	if (pg_encoding_max_length(GetDatabaseEncoding()) <= 1)
 	    return NULL;
 
 	while (len > 0 && *mbstr)
diff --git a/src/include/mb/pg_wchar.h b/src/include/mb/pg_wchar.h
index 35bb58a1526..d27e316bde9 100644
--- a/src/include/mb/pg_wchar.h
+++ b/src/include/mb/pg_wchar.h
@@ -1,4 +1,4 @@
-/* $Id: pg_wchar.h,v 1.30 2001/09/11 04:50:36 ishii Exp $ */
+/* $Id: pg_wchar.h,v 1.31 2001/09/21 15:27:38 tgl Exp $ */
 
 #ifndef PG_WCHAR_H
 #define PG_WCHAR_H
@@ -17,7 +17,6 @@
  */
 #ifdef MULTIBYTE
 typedef unsigned int pg_wchar;
-
 #else
 #define pg_wchar char
 #endif
@@ -152,6 +151,9 @@ extern pg_encname	*pg_char_to_encname_struct(const char *name);
 extern int		pg_char_to_encoding(const char *s);
 extern const char	*pg_encoding_to_char(int encoding);
 
+typedef void (*to_mic_converter) (unsigned char *l, unsigned char *p, int len);
+typedef void (*from_mic_converter) (unsigned char *mic, unsigned char *p, int len);
+
 /*
  * The backend encoding conversion routines
  * Careful:
@@ -162,11 +164,11 @@ extern const char	*pg_encoding_to_char(int encoding);
 #ifndef FRONTEND
 typedef struct pg_enconv
 {
-	pg_enc		encoding;		/* encoding identificator */
-	void		(*to_mic) ();		/* client encoding to MIC */
-	void		(*from_mic) (); 	/* MIC to client encoding */
-	void		(*to_unicode) ();	/* client encoding to UTF-8 */
-	void		(*from_unicode) ();	/* UTF-8 to client encoding */
+	pg_enc		encoding;					/* encoding identifier */
+	to_mic_converter	to_mic;				/* client encoding to MIC */
+	from_mic_converter	from_mic;			/* MIC to client encoding */
+	to_mic_converter to_unicode;			/* client encoding to UTF-8 */
+	from_mic_converter from_unicode;		/* UTF-8 to client encoding */
 } pg_enconv;
 
 extern pg_enconv pg_enconv_tbl[];
@@ -177,13 +179,16 @@ extern pg_enconv *pg_get_enconv_by_encoding(int encoding);
 /*
  * pg_wchar stuff
  */
+typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
+											pg_wchar *to,
+											int len);
+typedef int (*mblen_converter) (const unsigned char *mbstr);
+
 typedef struct
 {
-	int		(*mb2wchar_with_len) ();	/* convert a multi-byte	
-							 * string to a wchar */
-	int		(*mblen) ();			/* returns the length of a multi-byte word */
-	int		maxmblen;			/* max bytes for a letter in this charset */
-
+	mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multi-byte string to a wchar */
+	mblen_converter mblen;		/* returns the length of a multi-byte char */
+	int		maxmblen;			/* max bytes for a char in this charset */
 } pg_wchar_tbl;
 
 extern pg_wchar_tbl pg_wchar_table[];
@@ -220,6 +225,7 @@ extern int	pg_mbstrlen(const unsigned char *);
 extern int	pg_mbstrlen_with_len(const unsigned char *, int);
 extern int	pg_mbcliplen(const unsigned char *, int, int);
 extern int	pg_mbcharcliplen(const unsigned char *, int, int);
+extern int	pg_encoding_max_length(int);
 
 extern int		pg_set_client_encoding(int);
 extern int		pg_get_client_encoding(void);
@@ -233,8 +239,12 @@ extern int	pg_valid_client_encoding(const char *name);
 extern int	pg_valid_server_encoding(const char *name);
 
 extern int	pg_utf_mblen(const unsigned char *);
-extern int	pg_find_encoding_converters(int, int, void (**)(), void (**)());
-extern unsigned char *pg_do_encoding_conversion(unsigned char *, int, void (*)(), void (*)());
+extern int	pg_find_encoding_converters(int src, int dest,
+										to_mic_converter *src_to_mic,
+										from_mic_converter *dest_from_mic);
+extern unsigned char *pg_do_encoding_conversion(unsigned char *src, int len,
+												to_mic_converter src_to_mic,
+												from_mic_converter dest_from_mic);
 
 extern unsigned char *pg_client_to_server(unsigned char *, int);
 extern unsigned char *pg_server_to_client(unsigned char *, int);
-- 
GitLab