#ifndef PL_PERL_HELPERS_H #define PL_PERL_HELPERS_H /* * convert from utf8 to database encoding * * Returns a palloc'ed copy of the original string */ static inline char * utf_u2e(char *utf8_str, size_t len) { char *ret; ret = pg_any_to_server(utf8_str, len, PG_UTF8); /* ensure we have a copy even if no conversion happened */ if (ret == utf8_str) ret = pstrdup(ret); return ret; } /* * convert from database encoding to utf8 * * Returns a palloc'ed copy of the original string */ static inline char * utf_e2u(const char *str) { char *ret; ret = pg_server_to_any(str, strlen(str), PG_UTF8); /* ensure we have a copy even if no conversion happened */ if (ret == str) ret = pstrdup(ret); return ret; } /* * Convert an SV to a char * in the current database encoding * * Returns a palloc'ed copy of the original string */ static inline char * sv2cstr(SV *sv) { char *val, *res; STRLEN len; /* * get a utf8 encoded char * out of perl. *note* it may not be valid utf8! */ /* * SvPVutf8() croaks nastily on certain things, like typeglobs and * readonly objects such as $^V. That's a perl bug - it's not supposed to * happen. To avoid crashing the backend, we make a copy of the sv before * passing it to SvPVutf8(). The copy is garbage collected when we're done * with it. */ if (SvREADONLY(sv) || isGV_with_GP(sv) || (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM)) sv = newSVsv(sv); else { /* * increase the reference count so we can just SvREFCNT_dec() it when * we are done */ SvREFCNT_inc_simple_void(sv); } /* * Request the string from Perl, in UTF-8 encoding; but if we're in a * SQL_ASCII database, just request the byte soup without trying to make * it UTF8, because that might fail. */ if (GetDatabaseEncoding() == PG_SQL_ASCII) val = SvPV(sv, len); else val = SvPVutf8(sv, len); /* * Now convert to database encoding. We use perl's length in the event we * had an embedded null byte to ensure we error out properly. */ res = utf_u2e(val, len); /* safe now to garbage collect the new SV */ SvREFCNT_dec(sv); return res; } /* * Create a new SV from a string assumed to be in the current database's * encoding. */ static inline SV * cstr2sv(const char *str) { SV *sv; char *utf8_str; /* no conversion when SQL_ASCII */ if (GetDatabaseEncoding() == PG_SQL_ASCII) return newSVpv(str, 0); utf8_str = utf_e2u(str); sv = newSVpv(utf8_str, 0); SvUTF8_on(sv); pfree(utf8_str); return sv; } #endif /* PL_PERL_HELPERS_H */