Re: Simplify formatting.c - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Simplify formatting.c
Date
Msg-id 200806140015.m5E0FxX02327@momjian.us
Whole thread Raw
In response to Re: Simplify formatting.c  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: Simplify formatting.c  (Alvaro Herrera <alvherre@commandprompt.com>)
List pgsql-patches
Tom Lane wrote:
> Euler Taveira de Oliveira <euler@timbira.com> 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  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
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);

pgsql-patches by date:

Previous
From: Zdenek Kotala
Date:
Subject: page macros cleanup
Next
From: Tom Lane
Date:
Subject: Re: Tentative patch for making DROP put dependency info in DETAIL