mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-26 08:03:03 +01:00
ed17cfafbf
if<space>( for<space>( switch<space>( while<space>(
696 lines
17 KiB
Plaintext
696 lines
17 KiB
Plaintext
/*
|
|
* PROGRAM: Interbase layered support library
|
|
* MODULE: array.epp
|
|
* DESCRIPTION: Dynamic array support
|
|
*
|
|
* The contents of this file are subject to the Interbase Public
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
*
|
|
* Software distributed under the License is distributed on an
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
* or implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code was created by Inprise Corporation
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
* Copyright (C) Inprise Corporation.
|
|
*
|
|
* All Rights Reserved.
|
|
* Contributor(s): ______________________________________.
|
|
*
|
|
* 2001.09.18 Claudio Valderrama: get_name() was preventing the API calls
|
|
* isc_array_lookup_bounds, isc_lookup_desc & isc_array_set_desc
|
|
* from working properly with dialect 3 names. Therefore, incorrect names
|
|
* could be returned or a lookup for a blob field could fail. In addition,
|
|
* a possible buffer overrun due to unchecked bounds was closed. The fc
|
|
* get_name() as been renamed copy_exact_name().
|
|
*
|
|
* 2002-02-24 Sean Leyne - Code Cleanup of old Win 3.1 port (WINDOWS_ONLY)
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include "firebird.h"
|
|
#include <string.h>
|
|
#include "../jrd/common.h"
|
|
#include <stdarg.h>
|
|
#include "../jrd/ibase.h"
|
|
#include "../dsql/array_proto.h"
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
DATABASE DB = STATIC FILENAME "yachts.lnk";
|
|
|
|
const int array_desc_column_major = 1; // Set for FORTRAN
|
|
|
|
struct gen_t {
|
|
UCHAR* gen_sdl;
|
|
UCHAR** gen_sdl_ptr;
|
|
UCHAR* gen_end;
|
|
ISC_STATUS* gen_status;
|
|
SSHORT gen_internal;
|
|
};
|
|
|
|
typedef gen_t *GEN_T;
|
|
|
|
static void adjust_length(ISC_ARRAY_DESC*);
|
|
static void copy_exact_name (const char*, char*, SSHORT);
|
|
static ISC_STATUS copy_status(const ISC_STATUS*, ISC_STATUS*);
|
|
static ISC_STATUS error(ISC_STATUS*, SSHORT, ...);
|
|
static ISC_STATUS gen_sdl(ISC_STATUS*, const ISC_ARRAY_DESC*, SSHORT*, UCHAR**,
|
|
SSHORT*, bool);
|
|
static ISC_STATUS lookup_desc(ISC_STATUS*, FB_API_HANDLE*, FB_API_HANDLE*, const SCHAR*,
|
|
const SCHAR*, ISC_ARRAY_DESC*, SCHAR*);
|
|
static ISC_STATUS stuff_args(gen_t*, SSHORT, ...);
|
|
static ISC_STATUS stuff_literal(gen_t*, SLONG);
|
|
static ISC_STATUS stuff_string(gen_t*, UCHAR, const SCHAR*);
|
|
|
|
// stuff_sdl used in place of STUFF to avoid confusion with BLR STUFF
|
|
// macro defined in dsql.h
|
|
|
|
static inline ISC_STATUS stuff_sdl(gen_t* gen, int byte)
|
|
{
|
|
return stuff_args(gen, 1, byte);
|
|
}
|
|
|
|
static inline ISC_STATUS stuff_sdl_word(gen_t* gen, int word)
|
|
{
|
|
return stuff_args(gen, 2, word, word >> 8);
|
|
}
|
|
|
|
static inline ISC_STATUS stuff_sdl_long(gen_t* gen, int word)
|
|
{
|
|
return stuff_args(gen, 4, word, word >> 8, word >> 16, word >> 24);
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_gen_sdl(ISC_STATUS* status,
|
|
const ISC_ARRAY_DESC* desc,
|
|
SSHORT* sdl_buffer_length,
|
|
UCHAR* sdl_buffer, SSHORT* sdl_length)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ g e n _ s d l
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
|
|
return gen_sdl(status, desc, sdl_buffer_length, &sdl_buffer, sdl_length, false);
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_get_slice(ISC_STATUS* status,
|
|
FB_API_HANDLE* db_handle,
|
|
FB_API_HANDLE* trans_handle,
|
|
ISC_QUAD* array_id,
|
|
const ISC_ARRAY_DESC* desc,
|
|
void* array,
|
|
SLONG* slice_length)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ g e t _ s l i c e
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
UCHAR sdl_buffer[512];
|
|
|
|
SSHORT sdl_length = sizeof(sdl_buffer);
|
|
UCHAR* sdl = sdl_buffer;
|
|
|
|
if (gen_sdl(status, desc, &sdl_length, &sdl, &sdl_length, true))
|
|
return status[1];
|
|
|
|
isc_get_slice(status, db_handle, trans_handle, array_id,
|
|
// SD: I do not complain but in ibase.h sdl is a plain char in functions'
|
|
// declaration while it is UCHAR in the functions' implementations. Damned legacy!
|
|
sdl_length, reinterpret_cast<const char*>(sdl),
|
|
0, NULL, *slice_length, array, slice_length);
|
|
|
|
if (sdl != sdl_buffer)
|
|
gds__free(sdl);
|
|
|
|
return status[1];
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_lookup_bounds(ISC_STATUS* status,
|
|
FB_API_HANDLE* db_handle,
|
|
FB_API_HANDLE* trans_handle,
|
|
const SCHAR* relation_name,
|
|
const SCHAR* field_name,
|
|
ISC_ARRAY_DESC* desc)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ l o o k u p _ b o u n d s
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
SCHAR global[32];
|
|
|
|
if (lookup_desc(status, db_handle, trans_handle,
|
|
field_name, relation_name, desc, global))
|
|
{
|
|
return status[1];
|
|
}
|
|
|
|
ISC_ARRAY_BOUND* tail = desc->array_desc_bounds;
|
|
|
|
FOR X IN RDB$FIELD_DIMENSIONS
|
|
WITH X.RDB$FIELD_NAME EQ global
|
|
SORTED BY X.RDB$DIMENSION
|
|
tail->array_bound_lower = (SSHORT)X.RDB$LOWER_BOUND;
|
|
tail->array_bound_upper = (SSHORT)X.RDB$UPPER_BOUND;
|
|
++tail;
|
|
END_FOR
|
|
ON_ERROR
|
|
return copy_status(gds_status, status);
|
|
END_ERROR;
|
|
|
|
return status[1];
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_lookup_desc(ISC_STATUS* status,
|
|
FB_API_HANDLE* db_handle,
|
|
FB_API_HANDLE* trans_handle,
|
|
const SCHAR* relation_name,
|
|
const SCHAR* field_name,
|
|
ISC_ARRAY_DESC* desc)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ l o o k u p _ d e s c
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
|
|
return lookup_desc(status, db_handle, trans_handle,
|
|
field_name, relation_name, desc, NULL);
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_put_slice(ISC_STATUS* status,
|
|
FB_API_HANDLE* db_handle,
|
|
FB_API_HANDLE* trans_handle,
|
|
ISC_QUAD* array_id,
|
|
const ISC_ARRAY_DESC* desc,
|
|
void* array,
|
|
SLONG* slice_length)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ p u t _ s l i c e
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
UCHAR sdl_buffer[512];
|
|
|
|
SSHORT sdl_length = sizeof(sdl_buffer);
|
|
UCHAR* sdl = sdl_buffer;
|
|
|
|
if (gen_sdl(status, desc, &sdl_length, &sdl, &sdl_length, true))
|
|
return status[1];
|
|
|
|
isc_put_slice(status, db_handle, trans_handle, array_id,
|
|
sdl_length, reinterpret_cast<const char*>(sdl),
|
|
0, NULL, *slice_length, array);
|
|
|
|
if (sdl != sdl_buffer)
|
|
gds__free(sdl);
|
|
|
|
return status[1];
|
|
}
|
|
|
|
|
|
ISC_STATUS API_ROUTINE isc_array_set_desc(ISC_STATUS* status,
|
|
const SCHAR* relation_name,
|
|
const SCHAR* field_name,
|
|
const SSHORT* sql_dtype,
|
|
const SSHORT* sql_length,
|
|
const SSHORT* dimensions,
|
|
ISC_ARRAY_DESC* desc)
|
|
{
|
|
/**************************************
|
|
*
|
|
* i s c _ a r r a y _ s e t _ d e s c
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
copy_exact_name (field_name, desc->array_desc_field_name,
|
|
sizeof(desc->array_desc_field_name));
|
|
copy_exact_name (relation_name, desc->array_desc_relation_name,
|
|
sizeof(desc->array_desc_relation_name));
|
|
|
|
|
|
desc->array_desc_flags = 0;
|
|
desc->array_desc_dimensions = *dimensions;
|
|
desc->array_desc_length = *sql_length;
|
|
desc->array_desc_scale = 0;
|
|
|
|
const SSHORT dtype = *sql_dtype & ~1;
|
|
|
|
switch (dtype) {
|
|
case SQL_VARYING:
|
|
desc->array_desc_dtype = blr_varying;
|
|
break;
|
|
case SQL_TEXT:
|
|
desc->array_desc_dtype = blr_text;
|
|
break;
|
|
case SQL_DOUBLE:
|
|
desc->array_desc_dtype = blr_double;
|
|
break;
|
|
case SQL_FLOAT:
|
|
desc->array_desc_dtype = blr_float;
|
|
break;
|
|
case SQL_D_FLOAT:
|
|
desc->array_desc_dtype = blr_d_float;
|
|
break;
|
|
case SQL_TIMESTAMP:
|
|
desc->array_desc_dtype = blr_timestamp;
|
|
break;
|
|
case SQL_TYPE_DATE:
|
|
desc->array_desc_dtype = blr_sql_date;
|
|
break;
|
|
case SQL_TYPE_TIME:
|
|
desc->array_desc_dtype = blr_sql_time;
|
|
break;
|
|
case SQL_LONG:
|
|
desc->array_desc_dtype = blr_long;
|
|
break;
|
|
case SQL_SHORT:
|
|
desc->array_desc_dtype = blr_short;
|
|
break;
|
|
case SQL_INT64:
|
|
desc->array_desc_dtype = blr_int64;
|
|
break;
|
|
case SQL_QUAD:
|
|
desc->array_desc_dtype = blr_quad;
|
|
break;
|
|
default:
|
|
return error(status, 7, (ISC_STATUS) isc_sqlerr,
|
|
(ISC_STATUS) isc_arg_number, (ISC_STATUS) - 804,
|
|
(ISC_STATUS) isc_arg_gds, (ISC_STATUS) isc_random,
|
|
(ISC_STATUS) isc_arg_string,
|
|
(ISC_STATUS) "data type not understood");
|
|
}
|
|
|
|
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
|
|
}
|
|
|
|
|
|
static void adjust_length( ISC_ARRAY_DESC* desc)
|
|
{
|
|
/**************************************
|
|
*
|
|
* a d j u s t _ l e n g t h
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Make architectural adjustment to fixed datatypes.
|
|
*
|
|
**************************************/
|
|
}
|
|
|
|
static void copy_exact_name (
|
|
const char* from,
|
|
char* to,
|
|
SSHORT bsize)
|
|
{
|
|
/**************************************
|
|
*
|
|
* c o p y _ e x a c t _ n a m e
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Copy null terminated name ot stops at bsize - 1.
|
|
* CVC: This is just another fc like DYN_terminate.
|
|
*
|
|
**************************************/
|
|
const char* const from_end = from + bsize - 1;
|
|
char* to2 = to - 1;
|
|
while (*from && from < from_end) {
|
|
if (*from != ' ') {
|
|
to2 = to;
|
|
}
|
|
*to++ = *from++;
|
|
}
|
|
*++to2 = 0;
|
|
}
|
|
|
|
|
|
static ISC_STATUS copy_status( const ISC_STATUS* from, ISC_STATUS* to)
|
|
{
|
|
/**************************************
|
|
*
|
|
* c o p y _ s t a t u s
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Copy a status vector.
|
|
*
|
|
**************************************/
|
|
const ISC_STATUS status = from[1];
|
|
|
|
const ISC_STATUS* const end = from + ISC_STATUS_LENGTH;
|
|
while (from < end)
|
|
*to++ = *from++;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
static ISC_STATUS error( ISC_STATUS* status, SSHORT count, ...)
|
|
{
|
|
/**************************************
|
|
*
|
|
* e r r o r
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Stuff a status vector.
|
|
*
|
|
**************************************/
|
|
ISC_STATUS* stat;
|
|
va_list ptr;
|
|
|
|
va_start(ptr, count);
|
|
stat = status;
|
|
*stat++ = isc_arg_gds;
|
|
|
|
for (; count; --count)
|
|
*stat++ = (ISC_STATUS) va_arg(ptr, ISC_STATUS);
|
|
|
|
va_end(ptr);
|
|
*stat = isc_arg_end;
|
|
|
|
return status[1];
|
|
}
|
|
|
|
|
|
static ISC_STATUS gen_sdl(ISC_STATUS* status,
|
|
const ISC_ARRAY_DESC* desc,
|
|
SSHORT* sdl_buffer_length,
|
|
UCHAR** sdl_buffer,
|
|
SSHORT* sdl_length,
|
|
bool internal_flag)
|
|
{
|
|
/**************************************
|
|
*
|
|
* g e n _ s d l
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
const SSHORT dimensions = desc->array_desc_dimensions;
|
|
|
|
if (dimensions > 16)
|
|
return error(status, 5, (ISC_STATUS) isc_invalid_dimension,
|
|
(ISC_STATUS) isc_arg_number, (ISC_STATUS) dimensions,
|
|
(ISC_STATUS) isc_arg_number, (ISC_STATUS) 16);
|
|
|
|
gen_t gen_block;
|
|
gen_t* gen = &gen_block;
|
|
gen->gen_sdl = *sdl_buffer;
|
|
gen->gen_sdl_ptr = sdl_buffer;
|
|
gen->gen_end = *sdl_buffer + *sdl_buffer_length;
|
|
gen->gen_status = status;
|
|
gen->gen_internal = internal_flag ? 0 : -1;
|
|
|
|
if (stuff_args(gen, 4, isc_sdl_version1, isc_sdl_struct, 1,
|
|
desc->array_desc_dtype))
|
|
{
|
|
return status[1];
|
|
}
|
|
|
|
switch (desc->array_desc_dtype) {
|
|
case blr_short:
|
|
case blr_long:
|
|
case blr_int64:
|
|
case blr_quad:
|
|
if (stuff_sdl(gen, desc->array_desc_scale))
|
|
return status[1];
|
|
break;
|
|
|
|
case blr_text:
|
|
case blr_cstring:
|
|
case blr_varying:
|
|
if (stuff_sdl_word(gen, desc->array_desc_length))
|
|
return status[1];
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (stuff_string(gen, isc_sdl_relation, desc->array_desc_relation_name))
|
|
return status[1];
|
|
|
|
if (stuff_string(gen, isc_sdl_field, desc->array_desc_field_name))
|
|
return status[1];
|
|
|
|
SSHORT from, to, increment;
|
|
if (desc->array_desc_flags & array_desc_column_major) {
|
|
from = dimensions - 1;
|
|
to = -1;
|
|
increment = -1;
|
|
}
|
|
else {
|
|
from = 0;
|
|
to = dimensions;
|
|
increment = 1;
|
|
}
|
|
|
|
SSHORT n;
|
|
for (n = from; n != to; n += increment) {
|
|
const ISC_ARRAY_BOUND* tail = desc->array_desc_bounds + n;
|
|
if (tail->array_bound_lower == 1) {
|
|
if (stuff_args(gen, 2, isc_sdl_do1, n))
|
|
return status[1];
|
|
}
|
|
else {
|
|
if (stuff_args(gen, 2, isc_sdl_do2, n))
|
|
return status[1];
|
|
if (stuff_literal(gen, (SLONG) tail->array_bound_lower))
|
|
return status[1];
|
|
}
|
|
if (stuff_literal(gen, (SLONG) tail->array_bound_upper))
|
|
return status[1];
|
|
}
|
|
|
|
if (stuff_args(gen, 5, isc_sdl_element, 1, isc_sdl_scalar, 0, dimensions))
|
|
return status[1];
|
|
|
|
for (n = 0; n < dimensions; n++)
|
|
if (stuff_args(gen, 2, isc_sdl_variable, n))
|
|
return status[1];
|
|
|
|
if (stuff_sdl(gen, isc_sdl_eoc))
|
|
return status[1];
|
|
*sdl_length = gen->gen_sdl - *gen->gen_sdl_ptr;
|
|
|
|
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
static ISC_STATUS lookup_desc(ISC_STATUS* status,
|
|
FB_API_HANDLE* db_handle,
|
|
FB_API_HANDLE* trans_handle,
|
|
const SCHAR* field_name,
|
|
const SCHAR* relation_name,
|
|
ISC_ARRAY_DESC* desc,
|
|
SCHAR* global)
|
|
{
|
|
/**************************************
|
|
*
|
|
* l o o k u p _ d e s c
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
if (DB && DB != *db_handle)
|
|
RELEASE_REQUESTS;
|
|
|
|
DB = *db_handle;
|
|
gds_trans = *trans_handle;
|
|
|
|
copy_exact_name (field_name, desc->array_desc_field_name,
|
|
sizeof(desc->array_desc_field_name));
|
|
copy_exact_name (relation_name, desc->array_desc_relation_name,
|
|
sizeof(desc->array_desc_relation_name));
|
|
|
|
|
|
desc->array_desc_flags = 0;
|
|
|
|
bool flag = false;
|
|
|
|
FOR X IN RDB$RELATION_FIELDS CROSS Y IN RDB$FIELDS
|
|
WITH X.RDB$FIELD_SOURCE EQ Y.RDB$FIELD_NAME AND
|
|
X.RDB$RELATION_NAME EQ desc->array_desc_relation_name AND
|
|
X.RDB$FIELD_NAME EQ desc->array_desc_field_name
|
|
flag = true;
|
|
desc->array_desc_dtype = (UCHAR)Y.RDB$FIELD_TYPE;
|
|
desc->array_desc_scale = (SCHAR)Y.RDB$FIELD_SCALE;
|
|
desc->array_desc_length = Y.RDB$FIELD_LENGTH;
|
|
adjust_length(desc);
|
|
desc->array_desc_dimensions = Y.RDB$DIMENSIONS;
|
|
if (global) {
|
|
copy_exact_name (Y.RDB$FIELD_NAME, global, sizeof(Y.RDB$FIELD_NAME));
|
|
}
|
|
|
|
END_FOR
|
|
ON_ERROR
|
|
return copy_status(gds_status, status);
|
|
END_ERROR;
|
|
|
|
if (!flag)
|
|
return error(status, 5, (ISC_STATUS) isc_fldnotdef,
|
|
(ISC_STATUS) isc_arg_string,
|
|
(ISC_STATUS) desc->array_desc_field_name,
|
|
(ISC_STATUS) isc_arg_string,
|
|
(ISC_STATUS) desc->array_desc_relation_name);
|
|
|
|
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
|
|
}
|
|
|
|
|
|
static ISC_STATUS stuff_args(gen_t* gen, SSHORT count, ...)
|
|
{
|
|
/**************************************
|
|
*
|
|
* s t u f f
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Stuff a SDL byte.
|
|
*
|
|
**************************************/
|
|
UCHAR c;
|
|
va_list ptr;
|
|
|
|
if (gen->gen_sdl + count >= gen->gen_end) {
|
|
if (gen->gen_internal < 0) {
|
|
return error(gen->gen_status, 3, (ISC_STATUS) isc_misc_interpreted,
|
|
(ISC_STATUS) isc_arg_string,
|
|
(ISC_STATUS) "SDL buffer overflow");
|
|
}
|
|
|
|
// The sdl buffer is too small. Allocate a larger one.
|
|
|
|
const SSHORT new_len = gen->gen_end - *gen->gen_sdl_ptr + 512 + count;
|
|
UCHAR* const new_sdl = (UCHAR*) gds__alloc(new_len);
|
|
if (!new_sdl) {
|
|
return error(gen->gen_status, 5, (ISC_STATUS) isc_misc_interpreted,
|
|
(ISC_STATUS) isc_arg_string,
|
|
(ISC_STATUS) "SDL buffer overflow", (ISC_STATUS) isc_arg_gds,
|
|
(ISC_STATUS) isc_virmemexh);
|
|
}
|
|
|
|
const SSHORT current_len = gen->gen_sdl - *gen->gen_sdl_ptr;
|
|
memcpy(new_sdl, *gen->gen_sdl_ptr, current_len);
|
|
if (gen->gen_internal++)
|
|
gds__free(*gen->gen_sdl_ptr);
|
|
gen->gen_sdl = new_sdl + current_len;
|
|
*gen->gen_sdl_ptr = new_sdl;
|
|
gen->gen_end = new_sdl + new_len;
|
|
}
|
|
|
|
va_start(ptr, count);
|
|
|
|
for (; count; --count) {
|
|
c = va_arg(ptr, int);
|
|
*(gen->gen_sdl)++ = c;
|
|
}
|
|
|
|
va_end(ptr);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static ISC_STATUS stuff_literal(gen_t* gen, SLONG literal)
|
|
{
|
|
/**************************************
|
|
*
|
|
* s t u f f _ l i t e r a l
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Stuff an SDL literal.
|
|
*
|
|
**************************************/
|
|
ISC_STATUS* status = gen->gen_status;
|
|
|
|
if (literal >= -128 && literal <= 127)
|
|
return stuff_args(gen, 2, isc_sdl_tiny_integer, literal);
|
|
|
|
if (literal >= -32768 && literal <= 32767)
|
|
return stuff_args(gen, 3, isc_sdl_short_integer, literal, literal >> 8);
|
|
|
|
if (stuff_sdl(gen, isc_sdl_long_integer))
|
|
return status[1];
|
|
if (stuff_sdl_long(gen, literal))
|
|
return status[1];
|
|
|
|
return FB_SUCCESS;
|
|
}
|
|
|
|
|
|
static ISC_STATUS stuff_string(gen_t* gen, UCHAR sdl, const SCHAR* string)
|
|
{
|
|
/**************************************
|
|
*
|
|
* s t u f f _ s t r i n g
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Stuff a "thing" then a counted string.
|
|
*
|
|
**************************************/
|
|
ISC_STATUS* status = gen->gen_status;
|
|
|
|
if (stuff_sdl(gen, sdl))
|
|
return status[1];
|
|
if (stuff_sdl(gen, strlen(string)))
|
|
return status[1];
|
|
|
|
while (*string) {
|
|
if (stuff_sdl(gen, *string++))
|
|
return status[1];
|
|
}
|
|
|
|
return FB_SUCCESS;
|
|
}
|
|
|