void EXE_send(thread_db* tdbb, jrd_req* request, USHORT msg, ULONG length, const UCHAR* buffer) { /************************************** * * E X E _ s e n d * ************************************** * * Functional description * Send a message from the host program to the engine. * This corresponds to a blr_receive or blr_select statement. * **************************************/ SET_TDBB(tdbb); DEV_BLKCHK(request, type_req); if (--tdbb->tdbb_quantum < 0) JRD_reschedule(tdbb, 0, true); if (!(request->req_flags & req_active)) ERR_post(Arg::Gds(isc_req_sync)); const StmtNode* message = NULL; const StmtNode* node; if (request->req_operation != jrd_req::req_receive) ERR_post(Arg::Gds(isc_req_sync)); node = request->req_message; jrd_tra* transaction = request->req_transaction; const JrdStatement* statement = request->getStatement(); const SelectNode* selectNode; if (StmtNode::is<MessageNode>(node)) message = node; else if ((selectNode = StmtNode::as<SelectNode>(node))) { const NestConst<StmtNode>* ptr = selectNode->statements.begin(); for (const NestConst<StmtNode>* end = selectNode->statements.end(); ptr != end; ++ptr) { const ReceiveNode* receiveNode = (*ptr)->as<ReceiveNode>(); message = receiveNode->message; if (message->as<MessageNode>()->messageNumber == msg) { request->req_next = *ptr; break; } } } else BUGCHECK(167); // msg 167 invalid SEND request const Format* format = StmtNode::as<MessageNode>(message)->format; if (msg != StmtNode::as<MessageNode>(message)->messageNumber) ERR_post(Arg::Gds(isc_req_sync)); if (length != format->fmt_length) ERR_post(Arg::Gds(isc_port_len) << Arg::Num(length) << Arg::Num(format->fmt_length)); memcpy(request->getImpure<UCHAR>(message->impureOffset), buffer, length); for (USHORT i = 0; i < format->fmt_count; ++i) { const DSC* desc = &format->fmt_desc[i]; // ASF: I'll not test for dtype_cstring because usage is only internal if (desc->dsc_dtype == dtype_text || desc->dsc_dtype == dtype_varying) { const UCHAR* p = request->getImpure<UCHAR>(message->impureOffset + (ULONG)(IPTR) desc->dsc_address); USHORT len; switch (desc->dsc_dtype) { case dtype_text: len = desc->dsc_length; break; case dtype_varying: len = reinterpret_cast<const vary*>(p)->vary_length; p += sizeof(USHORT); break; } CharSet* charSet = INTL_charset_lookup(tdbb, DSC_GET_CHARSET(desc)); if (!charSet->wellFormed(len, p)) ERR_post(Arg::Gds(isc_malformed_string)); } else if (desc->isBlob()) { if (desc->getCharSet() != CS_NONE && desc->getCharSet() != CS_BINARY) { const Jrd::bid* bid = request->getImpure<Jrd::bid>( message->impureOffset + (ULONG)(IPTR) desc->dsc_address); if (!bid->isEmpty()) { AutoBlb blob(tdbb, blb::open(tdbb, transaction/*tdbb->getTransaction()*/, bid)); blob.getBlb()->BLB_check_well_formed(tdbb, desc); } } } } execute_looper(tdbb, request, transaction, request->req_next, jrd_req::req_proceed); }
ULONG INTL_convert_bytes(thread_db* tdbb, CHARSET_ID dest_type, BYTE* dest_ptr, const ULONG dest_len, CHARSET_ID src_type, const BYTE* src_ptr, const ULONG src_len, ErrorFunction err) { /************************************** * * I N T L _ c o n v e r t _ b y t e s * ************************************** * * Functional description * Given a string of bytes in one character set, convert it to another * character set. * * If (dest_ptr) is NULL, return the count of bytes needed to convert * the string. This does not guarantee the string can be converted, * the purpose of this is to allocate a large enough buffer. * * RETURNS: * Length of resulting string, in bytes. * calls (err) if conversion error occurs. * **************************************/ SET_TDBB(tdbb); fb_assert(src_ptr != NULL); fb_assert(src_type != dest_type); fb_assert(err != NULL); dest_type = INTL_charset(tdbb, dest_type); src_type = INTL_charset(tdbb, src_type); const UCHAR* const start_dest_ptr = dest_ptr; if (dest_type == CS_BINARY || dest_type == CS_NONE || src_type == CS_BINARY || src_type == CS_NONE) { // See if we just need a length estimate if (dest_ptr == NULL) return (src_len); if (dest_type != CS_BINARY && dest_type != CS_NONE) { CharSet* toCharSet = INTL_charset_lookup(tdbb, dest_type); if (!toCharSet->wellFormed(src_len, src_ptr)) err(Arg::Gds(isc_malformed_string)); } ULONG len = MIN(dest_len, src_len); if (len) { do { *dest_ptr++ = *src_ptr++; } while (--len); } // See if only space characters are remaining len = src_len - MIN(dest_len, src_len); if (len == 0 || allSpaces(INTL_charset_lookup(tdbb, src_type), src_ptr, len, 0)) return dest_ptr - start_dest_ptr; err(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) << Arg::Gds(isc_trunc_limits) << Arg::Num(dest_len) << Arg::Num(src_len)); } else if (src_len) { // character sets are known to be different // Do we know an object from cs1 to cs2? CsConvert cs_obj = INTL_convert_lookup(tdbb, dest_type, src_type); return cs_obj.convert(src_len, src_ptr, dest_len, dest_ptr, NULL, true); } return 0; }