home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 May / PCWorld_1999-05_cd.bin / software / Vyzkuste / inprise / INTRBASE_55 / EXAMPLES / API / UDFLIB.C < prev    next >
C/C++ Source or Header  |  1998-10-18  |  12KB  |  466 lines

  1. /*====================================================================
  2.   File Name:    udflib.c
  3.   Description:
  4.   This module contains some user defined functions (UDF).  
  5.   The test suite for UDF will use udf.sql
  6.   to define UDF to the database using SQL statements.
  7. ====================================================================== */
  8.  
  9. #include <stdlib.h>
  10. #include <time.h>
  11. #include <string.h>
  12. #include <math.h>
  13. #include <ibase.h>
  14. #include "example.h"
  15.  
  16. #define BADVAL -9999L
  17. #define MYBUF_LEN 15        /* number of chars to get for */
  18.  
  19. typedef struct blob {
  20.     short    (*blob_get_segment) ();
  21.     void    *blob_handle;
  22.     long    blob_number_segments;
  23.     long    blob_max_segment;
  24.     long    blob_total_length;
  25.     void    (*blob_put_segment) ();
  26. } *BLOB;
  27.  
  28. time_t    time();
  29. char    *ctime();
  30.  
  31. /* variable to return values in.  Needs to be static so it doesn't go 
  32.    away as soon as the function invocation is finished */
  33.  
  34. char    buffer[256];
  35. char    buffer2[512];    /* for string concatenation */
  36. char    datebuf[12];    /* for date string */
  37.  
  38. long    r_long;
  39. double    r_double;
  40. float    r_float;
  41. short    r_short;
  42.  
  43. struct    tm *tbuf;
  44. long    time_sec;
  45.  
  46. ISC_QUAD newdate;
  47.  
  48.  
  49. /*===============================================================
  50.  fn_lower_c() - Puts its argument longo lower case, for C programs
  51.  Input is of VARCHAR, output is of CSTRING.
  52.  Not international or non-ascii friendly.
  53. ================================================================= */
  54. char* EXPORT fn_lower_c (ARG(char*, s))
  55. ARGLIST(char *s)            /* VARCHAR input */
  56. {
  57.     char *buf;
  58.     short length = 0;
  59.  
  60.     char *buffer = (char *)malloc(256);
  61.  
  62.     length = (short)*s;
  63.     s += 2;
  64.     buf = buffer;
  65.     while (*s)
  66.         if (*s >= 'A' && *s <= 'Z')
  67.             *buf++ = *s++ - 'A' + 'a';
  68.         else
  69.             *buf++ = *s++;
  70.  
  71.     *buf = '\0';
  72.     buffer [length] = '\0';
  73.  
  74.     return buffer;
  75. }
  76.  
  77. /*===============================================================
  78.  fn_strcat(s1, s2) - Returns concatenated string. 
  79.     s1 and s2 are varchar to get a length count
  80. ================================================================= */
  81.  
  82. char* EXPORT fn_strcat(ARG(char*, s1), ARG(char*, s2))
  83. ARGLIST(char *s1)
  84. ARGLIST(char *s2)
  85. {
  86.         short j = 0;
  87.     short length1, length2;
  88.     char *p;
  89.  
  90.     char *buffer2 = (char *)malloc(512);
  91.     
  92.     length1 = (short)*s1;
  93.     length2 = (short)*s2;
  94.  
  95.     s1 += 2;
  96.     s2 += 2;
  97.  
  98.     /* strip trailing blanks of s1 */
  99.     p = s1 + length1 - 1;
  100.     while (*p  && *p == ' ')
  101.         p--;
  102.     p++;
  103.     *p = '\0';
  104.  
  105.     p = buffer2;
  106.     while (*s1)
  107.         *p++ = *s1++;
  108.  
  109.     for (j = 0; j < length2; j++)
  110.         if (*s2)
  111.             *p++ = *s2++;
  112.  
  113.     *p = '\0';
  114.         return buffer2; 
  115. }
  116.  
  117. /*===============================================================
  118.  fn_substr(s, m, n) - Returns the substr starting m ending n in s. 
  119. ================================================================= */
  120. char* EXPORT fn_substr(ARG(char*, s), ARG(short*, m), ARG(short*, n))
  121. ARGLIST(char *s)
  122. ARGLIST(short *m)        /* starting position */
  123. ARGLIST(short *n)        /* ending position */
  124. {
  125.         short i = 0;
  126.     short j = 0;
  127.  
  128.     char *buffer = (char *)malloc(256);
  129.  
  130.         if (*m > *n || *m < 1 || *n < 1) return "Bad parameters in substring"; 
  131.  
  132.         while (*s && i++ < *m-1) /* skip */
  133.                 s++;
  134.  
  135.         while (*s && i++ <= *n)  /* copy */
  136.                 buffer[j++] = *s++;
  137.         buffer[j] = '\0';
  138.  
  139.         return buffer;
  140. }
  141.  
  142. /*===============================================================
  143.  fn_trim(s) - Returns string that has leading blanks trimmed. 
  144. ================================================================= */
  145. char* EXPORT fn_trim(ARG(char*, s))
  146. ARGLIST(char *s)
  147. {
  148.     short j = 0;
  149.  
  150.     char *buffer = (char *)malloc(256);
  151.  
  152.         while (*s == ' ')       /* skip leading blanks */
  153.                 s++;
  154.  
  155.         while (*s)        /* copy the rest */
  156.                 buffer[j++] = *s++;
  157.  
  158.         buffer[j] = '\0';
  159.  
  160.         return buffer;
  161. }
  162.  
  163. /*===============================================================
  164.  fn_trunc(s, m) - Returns the string truncated at position m; 
  165.  Input is of CSTRING, output is of VARCHAR.
  166. ================================================================= */
  167. char* EXPORT fn_trunc(ARG(char*, s), ARG(short*, m))
  168. ARGLIST(char *s)
  169. ARGLIST(short *m)
  170. {
  171.     short j = 2;    /* leave 1st 2 bytes for VARCHAR output */
  172.  
  173.     char *buffer = (char *)malloc(256);
  174.  
  175.     while (*s && j < *m + 2)    /* need to add 2 */
  176.         buffer[j++] = *s++;
  177.  
  178.     buffer[j] = '\0';
  179.  
  180.     buffer[0] = (unsigned short) strlen(s) + 2;
  181.     buffer[1] = ' ';    /* anything other than \0 */
  182.  
  183. /*
  184.     *((unsigned short *)buffer) = (unsigned short) (strlen(buffer) + 2);
  185. */
  186.  
  187.         return buffer;        /* VARCHAR output */
  188. }
  189.  
  190.  
  191. /* ==============================================================
  192.    fn_doy() return the nth day of the year, by value.
  193.    ============================================================== */
  194. long EXPORT fn_doy()
  195. {
  196.     char buf[4];    /* for day */
  197.     long i;
  198.  
  199.         time (&time_sec);
  200.         tbuf = localtime(&time_sec);
  201.  
  202.     i = strftime(buf, 4, "%j", tbuf);
  203.     return atoi (buf);
  204. }
  205.  
  206. /* ==============================================================
  207.    fn_moy() return the nth month of the year. e.g. 1,2,3,...12.
  208.    Return by reference.
  209.    ============================================================== */
  210. short* EXPORT fn_moy()
  211. {
  212.         time (&time_sec);
  213.         tbuf = localtime(&time_sec);
  214.     r_short = (short) tbuf->tm_mon + 1;
  215.  
  216.     return &r_short;
  217. }
  218.  
  219. /* ==============================================================
  220.    fn_dow() return the day of today. e.g., Monday, Friday. ...
  221.    ============================================================== */
  222. char* EXPORT fn_dow()
  223. {
  224.         time (&time_sec);
  225.         tbuf = localtime(&time_sec);
  226.  
  227.         switch (tbuf->tm_wday) {
  228.         case 1: return "Monday";
  229.         case 2: return "Tuesday";
  230.         case 3: return "Wednesday";
  231.         case 4: return "Thursday";
  232.         case 5: return "Friday";
  233.         case 6: return "Saturday";
  234.         case 7: return "Sunday";
  235.         default: return "Error in Date";
  236.         }
  237. }
  238.  
  239. /*===============================================================
  240.  fn_sysdate() - Returns the system date in the "MMM-DD-YYYY" format.
  241. ================================================================= */
  242. char* EXPORT fn_sysdate()
  243. {
  244.         short len, i, j = 0;
  245.  
  246.         char *time_str;
  247.  
  248.     char *datebuf = (char *)malloc(12);
  249.  
  250.         time (&time_sec);
  251.         time_str = ctime (&time_sec);
  252.         len = strlen(time_str);
  253.  
  254.         for (i = 4; i <= 10; i++) {
  255.                 if (*(time_str + i) != ' ')
  256.                         datebuf[j++] = *(time_str+i);
  257.                 else if (i == 7 || i == 10)
  258.                         datebuf[j++] = '-';
  259.                 else
  260.                         datebuf[j++] = '0';
  261.         }
  262.         for (i = 20; i < len-1 ; i++)
  263.                 datebuf[j++] = *(time_str+i);
  264.  
  265.         datebuf[j] = '\0';
  266.         return datebuf;
  267. }
  268.  
  269.  
  270.  
  271. /* ==============================================
  272.   fn_add2 (a, b) - returns a + b
  273.   =============================================== */
  274.  
  275. long EXPORT fn_add2 (ARG(long*, a), ARG(long*, b))
  276. ARGLIST(long *a)
  277. ARGLIST(long *b)
  278. {
  279.     return (*a + *b);
  280. }
  281.  
  282.  
  283. /* ==================================================
  284.   fn_mul (a, b) - returns a * b
  285.  =================================================== */
  286.  
  287. double EXPORT fn_mul (ARG(double*, a), ARG(double*, b))
  288. ARGLIST(double *a)
  289. ARGLIST(double *b)
  290. {
  291.     return (*a * *b);
  292. }
  293.  
  294.  
  295. /* ==============================================
  296.   fn_fact (n) - return factorial of n
  297.  ================================================ */
  298.  
  299. double EXPORT fn_fact (ARG(double*, n))
  300. ARGLIST(double *n)
  301. {
  302.     double k;
  303.  
  304.     if (*n > 100) return BADVAL;
  305.         if (*n < 0) return BADVAL;   
  306.  
  307.         if (*n == 0) return 1L;
  308.  
  309.         else {
  310.         k = *n - 1L;
  311.         return (*n * fn_fact(&k));
  312.     }
  313. }
  314.  
  315. /*===============================================================
  316.  fn_abs() - returns the absolute value of its argument.
  317. ================================================================= */
  318. double EXPORT fn_abs(ARG(double*, x))
  319. ARGLIST(double    *x)
  320. {
  321.     return (*x < 0.0) ? -*x : *x;
  322. }
  323.  
  324.  
  325. /*===============================================================
  326.  fn_max() - Returns the greater of its two arguments
  327. ================================================================ */
  328. double EXPORT fn_max(ARG(double*, a), ARG(double*, b))
  329. ARGLIST(double    *a)
  330. ARGLIST(double    *b)
  331. {      
  332.     return  (*a > *b) ? *a : *b;
  333. }
  334.  
  335.  
  336.  
  337. /*===============================================================
  338.  fn_sqrt() - Returns square root of n
  339. ================================================================ */
  340. double* EXPORT fn_sqrt(ARG(double*, n))
  341. ARGLIST(double *n)
  342. {
  343.     r_double = sqrt(*n);
  344.     return &r_double;
  345.  
  346.  
  347.  
  348.  
  349. /*=============================================================
  350.  fn_blob_linecount() returns the number of lines in a blob 
  351.   =============================================================*/
  352.  
  353. long EXPORT fn_blob_linecount (ARG(BLOB, b))
  354. ARGLIST(BLOB b)
  355. {
  356.         char *buf, *p;
  357.     short length, actual_length;
  358.  
  359.     /* Null values */
  360.     if (!b->blob_handle)
  361.         return 0L;
  362.  
  363.     length = b->blob_max_segment + 1L;
  364.     buf = (char *) malloc (length); 
  365.  
  366.     r_long = 0;
  367.         while ((*b->blob_get_segment) (b->blob_handle, buf, length, &actual_length)) 
  368.         {
  369.         buf [actual_length] = 0;
  370.         p = buf;
  371.                 while (*p)  
  372.             if (*p++  == '\n')
  373.                 r_long++;
  374.         }
  375.  
  376.         free (buf); 
  377.         return r_long;  
  378. }
  379.  
  380. /*=============================================================
  381.  fn_blob_bytecount() returns the number of bytes in a blob 
  382.  do not count newlines, so get rid of the newlines. 
  383.  ==============================================================*/
  384.  
  385. long EXPORT fn_blob_bytecount (ARG(BLOB, b))
  386. ARGLIST(BLOB b)
  387. {
  388.     /* Null values */
  389.     if (!b->blob_handle)
  390.         return 0L;
  391.  
  392.         return (b->blob_total_length - fn_blob_linecount(b));  
  393. }
  394.  
  395.  
  396.  
  397. /*=============================================================
  398.  fn_substr_blob() returns portion of TEXT blob beginning at m th
  399.  character and ended at n th character. 
  400.  Newlines are eliminated to make for better printing.
  401.   =============================================================*/
  402.  
  403. char* EXPORT fn_blob_substr(ARG(BLOB, b), ARG(long*, m), ARG(long*, n))
  404. ARGLIST(BLOB b)
  405. ARGLIST(long *m)
  406. ARGLIST(long *n)
  407. {
  408.     char *buf, *p, *q;
  409.     long i = 0;
  410.     long curr_bytecount = 0;
  411.         long begin, end; 
  412.     short length, actual_length;
  413.  
  414.     char *buffer = (char *)malloc(256);
  415.  
  416.     if (!b->blob_handle)
  417.         return "<null>";
  418.     length = b->blob_max_segment + 1L;
  419.     buf = (char *) malloc (length); 
  420.  
  421.  
  422.         if (*m > *n || *m < 1L || *n < 1L) 
  423.         return "";
  424.     if (b->blob_total_length < (long)*m) 
  425.         return "";
  426.  
  427.     begin = *m;                /* beginning position */
  428.  
  429.     if (b->blob_total_length < (long)*n) 
  430.         end = b->blob_total_length;    /* ending position */
  431.     else
  432.         end = *n;
  433.  
  434.     /* Limit the return string to 255 bytes */
  435.     if (end - begin + 1L > 255L)
  436.         end = begin + 254L;
  437.     q = buffer;
  438.  
  439.         while ((*b->blob_get_segment) (b->blob_handle, buf, length, 
  440.         &actual_length))
  441.         {    
  442.         buf [actual_length] = 0;
  443.  
  444.         p = buf;
  445.         while (*p && (curr_bytecount <= end))
  446.             {
  447.             curr_bytecount++;
  448.             if (*p == '\n')
  449.                 *p = ' ';
  450.             if (curr_bytecount >= begin)
  451.                 *q++ = *p;
  452.             p++;
  453.             }
  454.         if (curr_bytecount >= end) 
  455.             {
  456.             *q = 0;
  457.             break;
  458.             }
  459.         }
  460.  
  461.     free (buf);
  462.         return buffer;
  463. }
  464.  
  465.