Re: Simplify formatting.c

Bruce Momjian <[email protected]>
Newsgroups gmane.comp.db.postgresql.devel.patches
Message-ID <[email protected]>
Bruce Momjian wrote:
> Alvaro Herrera wrote:
> > Bruce Momjian wrote:
> > 
> > > I moved str_initcap() over into oracle_compat.c and then had initcap()
> > > convert to/from TEXT to call it.  The code is a little weird because
> > > str_initcap() needs to convert to text to use texttowcs(), so in
> > > multibyte encodings initcap converts the string to text, then to char,
> > > then to text to call texttowcs().  I didn't see a cleaner way to do
> > > this.
> > 
> > Why not use wchar2char?  It seems there's room for extra cleanup here.
> > 
> > Also, the prototype of str_initcap in builtins.h looks out of place.
> 
> I talked to Alvaro on IM, and there is certainly much more cleanup to do
> in this area. I will work from the bottom up.  First, is moving the
> USE_WIDE_UPPER_LOWER define to c.h, and removing TS_USE_WIDE and using
> USE_WIDE_UPPER_LOWER instead.  Patch attached and applied.

The second step is to move wchar2char() and char2wchar() from tsearch
into /mb to be easier to use for other modules;  also move pnstrdup(). 

Patch attached and applied.

-- 
  Bruce Momjian  <[email protected]>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +


-- 
Sent via pgsql-patches mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches
/rtmp/diff (text/x-diff, 11.4 KB)
Index: src/backend/tsearch/ts_locale.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tsearch/ts_locale.c,v
retrieving revision 1.8
diff -c -c -r1.8 ts_locale.c
*** src/backend/tsearch/ts_locale.c	17 Jun 2008 16:09:06 -0000	1.8
--- src/backend/tsearch/ts_locale.c	18 Jun 2008 18:37:02 -0000
***************
*** 16,140 ****
  #include "tsearch/ts_locale.h"
  #include "tsearch/ts_public.h"
  
- 
  #ifdef USE_WIDE_UPPER_LOWER
  
