| @ -0,0 +1,222 @@ | |||||
| /***************************************************************************** | |||||
| * strings.h: ETSI EN 300 468 Strings | |||||
| ***************************************************************************** | |||||
| * Copyright (C) 2009-2010 VideoLAN | |||||
| * | |||||
| * Authors: Christophe Massiot <massiot@via.ecp.fr> | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining | |||||
| * a copy of this software and associated documentation files (the | |||||
| * "Software"), to deal in the Software without restriction, including | |||||
| * without limitation the rights to use, copy, modify, merge, publish, | |||||
| * distribute, sublicense, and/or sell copies of the Software, and to | |||||
| * permit persons to whom the Software is furnished to do so, subject | |||||
| * to the following conditions: | |||||
| * | |||||
| * The above copyright notice and this permission notice shall be | |||||
| * included in all copies or substantial portions of the Software. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||||
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||||
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||||
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||||
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
| *****************************************************************************/ | |||||
| /* | |||||
| * Normative references: | |||||
| * - ETSI EN 300 468 V1.11.1 (2010-04) (SI in DVB systems) | |||||
| */ | |||||
| #ifndef __BITSTREAM_DVB_STRINGS_H__ | |||||
| #define __BITSTREAM_DVB_STRINGS_H__ | |||||
| #include <stdlib.h> /* malloc, free */ | |||||
| #include <bitstream/common.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" | |||||
| { | |||||
| #endif | |||||
| /***************************************************************************** | |||||
| * DVB string | |||||
| *****************************************************************************/ | |||||
| static const char *ppsz_dvb_encodings[] = { | |||||
| /* 0x00 - 0x0f */ | |||||
| "", "ISO_8859-5", "ISO_8859-6", "ISO_8859-7", "ISO_8859-8", | |||||
| "ISO_8859-9", "ISO_8859-10", "ISO_8859-11", "", "ISO_8859-13", | |||||
| "ISO_8859-14", "ISO_8859-15", "", "", "", "", | |||||
| /* 0x10 - 0x1f */ | |||||
| "", "UTF-16", "KSC5601-1987", "GB2312", "BIG-5", "UTF-8", | |||||
| "", "", "", "", "", "", "", "", "", "", NULL | |||||
| }; | |||||
| static const char *ppsz_dvb_encodings10[] = { | |||||
| "", "ISO_8859-1", "ISO_8859-2", "ISO_8859-3", "ISO_8859-4", | |||||
| "ISO_8859-5", "ISO_8859-6", "ISO_8859-7", "ISO_8859-8", "ISO_8859-9", | |||||
| "ISO_8859-10", "ISO_8859-11", "", "ISO_8859-13", "ISO_8859-14", | |||||
| "ISO_8859-15", NULL | |||||
| }; | |||||
| static inline const char *dvb_string_get_encoding(const uint8_t **pp_string, | |||||
| size_t *pi_length) | |||||
| { | |||||
| uint8_t i_first; | |||||
| if (!*pi_length) return NULL; | |||||
| i_first = (*pp_string)[0]; | |||||
| if (!i_first) return NULL; | |||||
| if (i_first >= 0x20) return "ISO_8859-1"; | |||||
| (*pp_string)++; | |||||
| (*pi_length)--; | |||||
| if (i_first == 0x10 && *pi_length >= 2) { | |||||
| uint8_t i_second = (*pp_string)[0]; | |||||
| uint8_t i_third = (*pp_string)[1]; | |||||
| (*pp_string) += 2; | |||||
| (*pi_length) -= 2; | |||||
| if (i_second != 0x0 || i_third == 0 || i_third >= 0x10) | |||||
| return NULL; | |||||
| return ppsz_dvb_encodings10[i_third]; | |||||
| } | |||||
| if (i_first == 0x1f && *pi_length >= 1) { | |||||
| /* no info on these encodings, skip */ | |||||
| (*pp_string)++; | |||||
| (*pi_length)--; | |||||
| return NULL; | |||||
| } | |||||
| return ppsz_dvb_encodings[i_first]; | |||||
| } | |||||
| static inline uint8_t *dvb_string_set(const uint8_t *p_string, size_t i_length, | |||||
| const char *psz_encoding, | |||||
| size_t *pi_out_length) | |||||
| { | |||||
| int i; | |||||
| if (!strcmp(psz_encoding, "ISO_8859-9")) { | |||||
| *pi_out_length = i_length; | |||||
| return (uint8_t *)strdup((const char *)p_string); | |||||
| } | |||||
| for (i = 0; ppsz_dvb_encodings[i] != NULL; i++) { | |||||
| if (!strcasecmp(psz_encoding, ppsz_dvb_encodings[i])) { | |||||
| uint8_t *p_encoded = malloc(i_length + 1); | |||||
| *pi_out_length = i_length + 1; | |||||
| p_encoded[0] = i; | |||||
| memcpy(p_encoded + 1, p_string, i_length); | |||||
| return p_encoded; | |||||
| } | |||||
| } | |||||
| for (i = 0; ppsz_dvb_encodings10[i] != NULL; i++) { | |||||
| if (!strcasecmp(psz_encoding, ppsz_dvb_encodings10[i])) { | |||||
| uint8_t *p_encoded = malloc(i_length + 3); | |||||
| *pi_out_length = i_length + 3; | |||||
| p_encoded[0] = 0x10; | |||||
| p_encoded[1] = 0x0; | |||||
| p_encoded[2] = i; | |||||
| memcpy(p_encoded + 3, p_string, i_length); | |||||
| return p_encoded; | |||||
| } | |||||
| } | |||||
| *pi_out_length = 0; | |||||
| return NULL; | |||||
| } | |||||
| /* simpler API because this one doesn't output to multibyte charsets */ | |||||
| static inline char *dvb_string_get(const uint8_t *p_string, size_t i_length, | |||||
| f_iconv pf_iconv, void *iconv_opaque) | |||||
| { | |||||
| if (i_length) { | |||||
| const char *psz_encoding = dvb_string_get_encoding(&p_string, | |||||
| &i_length); | |||||
| if (psz_encoding == NULL || !i_length) { | |||||
| /* try one-byte charset */ | |||||
| char *psz_string = malloc(i_length + 1); | |||||
| memcpy(psz_string, p_string, i_length); | |||||
| psz_string[i_length] = '\0'; | |||||
| return psz_string; | |||||
| } | |||||
| return pf_iconv(iconv_opaque, psz_encoding, | |||||
| (char *)p_string, i_length); | |||||
| } | |||||
| return strdup(""); | |||||
| } | |||||
| static inline char *dvb_string_xml_escape(char *psz_input) | |||||
| { | |||||
| char *psz_output, *psz2; | |||||
| char *psz1 = psz_input; | |||||
| size_t i_output_size = 0; | |||||
| while (*psz1) { | |||||
| switch (*psz1) { | |||||
| case '<': | |||||
| case '>': | |||||
| i_output_size += strlen("<"); | |||||
| break; | |||||
| case '&': | |||||
| i_output_size += strlen("&"); | |||||
| break; | |||||
| case '"': | |||||
| case '\'': | |||||
| i_output_size += strlen("""); | |||||
| break; | |||||
| default: | |||||
| i_output_size++; | |||||
| } | |||||
| psz1++; | |||||
| } | |||||
| psz2 = psz_output = malloc(i_output_size + 1); | |||||
| psz1 = psz_input; | |||||
| while (*psz1) { | |||||
| switch (*psz1) { | |||||
| case '<': | |||||
| memcpy(psz2, "<", strlen("<")); | |||||
| psz2 += strlen("<"); | |||||
| break; | |||||
| case '>': | |||||
| memcpy(psz2, ">", strlen(">")); | |||||
| psz2 += strlen(">"); | |||||
| break; | |||||
| case '&': | |||||
| memcpy(psz2, "&", strlen("&")); | |||||
| psz2 += strlen("&"); | |||||
| break; | |||||
| case '"': | |||||
| memcpy(psz2, """, strlen(""")); | |||||
| psz2 += strlen("""); | |||||
| break; | |||||
| case '\'': | |||||
| memcpy(psz2, "'", strlen("'")); | |||||
| psz2 += strlen("'"); | |||||
| break; | |||||
| default: | |||||
| *psz2++ = *psz1; | |||||
| } | |||||
| psz1++; | |||||
| } | |||||
| *psz2 = '\0'; | |||||
| free(psz_input); | |||||
| return psz_output; | |||||
| } | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| #endif | |||||