// Transform strings (or substrings) prefixed with introducer (_charset) to ASCII equivalent. void Parser::transformString(const char* start, unsigned length, string& dest) { const static char HEX_DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; const unsigned fromBegin = start - lex.start; HalfStaticArray<char, 256> buffer; const char* pos = start; // We need only the "introduced" strings, in the bounds of "start" and "length" and in "pos" // order. Let collect them. SortedArray<StrMark> introducedMarks; GenericMap<NonPooled<IntlString*, StrMark> >::ConstAccessor accessor(&strMarks); for (bool found = accessor.getFirst(); found; found = accessor.getNext()) { const StrMark& mark = accessor.current()->second; if (mark.introduced && mark.pos >= fromBegin && mark.pos < fromBegin + length) introducedMarks.add(mark); } for (size_t i = 0; i < introducedMarks.getCount(); ++i) { const StrMark& mark = introducedMarks[i]; const char* s = lex.start + mark.pos; buffer.add(pos, s - pos); if (!isspace(UCHAR(pos[s - pos - 1]))) buffer.add(' '); // fix _charset'' becoming invalid syntax _charsetX'' const size_t count = buffer.getCount(); const size_t newSize = count + 2 + mark.str->getString().length() * 2 + 1; buffer.grow(newSize); char* p = buffer.begin() + count; *p++ = 'X'; *p++ = '\''; const char* s2 = mark.str->getString().c_str(); for (const char* end = s2 + mark.str->getString().length(); s2 < end; ++s2) { *p++ = HEX_DIGITS[UCHAR(*s2) >> 4]; *p++ = HEX_DIGITS[UCHAR(*s2) & 0xF]; } *p = '\''; fb_assert(p < buffer.begin() + newSize); pos = s + mark.length; } fb_assert(start + length - pos >= 0); buffer.add(pos, start + length - pos); dest.assign(buffer.begin(), MIN(string::max_length(), buffer.getCount())); }
void releaseUpgradeTabs(IPluginModule* module) { HalfStaticArray<UpgradeKey, 16> removeList; WriteLockGuard sync(mapLock, FB_FUNCTION); GenericMap<FunctionPair>::Accessor scan(&functionMap); if (scan.getFirst()) { do { UpgradeKey& cur(scan.current()->first); if (cur.contains(module)) removeList.add(cur); } while (scan.getNext()); } for(unsigned int i = 0; i < removeList.getCount(); ++i) functionMap->remove(removeList[i]); }
int INTL_compare(thread_db* tdbb, const dsc* pText1, const dsc* pText2, ErrorFunction err) { /************************************** * * I N T L _ c o m p a r e * ************************************** * * Functional description * Compare two pieces of international text. * **************************************/ SET_TDBB(tdbb); fb_assert(pText1 != NULL); fb_assert(pText2 != NULL); fb_assert(IS_TEXT(pText1) && IS_TEXT(pText2)); fb_assert(INTL_data_or_binary(pText1) || INTL_data_or_binary(pText2)); fb_assert(err); // normal compare routine from CVT_compare // trailing spaces in strings are ignored for comparision UCHAR* p1; USHORT t1; ULONG length1 = CVT_get_string_ptr(pText1, &t1, &p1, NULL, 0, err); UCHAR* p2; USHORT t2; ULONG length2 = CVT_get_string_ptr(pText2, &t2, &p2, NULL, 0, err); // YYY - by SQL II compare_type must be explicit in the // SQL statement if there is any doubt USHORT compare_type = MAX(t1, t2); // YYY HalfStaticArray<UCHAR, BUFFER_XLARGE> buffer; if (t1 != t2) { CHARSET_ID cs1 = INTL_charset(tdbb, t1); CHARSET_ID cs2 = INTL_charset(tdbb, t2); if (cs1 != cs2) { if (compare_type != t2) { // convert pText2 to pText1's type, if possible /* YYY - should failure to convert really return an error here? Support joining a 437 & Latin1 Column, and we pick the compare_type as 437, still only want the equal values.... But then, what about < operations, which make no sense if the string cannot be expressed... */ UCHAR* p = buffer.getBuffer(INTL_convert_bytes(tdbb, cs1, NULL, 0, cs2, p2, length2, err)); length2 = INTL_convert_bytes(tdbb, cs1, p, (ULONG) buffer.getCount(), cs2, p2, length2, err); p2 = p; } else { // convert pText1 to pText2's type, if possible UCHAR* p = buffer.getBuffer(INTL_convert_bytes(tdbb, cs2, NULL, 0, cs1, p1, length1, err)); length1 = INTL_convert_bytes(tdbb, cs2, p, (ULONG) buffer.getCount(), cs1, p1, length1, err); p1 = p; } } } TextType* obj = INTL_texttype_lookup(tdbb, compare_type); return obj->compare(length1, p1, length2, p2); }