- /*
-  * wchar2char --- convert wide characters to multibyte format
-  *
-  * This has the same API as the standard wcstombs() function; in particular,
-  * tolen is the maximum number of bytes to store at *to, and *from must be
-  * zero-terminated.  The output will be zero-terminated iff there is room.
-  */
- size_t
- wchar2char(char *to, const wchar_t *from, size_t tolen)
- {
- 	if (tolen == 0)
- 		return 0;
- 
- #ifdef WIN32
- 	if (GetDatabaseEncoding() == PG_UTF8)
- 	{
- 		int			r;
- 
- 		r = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
- 								NULL, NULL);
- 
- 		if (r <= 0)
- 			return (size_t) -1;
- 
- 		Assert(r <= tolen);
- 
- 		/* Microsoft counts the zero terminator in the result */
- 		return r - 1;
- 	}
- #endif   /* WIN32 */
- 
- 	return wcstombs(to, from, tolen);
- }
- 
- /*
-  * char2wchar --- convert multibyte characters to wide characters
-  *
-  * This has almost the API of mbstowcs(), except that *from need not be
-  * null-terminated; instead, the number of input bytes is specified as
-  * fromlen.  Also, we ereport() rather than returning -1 for invalid
-  * input encoding.	tolen is the maximum number of wchar_t's to store at *to.
-  * The output will be zero-terminated iff there is room.
-  */
- size_t
- char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen)
- {
- 	if (tolen == 0)
- 		return 0;
- 
- #ifdef WIN32
- 	if (GetDatabaseEncoding() == PG_UTF8)
- 	{
- 		int			r;
- 
- 		/* stupid Microsloth API does not work for zero-length input */
- 		if (fromlen == 0)
- 			r = 0;
- 		else
- 		{
- 			r = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
- 
- 			if (r <= 0)
- 			{
- 				/* see notes in oracle_compat.c about error reporting */
- 				pg_verifymbstr(from, fromlen, false);
- 				ereport(ERROR,
- 						(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
- 						 errmsg("invalid multibyte character for locale"),
- 						 errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
- 			}
- 		}
- 
- 		Assert(r < tolen);
- 		to[r] = 0;
- 
- 		return r;
- 	}
- #endif   /* WIN32 */
- 
- 	if (lc_ctype_is_c())
- 	{
- 		/*
- 		 * pg_mb2wchar_with_len always adds trailing '\0', so 'to' should be
- 		 * allocated with sufficient space
- 		 */
- 		return pg_mb2wchar_with_len(from, (pg_wchar *) to, fromlen);
- 	}
- 	else
- 	{
- 		/*
- 		 * mbstowcs requires ending '\0'
- 		 */
- 		char	   *str = pnstrdup(from, fromlen);
- 		size_t		result;
- 
- 		result = mbstowcs(to, str, tolen);
- 
- 		pfree(str);
- 
- 		if (result == (size_t) -1)
- 		{
- 			pg_verifymbstr(from, fromlen, false);
- 			ereport(ERROR,
- 					(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
- 					 errmsg("invalid multibyte character for locale"),
- 					 errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
- 		}
- 
- 		if (result < tolen)
- 			to[result] = 0;
- 
- 		return result;
- 	}
- }
- 
- 
  int
  t_isdigit(const char *ptr)
  {
--- 16,23 ----
Index: src/backend/tsearch/ts_utils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tsearch/ts_utils.c,v
retrieving revision 1.9
diff -c -c -r1.9 ts_utils.c
*** src/backend/tsearch/ts_utils.c	1 Jan 2008 19:45:52 -0000	1.9
--- src/backend/tsearch/ts_utils.c	18 Jun 2008 18:37:02 -0000
***************
*** 153,165 ****
  			bsearch(&key, s->stop, s->len,
  					sizeof(char *), comparestr)) ? true : false;
  }
- 
- char *
- pnstrdup(const char *in, int len)
- {
- 	char	   *out = palloc(len + 1);
- 
- 	memcpy(out, in, len);
- 	out[len] = '\0';
- 	return out;
- }
--- 153,155 ----
Index: src/backend/utils/mb/mbutils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/mb/mbutils.c,v
retrieving revision 1.71
diff -c -c -r1.71 mbutils.c
*** src/backend/utils/mb/mbutils.c	27 May 2008 12:24:42 -0000	1.71
--- src/backend/utils/mb/mbutils.c	18 Jun 2008 18:37:02 -0000
***************
*** 555,560 ****
--- 555,688 ----
  	return result;
  }
  
+ 
+ 
+ #ifdef USE_WIDE_UPPER_LOWER
+ 
+ /*
+  * wchar2char --- convert wide characters to multibyte format
+  *
+  * This has the same API as the standard wcstombs() function; in particular,
+  * tolen is the maximum number of bytes to store at *to, and *from must be
+  * zero-terminated.  The output will be zero-terminated iff there is room.
+  */
+ size_t
+ wchar2char(char *to, const wchar_t *from, size_t tolen)
+ {
+ 	size_t result;
+ 	
+ 	if (tolen == 0)
+ 		return 0;
+ 
+ #ifdef WIN32
+ 	/*
+ 	 * On Windows, the "Unicode" locales assume UTF16 not UTF8 encoding,
+ 	 * and for some reason mbstowcs and wcstombs won't do this for us,
+ 	 * so we use MultiByteToWideChar().
+ 	 */
+ 	if (GetDatabaseEncoding() == PG_UTF8)
+ 	{
+ 		result = WideCharToMultiByte(CP_UTF8, 0, from, -1, to, tolen,
+ 								NULL, NULL);
+ 		/* A zero return is failure */
+ 		if (result <= 0)
+ 			result = -1;
+ 		else
+ 		{
+ 			Assert(result <= tolen);
+ 			/* Microsoft counts the zero terminator in the result */
+ 			result--;
+ 		}
+ 	}
+ 	else
+ #endif   /* WIN32 */
+ 		result = wcstombs(to, from, tolen);
+ 	return result;
+ }
+ 
+ /*
+  * char2wchar --- convert multibyte characters to wide characters
+  *
+  * This has almost the API of mbstowcs(), except that *from need not be
+  * null-terminated; instead, the number of input bytes is specified as
+  * fromlen.  Also, we ereport() rather than returning -1 for invalid
+  * input encoding.	tolen is the maximum number of wchar_t's to store at *to.
+  * The output will be zero-terminated iff there is room.
+  */
+ size_t
+ char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen)
+ {
+ 	size_t		result;
+ 
+ 	if (tolen == 0)
+ 		return 0;
+ 
+ #ifdef WIN32
+ 	/* See WIN32 "Unicode" comment above */
+ 	if (GetDatabaseEncoding() == PG_UTF8)
+ 	{
+ 		/* Win32 API does not work for zero-length input */
+ 		if (fromlen == 0)
+ 			result = 0;
+ 		else
+ 		{
+ 			result = MultiByteToWideChar(CP_UTF8, 0, from, fromlen, to, tolen - 1);
+ 			/* A zero return is failure */
+ 			if (result == 0)
+ 				result = -1;
+ 		}
+ 
+ 		if (result != -1)
+ 		{
+ 			Assert(result < tolen);
+ 			/* Append trailing null wchar (MultiByteToWideChar() does not) */
+ 			to[result] = 0;
+ 		}
+ 	}
+ 	else
+ #endif   /* WIN32 */
+ 	{
+ 		if (lc_ctype_is_c())
+ 		{
+ 			/*
+ 			 * pg_mb2wchar_with_len always adds trailing '\0', so 'to' should be
+ 			 * allocated with sufficient space
+ 			 */
+ 			result = pg_mb2wchar_with_len(from, (pg_wchar *) to, fromlen);
+ 		}
+ 		else
+ 		{
+ 			/* mbstowcs requires ending '\0' */
+ 			char	   *str = pnstrdup(from, fromlen);
+ 
+ 			result = mbstowcs(to, str, tolen);
+ 			pfree(str);
+ 		}
+ 	}
+ 
+ 	if (result == -1)
+ 	{
+ 		/*
+ 		 * Invalid multibyte character encountered.  We try to give a useful
+ 		 * error message by letting pg_verifymbstr check the string.  But it's
+ 		 * possible that the string is OK to us, and not OK to mbstowcs ---
+ 		 * this suggests that the LC_CTYPE locale is different from the
+ 		 * database encoding.  Give a generic error message if verifymbstr
+ 		 * can't find anything wrong.
+ 		 */
+ 		pg_verifymbstr(from, fromlen, false);	/* might not return */
+ 		/* but if it does ... */
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
+ 				 errmsg("invalid multibyte character for locale"),
+ 				 errhint("The server's LC_CTYPE locale is probably incompatible with the database encoding.")));
+ 	}	
+ 
+ 	return result;
+ }
+ 
+ #endif
+ 
  /* convert a multibyte string to a wchar */
  int
  pg_mb2wchar(const char *from, pg_wchar *to)
