00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017
00018 #include <drizzled/charset.h>
00019 #include <drizzled/error.h>
00020 #include <drizzled/internal/m_string.h>
00021 #include <drizzled/configmake.h>
00022 #include <vector>
00023
00024 #include <drizzled/visibility.h>
00025
00026 using namespace std;
00027
00028 namespace drizzled {
00029
00030
00031
00032
00033 static vector<unsigned char*> memory_vector;
00034
00035 extern charset_info_st my_charset_utf8mb4_icelandic_uca_ci;
00036 extern charset_info_st my_charset_utf8mb4_latvian_uca_ci;
00037 extern charset_info_st my_charset_utf8mb4_romanian_uca_ci;
00038 extern charset_info_st my_charset_utf8mb4_slovenian_uca_ci;
00039 extern charset_info_st my_charset_utf8mb4_polish_uca_ci;
00040 extern charset_info_st my_charset_utf8mb4_estonian_uca_ci;
00041 extern charset_info_st my_charset_utf8mb4_spanish_uca_ci;
00042 extern charset_info_st my_charset_utf8mb4_swedish_uca_ci;
00043 extern charset_info_st my_charset_utf8mb4_turkish_uca_ci;
00044 extern charset_info_st my_charset_utf8mb4_czech_uca_ci;
00045 extern charset_info_st my_charset_utf8mb4_danish_uca_ci;
00046 extern charset_info_st my_charset_utf8mb4_lithuanian_uca_ci;
00047 extern charset_info_st my_charset_utf8mb4_slovak_uca_ci;
00048 extern charset_info_st my_charset_utf8mb4_spanish2_uca_ci;
00049 extern charset_info_st my_charset_utf8mb4_roman_uca_ci;
00050 extern charset_info_st my_charset_utf8mb4_persian_uca_ci;
00051 extern charset_info_st my_charset_utf8mb4_esperanto_uca_ci;
00052 extern charset_info_st my_charset_utf8mb4_hungarian_uca_ci;
00053 extern charset_info_st my_charset_utf8mb4_sinhala_uca_ci;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 bool my_charset_same(const charset_info_st *cs1, const charset_info_st *cs2)
00066 {
00067 return cs1 == cs2 || not strcmp(cs1->csname, cs2->csname);
00068 }
00069
00070 static uint get_collation_number_internal(const char *name)
00071 {
00072 for (charset_info_st **cs= all_charsets; cs < all_charsets + array_elements(all_charsets) - 1; cs++)
00073 {
00074 if (cs[0] && cs[0]->name && not my_charset_utf8_general_ci.strcasecmp(cs[0]->name, name))
00075 {
00076 return cs[0]->number;
00077 }
00078 }
00079 return 0;
00080 }
00081
00082 static unsigned char* cs_alloc(size_t size)
00083 {
00084 memory_vector.push_back(new unsigned char[size]);
00085 return memory_vector.back();
00086 }
00087
00088 static void init_state_maps(charset_info_st *cs)
00089 {
00090 cs->state_map= cs_alloc(256);
00091 cs->ident_map= cs_alloc(256);
00092
00093 unsigned char *state_map= cs->state_map;
00094 unsigned char *ident_map= cs->ident_map;
00095
00096
00097 for (int i= 0; i < 256; i++)
00098 {
00099 if (cs->isalpha(i))
00100 state_map[i]= MY_LEX_IDENT;
00101 else if (cs->isdigit(i))
00102 state_map[i]= MY_LEX_NUMBER_IDENT;
00103 else if (my_mbcharlen(cs, i) > 1)
00104 state_map[i]= MY_LEX_IDENT;
00105 else if (cs->isspace(i))
00106 state_map[i]= MY_LEX_SKIP;
00107 else
00108 state_map[i]= MY_LEX_CHAR;
00109 }
00110 state_map['_']=state_map['$']= MY_LEX_IDENT;
00111 state_map['\'']= MY_LEX_STRING;
00112 state_map['.']= MY_LEX_REAL_OR_POINT;
00113 state_map['>']=state_map['=']=state_map['!']= MY_LEX_CMP_OP;
00114 state_map['<']= MY_LEX_LONG_CMP_OP;
00115 state_map['&']=state_map['|']= MY_LEX_BOOL;
00116 state_map['#']= MY_LEX_COMMENT;
00117 state_map[';']= MY_LEX_SEMICOLON;
00118 state_map[':']= MY_LEX_SET_VAR;
00119 state_map[0]= MY_LEX_EOL;
00120 state_map['\\']= MY_LEX_ESCAPE;
00121 state_map['/']= MY_LEX_LONG_COMMENT;
00122 state_map['*']= MY_LEX_END_LONG_COMMENT;
00123 state_map['@']= MY_LEX_USER_END;
00124 state_map['`']= MY_LEX_USER_VARIABLE_DELIMITER;
00125 state_map['"']= MY_LEX_STRING_OR_DELIMITER;
00126
00127
00128
00129
00130 for (int i= 0; i < 256; i++)
00131 {
00132 ident_map[i]= state_map[i] == MY_LEX_IDENT || state_map[i] == MY_LEX_NUMBER_IDENT;
00133 }
00134
00135
00136 state_map['x']= state_map['X']= MY_LEX_IDENT_OR_HEX;
00137 state_map['b']= state_map['B']= MY_LEX_IDENT_OR_BIN;
00138 }
00139
00140 static bool charset_initialized= false;
00141
00142 DRIZZLED_API charset_info_st *all_charsets[256];
00143 const DRIZZLED_API charset_info_st *default_charset_info = &my_charset_utf8_general_ci;
00144
00145 static void add_compiled_collation(charset_info_st * cs)
00146 {
00147 all_charsets[cs->number]= cs;
00148 cs->state|= MY_CS_AVAILABLE;
00149 }
00150
00151 static void init_compiled_charsets()
00152 {
00153 add_compiled_collation(&my_charset_bin);
00154
00155 add_compiled_collation(&my_charset_utf8mb4_general_ci);
00156 add_compiled_collation(&my_charset_utf8mb4_bin);
00157 add_compiled_collation(&my_charset_utf8mb4_unicode_ci);
00158 add_compiled_collation(&my_charset_utf8mb4_icelandic_uca_ci);
00159 add_compiled_collation(&my_charset_utf8mb4_latvian_uca_ci);
00160 add_compiled_collation(&my_charset_utf8mb4_romanian_uca_ci);
00161 add_compiled_collation(&my_charset_utf8mb4_slovenian_uca_ci);
00162 add_compiled_collation(&my_charset_utf8mb4_polish_uca_ci);
00163 add_compiled_collation(&my_charset_utf8mb4_estonian_uca_ci);
00164 add_compiled_collation(&my_charset_utf8mb4_spanish_uca_ci);
00165 add_compiled_collation(&my_charset_utf8mb4_swedish_uca_ci);
00166 add_compiled_collation(&my_charset_utf8mb4_turkish_uca_ci);
00167 add_compiled_collation(&my_charset_utf8mb4_czech_uca_ci);
00168 add_compiled_collation(&my_charset_utf8mb4_danish_uca_ci);
00169 add_compiled_collation(&my_charset_utf8mb4_lithuanian_uca_ci);
00170 add_compiled_collation(&my_charset_utf8mb4_slovak_uca_ci);
00171 add_compiled_collation(&my_charset_utf8mb4_spanish2_uca_ci);
00172 add_compiled_collation(&my_charset_utf8mb4_roman_uca_ci);
00173 add_compiled_collation(&my_charset_utf8mb4_persian_uca_ci);
00174 add_compiled_collation(&my_charset_utf8mb4_esperanto_uca_ci);
00175 add_compiled_collation(&my_charset_utf8mb4_hungarian_uca_ci);
00176 add_compiled_collation(&my_charset_utf8mb4_sinhala_uca_ci);
00177 }
00178
00179 static void init_available_charsets()
00180 {
00181
00182
00183
00184
00185 if (charset_initialized)
00186 return;
00187 memset(&all_charsets, 0, sizeof(all_charsets));
00188 init_compiled_charsets();
00189
00190
00191 for (charset_info_st**cs= all_charsets;
00192 cs < all_charsets+array_elements(all_charsets)-1;
00193 cs++)
00194 {
00195 if (*cs && cs[0]->ctype)
00196 init_state_maps(*cs);
00197 }
00198
00199 charset_initialized= true;
00200 }
00201
00202 void free_charsets()
00203 {
00204 charset_initialized= false;
00205
00206 while (not memory_vector.empty())
00207 {
00208 delete[] memory_vector.back();
00209 memory_vector.pop_back();
00210 }
00211 }
00212
00213 uint32_t get_collation_number(const char *name)
00214 {
00215 init_available_charsets();
00216 return get_collation_number_internal(name);
00217 }
00218
00219 uint32_t get_charset_number(const char *charset_name, uint32_t cs_flags)
00220 {
00221 init_available_charsets();
00222
00223 for (charset_info_st** cs= all_charsets; cs < all_charsets + array_elements(all_charsets) - 1; cs++)
00224 {
00225 if (cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && not my_charset_utf8_general_ci.strcasecmp(cs[0]->csname, charset_name))
00226 return cs[0]->number;
00227 }
00228 return 0;
00229 }
00230
00231 const char *get_charset_name(uint32_t charset_number)
00232 {
00233 init_available_charsets();
00234 const charset_info_st* cs= all_charsets[charset_number];
00235 return cs && cs->number == charset_number && cs->name ? cs->name : "?";
00236 }
00237
00238 static const charset_info_st *get_internal_charset(uint32_t cs_number)
00239 {
00240 charset_info_st* cs= all_charsets[cs_number];
00241
00242
00243
00244
00245 if (not cs)
00246 return NULL;
00247 assert(not (not (cs->state & MY_CS_COMPILED) && not (cs->state & MY_CS_LOADED)));
00248 if (not (cs->state & MY_CS_AVAILABLE))
00249 return NULL;
00250 if (not (cs->state & MY_CS_READY))
00251 {
00252 if (cs->coll->init && cs->coll->init(*cs, cs_alloc))
00253 return NULL;
00254 cs->state|= MY_CS_READY;
00255 }
00256 return cs;
00257 }
00258
00259 const charset_info_st *get_charset(uint32_t cs_number)
00260 {
00261 if (cs_number == default_charset_info->number)
00262 return default_charset_info;
00263
00264 init_available_charsets();
00265
00266 if (!cs_number || cs_number >= array_elements(all_charsets)-1)
00267 return NULL;
00268
00269 return get_internal_charset(cs_number);
00270 }
00271
00272 const charset_info_st *get_charset_by_name(const char *cs_name)
00273 {
00274 init_available_charsets();
00275 uint32_t cs_number= get_collation_number(cs_name);
00276 return cs_number ? get_internal_charset(cs_number) : NULL;
00277 }
00278
00279 const charset_info_st *get_charset_by_csname(const char *cs_name, uint32_t cs_flags)
00280 {
00281 init_available_charsets();
00282 uint32_t cs_number= get_charset_number(cs_name, cs_flags);
00283 return cs_number ? get_internal_charset(cs_number) : NULL;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 size_t escape_quotes_for_drizzle(const charset_info_st *charset_info,
00313 char *to, size_t to_length,
00314 const char *from, size_t length)
00315 {
00316 const char *to_start= to;
00317 const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
00318 bool overflow= false;
00319 bool use_mb_flag= use_mb(charset_info);
00320 for (end= from + length; from < end; from++)
00321 {
00322 int tmp_length;
00323 if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
00324 {
00325 if (to + tmp_length > to_end)
00326 {
00327 overflow= true;
00328 break;
00329 }
00330 while (tmp_length--)
00331 *to++= *from++;
00332 from--;
00333 continue;
00334 }
00335
00336
00337
00338
00339
00340 if (*from == '\'')
00341 {
00342 if (to + 2 > to_end)
00343 {
00344 overflow= true;
00345 break;
00346 }
00347 *to++= '\'';
00348 *to++= '\'';
00349 }
00350 else
00351 {
00352 if (to + 1 > to_end)
00353 {
00354 overflow= true;
00355 break;
00356 }
00357 *to++= *from;
00358 }
00359 }
00360 *to= 0;
00361 return overflow ? UINT32_MAX : to - to_start;
00362 }
00363
00364 }