/* ** Title: Shapes ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software Inc. ** Created: 06/26/1998 13:27 ** Description: This is the generated 'C' file for the Shapes DataBlade. ** Comments: Generated for project Shapes.3.6 */ /* ** The following is placed here to insure ** that name "mangling" does not occur. */ #ifdef __cplusplus extern "C" { #endif /* Standard library includes. */ #include #include #define _REENTRANT #include #undef _REENTRANT #include #include /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "Shapes.h" #include "ShapeTypes.h" void log(char *str) { if (getenv("DEBUG") != NULL) { FILE *fp = fopen("c://temp//rtree.log", "a+"); if (fp == NULL) return; fprintf(fp, "----> %s\n", str); fclose(fp); } } /* {{FUNCTION(08ab3051-18e9-11d1-80b0-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeCompare ** ** Description: ** ** Perform the comparison operations required to compare two ** UDT values. ** ** This function returns zero if the two UDT values are equal and ** a non-zero value otherwise. ** ** Special Comments: ** ** Compares two variable-length opaque types ** ** Parameters: ** ** mi_bitvarying * Gen_param1; The first UDT value to compare. ** mi_bitvarying * Gen_param2; The second UDT value to compare. ** MI_FPARAM * Gen_fparam; Standard info - see DBDK docs. ** ** Return value: ** ** mi_integer The comparison result. ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MyShapeCompare FunctionId: 08ab3051-18e9-11d1-80b0-0800095a455b ** ***************************************************************** */ mi_integer MyShapeCompare ( mi_bitvarying * Gen_param1, /* The first UDT value to compare. */ mi_bitvarying * Gen_param2, /* The second UDT value to compare. */ MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs. */ ) { mi_integer datalen; Shape * Gen_Value1; /* Pointer to the first value. */ Shape * Gen_Value2; /* Pointer to the second value. */ mi_integer retval; /* Point to the data values that are to be compared. */ Gen_Value1 = (Shape *)mi_get_vardata( (mi_lvarchar *)Gen_param1 ); Gen_Value2 = (Shape *)mi_get_vardata( (mi_lvarchar *)Gen_param2 ); /* PROGRAMMER's NOTE: The comparison works as follows: If the two shapes compared are different, then they are compared and their order in the ShapeTypeEnum determines which shape is greater, else, a bitwise compare is done of their data. For type point, we use a smarter comparism by recreating the points and comparing the members directly. This function could become more sophisticated depending on some protocol that we may follow( eg. greater the area, larger the object) in which case that logic would have to be implemented in the else part. */ if (Gen_Value1->hdr.tag != Gen_Value2->hdr.tag) { retval= (Gen_Value1->hdr.tag > Gen_Value2->hdr.tag) ? 1 : -1; } else { datalen = sizeof(ShapeHdr); switch ( Gen_Value1->hdr.tag ) { case PointT: { PointData pnt1; PointData pnt2; /* retrieve the point data */ memcpy ( &pnt1, &Gen_Value1->data, sizeof(PointData) ); memcpy ( &pnt2, &Gen_Value2->data, sizeof(PointData) ); /* compare the points */ if (pnt1.x > pnt2.x) { retval = 1; } else if (pnt1.x < pnt2.x) { retval = -1; } else { if (pnt1.y > pnt2.y) { retval = 1; } else if (pnt1.y < pnt2.y) { retval = -1; } else { retval = 0; } } } break; case BoxT: datalen += sizeof(BoxData); retval = memcmp((const void*) Gen_Value1, (const void*) Gen_Value2, datalen); if( retval > 0 ) retval = 1; else if ( retval < 0 ) retval = -1; break; case CircleT: datalen += sizeof(CircleData); retval = memcmp((const void*) Gen_Value1, (const void*) Gen_Value2, datalen); if( retval > 0 ) retval = 1; else if ( retval < 0 ) retval = -1; break; default: break; } } return retval; } /* }}FUNCTION (#JB7L) */ /* {{FUNCTION(9a830881-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeEqual ** ** Description: ** ** Determine if one UDT value is equal to another. ** ** Special Comments: ** ** Compares two variable-length opaque types for equality ** ** Parameters: ** ** mi_bitvarying * Gen_param1; The first UDT value to compare. ** mi_bitvarying * Gen_param2; The second UDT value to compare. ** MI_FPARAM * Gen_fparam; Standard info - see DBDK docs. ** ** Return value: ** ** mi_boolean The comparison result. ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MyShapeEqual FunctionId: 9a830881-133b-11d1-80af-0800095a455b ** ***************************************************************** */ mi_boolean MyShapeEqual ( mi_bitvarying * Gen_param1, /* The first UDT value to compare. */ mi_bitvarying * Gen_param2, /* The second UDT value to compare. */ MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs. */ ) { /* Call Compare to perform the comparison. */ return (mi_boolean)(0 == MyShapeCompare( Gen_param1, Gen_param2, Gen_fparam )); } /* }}FUNCTION (#MG35) */ /* {{FUNCTION(08ab3052-18e9-11d1-80b0-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeNotEqual ** ** Description: ** ** Determine if one UDT value is not equal to another. ** ** Special Comments: ** ** Compares two variable-length opaque types for non-equality ** ** Parameters: ** ** mi_bitvarying * Gen_param1; The first UDT value to compare. ** mi_bitvarying * Gen_param2; The second UDT value to compare. ** MI_FPARAM * Gen_fparam; Standard info - see DBDK docs. ** ** Return value: ** ** mi_boolean The comparison result. ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MyShapeNotEqual FunctionId: 08ab3052-18e9-11d1-80b0-0800095a455b ** ***************************************************************** */ mi_boolean MyShapeNotEqual ( mi_bitvarying * Gen_param1, /* The first UDT value to compare. */ mi_bitvarying * Gen_param2, /* The second UDT value to compare. */ MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs. */ ) { /* Call Compare to perform the comparison. */ return (mi_boolean)(0 != MyShapeCompare( Gen_param1, Gen_param2, Gen_fparam )); } /* }}FUNCTION (#0H4S) */ /* {{FUNCTION(9a830887-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeOverlap ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Overlap (MyShape,MyShape) returns boolean. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeOverlap ( MyShape * Argument1, MyShape * Argument2, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ mi_boolean boxOverlap; ShapeHdr* h1 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument1 ); ShapeHdr* h2 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument2 ); /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* * Bounding box check. */ boxOverlap = ( h1->xmin <= h2->xmax && h2->xmin <= h1->xmax && h1->ymin <= h2->ymax && h2->ymin <= h1->ymax ); if (!boxOverlap) { Gen_RetVal = MI_FALSE; } else { if (h1->tag == HeaderT || h2->tag == HeaderT) Gen_RetVal = MI_TRUE; else Gen_RetVal = Dispatch(intersectTable, MI_TRUE, (Shape*) h1, (Shape*) h2, Gen_fparam); } /* ------ }}Your_Code (#CAD2) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#QD90) */ /* {{FUNCTION(9a830882-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeContains ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Contains (MyShape,MyShape) returns boolean. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeContains ( MyShape * Argument1, MyShape * Argument2, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ ShapeHdr* h1; ShapeHdr* h2; mi_boolean boxOverlap; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ h1 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument1 ); h2 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument2 ); /* PROGRAMMER's NOTE: This function determines if shape 1( argument1 ) contains shape 2 (argument2). If the first region is a point, then NULL value is returned. Else we return the true only if the second region is completely contained in the first. */ /* * Return NULL for non-region first argument. */ switch (h1->tag) { case HeaderT: case BoxT: case CircleT: boxOverlap = MI_TRUE; /* This is set just to enter the next if loop */ break; case PointT: default: mi_fp_setreturnisnull((Gen_fparam), 0, MI_TRUE); Gen_RetVal = MI_FALSE; } if( boxOverlap ) { boxOverlap = ( h1->xmin <= h2->xmax && h2->xmin <= h1->xmax && h1->ymin <= h2->ymax && h2->ymin <= h1->ymax ); if (!boxOverlap) { Gen_RetVal = MI_FALSE; } else { /* * Internal index node case. */ if (h1->tag == HeaderT || h2->tag == HeaderT) { Gen_RetVal = MI_TRUE; } else { /* * Geometric test. */ Gen_RetVal = Dispatch(insideTable, MI_FALSE, (Shape*) h2, (Shape*) h1, Gen_fparam); } } } /* ------ }}Your_Code (#BD8C) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#TV0B) */ /* {{FUNCTION(9a830883-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeWithin ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Within (MyShape,MyShape) returns boolean. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeWithin ( MyShape * Argument1, MyShape * Argument2, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ ShapeHdr * h1; ShapeHdr * h2; mi_boolean boxOverlap = MI_FALSE; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ h1 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument1 ); h2 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument2 ); /* * Return NULL for non-region second argument. */ switch (h2->tag) { case HeaderT: case BoxT: case CircleT: boxOverlap = MI_TRUE; /* Used only to enter the next if */ break; case PointT: default: mi_fp_setreturnisnull((Gen_fparam), 0, MI_TRUE); Gen_RetVal = MI_FALSE; } if( boxOverlap ) { boxOverlap = ( h1->xmin <= h2->xmax && h2->xmin <= h1->xmax && h1->ymin <= h2->ymax && h2->ymin <= h1->ymax ); if (!boxOverlap) { Gen_RetVal = MI_FALSE; } else { /* * Internal index node case. */ if (h1->tag == HeaderT || h2->tag == HeaderT) { Gen_RetVal = MI_TRUE; } else { /* * Geometric test */ Gen_RetVal = Dispatch(insideTable, MI_FALSE, (Shape*) h1, (Shape*) h2, Gen_fparam); } } } /* ------ }}Your_Code (#0L2V) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#KFFH) */ /* {{FUNCTION(9a830884-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeUnion ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Union (MyShape,MyShape,MyShape) returns integer. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeUnion ( MyShape * Argument1, MyShape * Argument2, MyShape * Argument3, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ ShapeHdr* h1 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument1 ); ShapeHdr* h2 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument2 ); ShapeHdr* h3 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument3 ); /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ if ( h1 == h2 ) { /* This is a 'self-union', which is how the rtree determines how * big your header structure is. */ h3->tag = HeaderT; h3->flags = 0; h3->xmin = h1->xmin; h3->ymin = h1->ymin; h3->xmax = h1->xmax; h3->ymax = h1->ymax; } else { /* * Caution! h1 and h3 may both reference the same structure! * Likewise, h2 and h3 may both reference the same structure! * This is because the Rtree reuses variables to save memory. * This means we have to be careful to save the union of h1 and h2 * in a temporary structure as we compute it, otherwise we will * prematurely wipe out h1 or h2 as we save the union in h3. */ ShapeHdr htemp; htemp.xmin = (h1->xmin < h2->xmin) ? h1->xmin : h2->xmin; htemp.ymin = (h1->ymin < h2->ymin) ? h1->ymin : h2->ymin; htemp.xmax = (h1->xmax > h2->xmax) ? h1->xmax : h2->xmax; htemp.ymax = (h1->ymax > h2->ymax) ? h1->ymax : h2->ymax; h3->tag = HeaderT; h3->flags = 0; h3->xmin = htemp.xmin; h3->ymin = htemp.ymin; h3->xmax = htemp.xmax; h3->ymax = htemp.ymax; } /* * Theoretically you should only have to do this for the self-union * case, since after that the Rtree should know how big each * element to be stored on internal node pages will be. However, * early versions of the Rtree code did not always 'remember' the * size correctly, so we do it for every union call. It's not a * very expensive function: it just sets a field in the mi_lvarchar * opaque data structure. */ mi_set_varlen ( (mi_lvarchar*) Argument3, sizeof(ShapeHdr) ); Gen_RetVal = 1; /* ------ }}Your_Code (#NJLJ) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#6PAQ) */ /* {{FUNCTION(9a830885-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeSize ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Size (MyShape,double precision) returns integer. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeSize ( MyShape * Argument1, mi_double_precision * Argument2, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ ShapeHdr* hdr = (ShapeHdr*) mi_get_vardata ((mi_lvarchar*) Argument1); /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ if ( hdr->flags == 1 ) { /* * Since flag is set, this Size() call follows an Inter() call * in which the two objects did not intersect. Return zero * to tell the Rtree that this is the case. */ *Argument2 = 0.0; } else { *Argument2 = (mi_double) (hdr->xmax - hdr->xmin) * (hdr->ymax - hdr->ymin); /* * Guard against returning zero. Since we are using an area method * to compute size, this could happen for a point, or a horizontal * or vertical line segment (box with zero height/width). */ if (*Argument2 < 0.000001) *Argument2 = 0.000001; } Gen_RetVal = 1; /* ------ }}Your_Code (#ED32) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#7GLQ) */ /* {{FUNCTION(9a830886-133b-11d1-80af-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeInter ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine Inter (MyShape,MyShape,MyShape) returns integer. ** ** Parameters: ** ** Return value: ** ** mi_integer ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_integer MyShapeInter ( MyShape * Argument1, MyShape * Argument2, MyShape * Argument3, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { MI_CONNECTION * Gen_Con; /* The connection handle. */ mi_integer Gen_RetVal; /* The return value. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ ShapeHdr* h1 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument1 ); ShapeHdr* h2 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument2 ); ShapeHdr* h3 = (ShapeHdr*) mi_get_vardata ( (mi_lvarchar*) Argument3 ); /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ if (!((h1->xmin <= h2->xmax) && (h1->xmax >= h2->xmin) && (h1->ymin <= h2->ymax) && (h1->ymax >= h2->ymin))) { /* * Bounding boxes of the two shapes do not intersect. * Set the flag word to indicate this. */ h3->tag = HeaderT; h3->flags = 1; h3->xmin = h3->ymin = h3->xmax = h3->ymax = 0; Gen_RetVal = 0; } else { /* * Bounding boxes of the two shapes do intersect. * Clear the flag word, and compute the bbox intersection. * Note that even if h3==h1, we aren't prematurely wiping * out any data. (Compare with Union() function.) */ h3->tag = HeaderT; h3->flags = 0; h3->xmin = (h1->xmin > h2->xmin) ? h1->xmin : h2->xmin; h3->ymin = (h1->ymin > h2->ymin) ? h1->ymin : h2->ymin; h3->xmax = (h1->xmax < h2->xmax) ? h1->xmax : h2->xmax; h3->ymax = (h1->ymax < h2->ymax) ? h1->ymax : h2->ymax; Gen_RetVal = 1; } mi_set_varlen ( (mi_lvarchar*) Argument3, sizeof(ShapeHdr) ); /* ------ }}Your_Code (#PJLJ) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#62QQ) */ /* {{FUNCTION(6b5abfc0-0f1e-11d1-9b29-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeInput ** ** Description: ** ** This function converts from the external representation of the ** UDT type MyShape to its internal representation. The external ** representation is a blank-separated list of values and the ** internal representation is a 'C' structure of type MyShape as ** defined in the header file. ** ** ** Data can be inserted into a table using an SQL insert statement: ** ** insert into tablename values ( 'value-list' ); ** ** value-list is a space-delimited list of values. ** ** Special Comments: ** ** Support routine for opaque type MyShape returns mi_lvarchar. ** ** Parameters: ** ** mi_lvarchar * Gen_param1; Pointer to the input text. ** MI_FPARAM * Gen_fparam; Standard info - see DBDK docs. ** ** Return value: ** ** mi_lvarchar * The constructed UDT value. ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MyShapeInput FunctionId: 6b5abfc0-0f1e-11d1-9b29-0800095a455b ** ***************************************************************** */ mi_lvarchar * MyShapeInput ( mi_lvarchar * Gen_param1, /* Pointer to the input text. */ MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs. */ ) { MI_CONNECTION * Gen_Con; /* The current connection. */ mi_char * Gen_InData; /* Pointer to the input data. */ Shape * Gen_OutData; /* Pointer to the output data. */ mi_lvarchar * Gen_RetVal; /* The return value. */ mi_char* token; mi_integer varchar_len; #ifndef WIN32 mi_char * Remainder; #endif /* Get the current connection handle. */ Gen_Con = mi_open( NULL, NULL, NULL ); /* Verify that the connection has been established. */ if( Gen_Con == 0 ) { /* ** Opening the current connection has failed ** so issue the following message and quit. ** ** "Connection has failed in MyShapeInput." */ DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG1, 10 ); /* not reached */ } /* ** Write to the trace file indicating ** that MyShapeInput has been called. */ DBDK_TRACE_ENTER( "MyShapeInput" ); /* Point to the input data. */ /* PROGRAMMER's NOTE: We need to extract the string and depending on whether it is a box or a circle or a point, we will allocate and initialize the appropriate structures. Conceptually, the data is structured as follows: struct Shape { ShapeHdr PointData | CircleData | BoxData } */ token = (char *)mi_get_vardata( Gen_param1 ); Gen_InData = (char *) mi_alloc( strlen( token ) + 1); strcpy( Gen_InData, token ); varchar_len = sizeof(ShapeHdr); #ifndef WIN32 token = strtok_r( Gen_InData, "(" , &Remainder); Gen_InData = Remainder; #else token = strtok( Gen_InData, "(" ); #endif if ( strcmp ( token, "box" ) == 0 ) { /* PROGRAMMER's NOTE: Box contains 4 numbers */ BoxData box; /* PROGRAMMER's NOTE: Note the use of strtok_r. This is a safe practice, as we need to remember that we are running in a multithreaded environment which implies that this code may be called by multiple threads. This could cause a problem with strtok. */ #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif /* PROGRAMMER's NOTE: These check for less numbers in the input string than required */ if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } box.ll.x = atof ( token ); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } box.ll.y = atof (token); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } box.ur.x = atof ( token ); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL ) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } box.ur.y = atof ( token ); varchar_len += sizeof(BoxData); /* PROGRAMMER's NOTE: Allocate sufficient memory, and initialize the data structures. */ Gen_RetVal = (mi_lvarchar*) mi_new_var ( varchar_len ); Gen_OutData = (Shape*) mi_get_vardata ( Gen_RetVal ); Gen_OutData->hdr.xmin = box.ll.x; Gen_OutData->hdr.ymin = box.ll.y; Gen_OutData->hdr.xmax = box.ur.x; Gen_OutData->hdr.ymax = box.ur.y; Gen_OutData->hdr.tag = BoxT; memcpy ( &Gen_OutData->data, &box, sizeof(BoxData) ); } else if ( strcmp ( token, "circle" ) == 0 ) { CircleData circ; /* PROGRAMMER's NOTE: Circle contains 3 numbers */ #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } circ.c.x = atof ( token ); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } circ.c.y = atof ( token ); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL ) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } circ.r = atof ( token ); varchar_len += sizeof(CircleData); Gen_RetVal = (mi_lvarchar*) mi_new_var ( varchar_len ); Gen_OutData = (Shape*) mi_get_vardata ( Gen_RetVal ); Gen_OutData->hdr.xmin = circ.c.x - circ.r; Gen_OutData->hdr.ymin = circ.c.y - circ.r; Gen_OutData->hdr.xmax = circ.c.x + circ.r; Gen_OutData->hdr.ymax = circ.c.y + circ.r; Gen_OutData->hdr.tag = CircleT; memcpy ( &Gen_OutData->data, &circ, sizeof(CircleData) ); } else if ( strcmp ( token, "point" ) == 0 ) { PointData pnt; /* PROGRAMMER's NOTE: Point contains 2 numbers */ #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } pnt.x = atof ( token ); #ifndef WIN32 token = strtok_r( Gen_InData,",", &Remainder ); Gen_InData = Remainder; #else token = strtok( NULL , "," ); #endif if( token == NULL ) { DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); } pnt.y = atof ( token ); varchar_len += sizeof(PointData); Gen_RetVal = (mi_lvarchar*) mi_new_var ( varchar_len ); Gen_OutData = (Shape*) mi_get_vardata ( Gen_RetVal ); Gen_OutData->hdr.xmin = pnt.x; Gen_OutData->hdr.ymin = pnt.y; Gen_OutData->hdr.xmax = pnt.x; Gen_OutData->hdr.ymax = pnt.y; Gen_OutData->hdr.tag = PointT; memcpy ( &Gen_OutData->data, &pnt, sizeof(PointData) ); } else { /* ** Opening the current connection has failed ** so issue the following message and quit. ** ** "Connection has failed in MyShapeInput." */ DBDK_TRACE_ERROR( "MyShapeInput", ERRORMESG11, 10 ); /* not reached */ } Gen_OutData->hdr.flags = 0; /* ** Write to the trace file indicating ** that MyShapeInput has successfully exited. */ DBDK_TRACE_EXIT( "MyShapeInput" ); mi_free( Gen_InData ); /* Close the connection. */ mi_close( Gen_Con ); /* Return the UDT value. */ return Gen_RetVal; } /* }}FUNCTION (#IFTG) */ /* {{FUNCTION(6b5abfc1-0f1e-11d1-9b29-0800095a455b) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MyShapeOutput ** ** Description: ** ** This function converts from the internal representation of the ** UDT type MyShape to its external representation. The external ** representation is a blank-separated list of values and the ** internal representation is a 'C' structure of type MyShape as ** defined in the header file. ** ** Data can be retrieved from a table using an SQL select statement: ** ** select * from tablename; ** ** Special Comments: ** ** Support routine for opaque type MyShape returns mi_lvarchar. ** ** Parameters: ** ** mi_lvarchar * Gen_param1; Pointer to the input text. ** MI_FPARAM * Gen_fparam; Standard info - see DBDK docs. ** ** Return value: ** ** mi_lvarchar * The constructed UDT value. ** ** History: ** ** 06/26/1998 - Generated by BladeSmith Version 3.60.626 . ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MyShapeOutput FunctionId: 6b5abfc1-0f1e-11d1-9b29-0800095a455b ** ***************************************************************** */ mi_lvarchar * MyShapeOutput ( mi_lvarchar * Gen_param1, /* The UDT value. */ MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs. */ ) { MI_CONNECTION * Gen_Con; /* The current connection. */ Shape * Gen_InData; /* Pointer to the input data. */ char * Gen_OutData; /* Pointer to the output data. */ mi_lvarchar * Gen_RetVal; /* The return result. */ mi_char textbuf[200]; /* Get the current connection handle. */ Gen_Con = mi_open( NULL, NULL, NULL ); /* Verify that the connection has been established. */ if( Gen_Con == 0 ) { /* ** Opening the current connection has failed ** so issue the following message and quit. ** ** "Connection has failed in MyShapeOutput." */ DBDK_TRACE_ERROR( "MyShapeOutput", ERRORMESG1, 10 ); /* not reached */ } /* ** Write to the trace file indicating ** that MyShapeOutput has been called. */ DBDK_TRACE_ENTER( "MyShapeOutput" ); Gen_InData = (Shape*) mi_get_vardata ( (mi_lvarchar*) Gen_param1 ); /* PROGRAMMER's NOTE: Based on the type, we will format the output accordingly */ switch ( Gen_InData->hdr.tag ) { case BoxT: { BoxData* box; box = (BoxData*) Gen_InData->data; sprintf ( textbuf, "box(%0.3f,%0.3f,%0.3f,%0.3f)", box->ll.x, box->ll.y, box->ur.x, box->ur.y ); } break; case CircleT: { CircleData* circle; circle = (CircleData*) Gen_InData->data; sprintf ( textbuf, "circle(%0.3f,%0.3f,%0.3f)", circle->c.x, circle->c.y, circle->r ); } break; case PointT: { PointData* point; point = (PointData*) Gen_InData->data; sprintf ( textbuf, "point(%0.3f,%0.3f)", point->x, point->y ); } break; } /* Allocate room for the output string. */ Gen_RetVal = mi_new_var( strlen( textbuf ) + 1 ); if( Gen_RetVal == 0 ) { /* ** Memory allocation has failed so issue ** the following message and quit. ** ** "Memory allocation has failed in MyShapeOutput." */ DBDK_TRACE_ERROR( "MyShapeOutput", ERRORMESG2, 10 ); /* not reached */ } /* Point to the output data. */ Gen_OutData = mi_get_vardata( Gen_RetVal ); strcpy( Gen_OutData, textbuf ); /* ** Write to the trace file indicating ** that MyShapeOutput has successfully exited. */ DBDK_TRACE_EXIT( "MyShapeOutput" ); /* Close the connection. */ mi_close( Gen_Con ); return Gen_RetVal; } /* }}FUNCTION (#2CI1) */ #ifdef __cplusplus } #endif