Re: Simplify formatting.c

Bruce Momjian <[email protected]>
Newsgroups gmane.comp.db.postgresql.devel.patches
Message-ID <[email protected]>
Tom Lane wrote:
> Euler Taveira de Oliveira <[email protected]> writes:
> > Tom Lane wrote:
> >> Also, it seems a bit inconsistent to be relying on
> >> oracle_compat.c for upper/lower but not initcap.
> >> 
> > I saw this inconsistence while I'm doing the patch. What about moving 
> > that upper/lower/initcap and wcs* code to another file. pg_locale.c? 
> 
> That doesn't seem a particularly appropriate place for them.  pg_locale
> is about dealing with the locale state, not about doing actual
> operations based on the locale data.
> 
> I was just thinking of having oracle_compat expose an initcap routine.

You mean like the attached?

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.

-- 
  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
/pgpatches/initcap (text/x-diff, 5.8 KB)
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.141
diff -c -c -r1.141 formatting.c
*** src/backend/utils/adt/formatting.c	20 May 2008 01:41:02 -0000	1.141
--- src/backend/utils/adt/formatting.c	13 Jun 2008 22:01:18 -0000
***************
*** 927,933 ****
  static int	strdigits_len(char *str);
  static char *str_toupper(char *buff);
  static char *str_tolower(char *buff);
- static char *str_initcap(char *buff);
  
  static int	seq_search(char *name, char **array, int type, int max, int *len);
  static void do_to_timestamp(text *date_txt, text *fmt,
--- 927,932 ----
***************
*** 1484,1549 ****
  }
    
  /* ----------
-  * wide-character-aware initcap function
-  * ----------
-  */
- static char *
- str_initcap(char *buff)
- {
- 	char		*result;
- 	bool		wasalnum = false;
- 
- 	if (!buff)
- 		return NULL;
- 
- #ifdef USE_WIDE_UPPER_LOWER
- 	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
- 	{
- 		wchar_t		*workspace;
- 		text		*in_text;
- 		text		*out_text;
- 		int			i;
- 
- 		in_text = cstring_to_text(buff);
- 		workspace = texttowcs(in_text);
- 
- 		for (i = 0; workspace[i] != 0; i++)
- 		{
- 			if (wasalnum)
- 				workspace[i] = towlower(workspace[i]);
- 			else
- 				workspace[i] = towupper(workspace[i]);
- 			wasalnum = iswalnum(workspace[i]);
- 		}
- 
- 		out_text = wcstotext(workspace, i);
- 		result = text_to_cstring(out_text);
- 
- 		pfree(workspace);
- 		pfree(in_text);
- 		pfree(out_text);
- 	}
- 	else
- #endif		/* USE_WIDE_UPPER_LOWER */
- 	{
- 		char *p;
- 
- 		result = pstrdup(buff);
- 
- 		for (p = result; *p; p++)
- 		{
- 			if (wasalnum)
- 				*p = pg_tolower((unsigned char) *p);
- 			else
- 				*p = pg_toupper((unsigned char) *p);
- 			wasalnum = isalnum((unsigned char) *p);
- 		}
- 	}
- 
- 	return result;
- }
- 
- /* ----------
   * Sequential search with to upper/lower conversion
   * ----------
   */
