Header And Logo

PostgreSQL
| The world's most advanced open source database.

plperl_helpers.h

Go to the documentation of this file.
00001 #ifndef PL_PERL_HELPERS_H
00002 #define PL_PERL_HELPERS_H
00003 
00004 /*
00005  * convert from utf8 to database encoding
00006  *
00007  * Returns a palloc'ed copy of the original string
00008  */
00009 static inline char *
00010 utf_u2e(char *utf8_str, size_t len)
00011 {
00012     int         enc = GetDatabaseEncoding();
00013     char       *ret;
00014 
00015     /*
00016      * When we are in a PG_UTF8 or SQL_ASCII database
00017      * pg_do_encoding_conversion() will not do any conversion (which is good)
00018      * or verification (not so much), so we need to run the verification step
00019      * separately.
00020      */
00021     if (enc == PG_UTF8 || enc == PG_SQL_ASCII)
00022     {
00023         pg_verify_mbstr_len(enc, utf8_str, len, false);
00024         ret = utf8_str;
00025     }
00026     else
00027         ret = (char *) pg_do_encoding_conversion((unsigned char *) utf8_str,
00028                                                  len, PG_UTF8, enc);
00029 
00030     if (ret == utf8_str)
00031         ret = pstrdup(ret);
00032 
00033     return ret;
00034 }
00035 
00036 /*
00037  * convert from database encoding to utf8
00038  *
00039  * Returns a palloc'ed copy of the original string
00040  */
00041 static inline char *
00042 utf_e2u(const char *str)
00043 {
00044     char       *ret =
00045         (char *) pg_do_encoding_conversion((unsigned char *) str, strlen(str),
00046                                            GetDatabaseEncoding(), PG_UTF8);
00047 
00048     if (ret == str)
00049         ret = pstrdup(ret);
00050     return ret;
00051 }
00052 
00053 
00054 /*
00055  * Convert an SV to a char * in the current database encoding
00056  *
00057  * Returns a palloc'ed copy of the original string
00058  */
00059 static inline char *
00060 sv2cstr(SV *sv)
00061 {
00062     char       *val,
00063                *res;
00064     STRLEN      len;
00065 
00066     /*
00067      * get a utf8 encoded char * out of perl. *note* it may not be valid utf8!
00068      */
00069 
00070     /*
00071      * SvPVutf8() croaks nastily on certain things, like typeglobs and
00072      * readonly objects such as $^V. That's a perl bug - it's not supposed to
00073      * happen. To avoid crashing the backend, we make a copy of the sv before
00074      * passing it to SvPVutf8(). The copy is garbage collected when we're done
00075      * with it.
00076      */
00077     if (SvREADONLY(sv) ||
00078         isGV_with_GP(sv) ||
00079         (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM))
00080         sv = newSVsv(sv);
00081     else
00082     {
00083         /*
00084          * increase the reference count so we can just SvREFCNT_dec() it when
00085          * we are done
00086          */
00087         SvREFCNT_inc_simple_void(sv);
00088     }
00089 
00090     /*
00091      * Request the string from Perl, in UTF-8 encoding; but if we're in a
00092      * SQL_ASCII database, just request the byte soup without trying to make it
00093      * UTF8, because that might fail.
00094      */
00095     if (GetDatabaseEncoding() == PG_SQL_ASCII)
00096         val = SvPV(sv, len);
00097     else
00098         val = SvPVutf8(sv, len);
00099 
00100     /*
00101      * Now convert to database encoding.  We use perl's length in the event we
00102      * had an embedded null byte to ensure we error out properly.
00103      */
00104     res = utf_u2e(val, len);
00105 
00106     /* safe now to garbage collect the new SV */
00107     SvREFCNT_dec(sv);
00108 
00109     return res;
00110 }
00111 
00112 /*
00113  * Create a new SV from a string assumed to be in the current database's
00114  * encoding.
00115  */
00116 static inline SV *
00117 cstr2sv(const char *str)
00118 {
00119     SV         *sv;
00120     char       *utf8_str;
00121 
00122     /* no conversion when SQL_ASCII */
00123     if (GetDatabaseEncoding() == PG_SQL_ASCII)
00124         return newSVpv(str, 0);
00125 
00126     utf8_str = utf_e2u(str);
00127 
00128     sv = newSVpv(utf8_str, 0);
00129     SvUTF8_on(sv);
00130     pfree(utf8_str);
00131 
00132     return sv;
00133 }
00134 
00135 #endif   /* PL_PERL_HELPERS_H */