Index: src/backend/utils/mmgr/mcxt.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/mmgr/mcxt.c,v
retrieving revision 1.63
diff -c -c -r1.63 mcxt.c
*** src/backend/utils/mmgr/mcxt.c	1 Jan 2008 19:45:55 -0000	1.63
--- src/backend/utils/mmgr/mcxt.c	18 Jun 2008 18:37:05 -0000
***************
*** 624,629 ****
--- 624,641 ----
  												 pointer, size);
  }
  
+ /* Like pstrdup(), but append null byte */
+ char *
+ pnstrdup(const char *in, int len)
+ {
+ 	char	   *out = palloc(len + 1);
+ 
+ 	memcpy(out, in, len);
+ 	out[len] = '\0';
+ 	return out;
+ }
+ 
+ 
  /*
   * MemoryContextSwitchTo
   *		Returns the current context; installs the given context.
Index: src/include/mb/pg_wchar.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/mb/pg_wchar.h,v
retrieving revision 1.78
diff -c -c -r1.78 pg_wchar.h
*** src/include/mb/pg_wchar.h	1 Jan 2008 19:45:58 -0000	1.78
--- src/include/mb/pg_wchar.h	18 Jun 2008 18:37:05 -0000
***************
*** 362,367 ****
--- 362,372 ----
  extern int	pg_encoding_max_length(int encoding);
  extern int	pg_database_encoding_max_length(void);
  
+ #ifdef USE_WIDE_UPPER_LOWER
+ extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen);
+ extern size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen);
+ #endif
+ 
  extern void SetDefaultClientEncoding(void);
  extern int	SetClientEncoding(int encoding, bool doit);
  extern void InitializeClientEncoding(void);
Index: src/include/tsearch/ts_locale.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/tsearch/ts_locale.h,v
retrieving revision 1.6
diff -c -c -r1.6 ts_locale.h
*** src/include/tsearch/ts_locale.h	17 Jun 2008 16:09:06 -0000	1.6
--- src/include/tsearch/ts_locale.h	18 Jun 2008 18:37:05 -0000
***************
*** 33,41 ****
  
  #ifdef USE_WIDE_UPPER_LOWER
  
- extern size_t wchar2char(char *to, const wchar_t *from, size_t tolen);
- extern size_t char2wchar(wchar_t *to, size_t tolen, const char *from, size_t fromlen);
- 
  extern int	t_isdigit(const char *ptr);
  extern int	t_isspace(const char *ptr);
  extern int	t_isalpha(const char *ptr);
--- 33,38 ----
Index: src/include/tsearch/ts_public.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/tsearch/ts_public.h,v
retrieving revision 1.9
diff -c -c -r1.9 ts_public.h
*** src/include/tsearch/ts_public.h	16 May 2008 16:31:02 -0000	1.9
--- src/include/tsearch/ts_public.h	18 Jun 2008 18:37:05 -0000
***************
*** 62,69 ****
  extern char *get_tsearch_config_filename(const char *basename,
  							const char *extension);
  
- extern char *pnstrdup(const char *in, int len);
- 
  /*
   * Often useful stopword list management
   */
--- 62,67 ----
Index: src/include/utils/palloc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/palloc.h,v
retrieving revision 1.38
diff -c -c -r1.38 palloc.h
*** src/include/utils/palloc.h	1 Jan 2008 19:45:59 -0000	1.38
--- src/include/utils/palloc.h	18 Jun 2008 18:37:05 -0000
***************
*** 70,75 ****
--- 70,77 ----
  
  extern void *repalloc(void *pointer, Size size);
  
+ extern char *pnstrdup(const char *in, int len);
+ 
  /*
   * MemoryContextSwitchTo can't be a macro in standard C compilers.
   * But we can make it an inline function when using GCC.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.