--- 1483,1488 ----
Index: src/backend/utils/adt/oracle_compat.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v
retrieving revision 1.79
diff -c -c -r1.79 oracle_compat.c
*** src/backend/utils/adt/oracle_compat.c	19 May 2008 18:08:16 -0000	1.79
--- src/backend/utils/adt/oracle_compat.c	13 Jun 2008 22:01:18 -0000
***************
*** 471,478 ****
  Datum
  initcap(PG_FUNCTION_ARGS)
  {
! #ifdef USE_WIDE_UPPER_LOWER
  
  	/*
  	 * Use wide char code only when max encoding length > 1 and ctype != C.
  	 * Some operating systems fail with multi-byte encodings and a C locale.
--- 471,496 ----
  Datum
  initcap(PG_FUNCTION_ARGS)
  {
! 	text	   *string = PG_GETARG_TEXT_PP(0);
! 	char	   *str2;
! 
! 	str2 = str_initcap(DatumGetCString(string));
! 	string = cstring_to_text(str2);
! 	pfree(str2);
! 	PG_RETURN_TEXT_P(string);
! }
! 
  
+ char *
+ str_initcap(char *str)
+ {
+ 	char		*result;
+ 	int			wasalnum = 0;
+ 
+ 	if (!str)
+ 		return NULL;
+ 
+ #ifdef USE_WIDE_UPPER_LOWER
  	/*
  	 * Use wide char code only when max encoding length > 1 and ctype != C.
  	 * Some operating systems fail with multi-byte encodings and a C locale.
***************
*** 480,492 ****
  	 */
  	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
  	{
- 		text	   *string = PG_GETARG_TEXT_PP(0);
- 		text	   *result;
  		wchar_t    *workspace;
! 		int			wasalnum = 0;
  		int			i;
  
! 		workspace = texttowcs(string);
  
  		for (i = 0; workspace[i] != 0; i++)
  		{
--- 498,510 ----
  	 */
  	if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
  	{
  		wchar_t    *workspace;
! 		text		*in_text;
! 		text		*out_text;
  		int			i;
  
! 		in_text = cstring_to_text(str);
! 		workspace = texttowcs(in_text);
  
  		for (i = 0; workspace[i] != 0; i++)
  		{
***************
*** 497,533 ****
  			wasalnum = iswalnum(workspace[i]);
  		}
  
! 		result = wcstotext(workspace, i);
  
  		pfree(workspace);
  
! 		PG_RETURN_TEXT_P(result);
  	}
  	else
  #endif   /* USE_WIDE_UPPER_LOWER */
  	{
- 		text	   *string = PG_GETARG_TEXT_P_COPY(0);
- 		int			wasalnum = 0;
  		char	   *ptr;
- 		int			m;
  
  		/*
  		 * Since we copied the string, we can scribble directly on the value
  		 */
! 		ptr = VARDATA(string);
! 		m = VARSIZE(string) - VARHDRSZ;
! 
! 		while (m-- > 0)
  		{
  			if (wasalnum)
  				*ptr = tolower((unsigned char) *ptr);
  			else
  				*ptr = toupper((unsigned char) *ptr);
  			wasalnum = isalnum((unsigned char) *ptr);
- 			ptr++;
  		}
  
! 		PG_RETURN_TEXT_P(string);
  	}
  }
  
--- 515,548 ----
  			wasalnum = iswalnum(workspace[i]);
  		}
  
! 		out_text = wcstotext(workspace, i);
! 		result = text_to_cstring(out_text);
  
  		pfree(workspace);
+ 		pfree(in_text);
+ 		pfree(out_text);
  
! 		return result;
  	}
  	else
  #endif   /* USE_WIDE_UPPER_LOWER */
  	{
  		char	   *ptr;
  
+ 		result = pstrdup(str);
  		/*
  		 * Since we copied the string, we can scribble directly on the value
  		 */
! 		for (ptr = result; *ptr; ptr++)
  		{
  			if (wasalnum)
  				*ptr = tolower((unsigned char) *ptr);
  			else
  				*ptr = toupper((unsigned char) *ptr);
  			wasalnum = isalnum((unsigned char) *ptr);
  		}
  
! 		return result;
  	}
  }
  
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.316
diff -c -c -r1.316 builtins.h
*** src/include/utils/builtins.h	27 May 2008 00:13:09 -0000	1.316
--- src/include/utils/builtins.h	13 Jun 2008 22:01:19 -0000
***************
*** 727,732 ****
--- 727,733 ----
  extern Datum lower(PG_FUNCTION_ARGS);
  extern Datum upper(PG_FUNCTION_ARGS);
  extern Datum initcap(PG_FUNCTION_ARGS);
+ extern char *str_initcap(char *str);
  extern Datum lpad(PG_FUNCTION_ARGS);
  extern Datum rpad(PG_FUNCTION_ARGS);
  extern Datum btrim(PG_FUNCTION_ARGS);
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.