/*
     +----------------------------------------------------------------------+
     | MySQL User Defined Functions Library & Plugin Library                |
     +----------------------------------------------------------------------+
     | Copyright ( c ) 2007 MySqdLib                                        |
     +----------------------------------------------------------------------+
     | This program is free software; you can redistribute it and/or modify |
     | it under the terms of the GNU General Public License as published by |
     | the Free Software Foundation; either version 2 of the License, or    |
     | ( at your option ) any later version.                                |
     |                                                                      |
     | This program is distributed in the hope that it will be useful,      |
     | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
     | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
     | GNU General Public License for more details.                         |
     |                                                                      |
     | You should have received a copy of the GNU General Public License    |
     | along with this program; if not, write to the Free Software          |
     | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
     | USA                                                                  |
     +----------------------------------------------------------------------+
     | Authors: MMMed <momed @ users dot1 sourceforge dot2 net>       |
     +----------------------------------------------------------------------+

     +----------------------------------------------------------------------+
     | NOTE : New UDF function definition/wrapper set on MYSQL_UDF_API.h    |
     +----------------------------------------------------------------------+
     | FUNCTION(                                                            |
     |   name       , => function name                                      |
     |   type       , => function type retrun(STRING|REAL|LONG)             |
     |   /S;|R;|I;/ , => args->arg_type pattern (S:STRING;I:INTEGER;R:REAL) |
     |   arg_count  , => args->arg_count min , must be > 0                  |
     |   maybe_null , => initid->maybe_null (1|0)                           |
     |   max_length , => initid->max_length, -1 to no max                   |
     |   "USAGE: .."  => String to be used as error message                 |
     | )                                                                    |
     +----------------------------------------------------------------------+
*/

#include "../MYSQL_UDF_API.h"       /* include MySqdLib UDF API */
#include "./libs/bstring/bstrlib.h" /* include BSting lib header */

/******************************************************************************
** str_mid ( string b, int left, int len )
**    Create a bstring which is the substring of b starting from position left 
**    and running for a length len (clamped by the end of the bstring b.)
******************************************************************************/
// {{{
	FUNCTION( str_mid, STRING, "S;I;I", 3, 1, 255, 
    "USAGE: STRING str_mid( STRING b, INT left, INT len)" )
    {
		bstring string ;
		long long left, len;

		string  = bfromcstr ( ARGV(0) );
		left    = *((long long*) ARGV(1));
		len     = *((long long*) ARGV(2) );

		RETURN_STRING( bdata( bmidstr( string, left, len ) ) );
    }
// }}}

/******************************************************************************
** str_del ( string b, int pos, int len )
**    Removes characters from pos to pos+len-1 and shifts the tail of the 
**    bstring starting from pos+len to pos.   
******************************************************************************/
// {{{
    FUNCTION( str_del, STRING, "S;I;I", 3, 1, 255, 
    "USAGE: STRING str_del( STRING b, INT pos, INT len)" )
	{
		bstring string ;
		long long pos, len;

		string = bfromcstr ( ARGV(0) );
		pos    = *( (long long*) ARGV(1) );
		len    = *( (long long*) ARGV(2) );

		bdelete( string, pos, len );

		RETURN_STRING( bdata( string ) );
    }
// }}}

/******************************************************************************
** use BString::extern bconcat (bstring b0, const_bstring b1);
**    Concatenate the bstring b1 to the end of bstring b0.  The value BSTR_OK 
**    is returned if the operation is successful, otherwise BSTR_ERR is 
**    returned.
******************************************************************************/
// {{{
    FUNCTION( str_concat, STRING, "S;S", 2, 1, 255, 
    "USAGE: STRING str_concat(STRING a, STRING b)" )
	{
		bstring string_1 = bfromcstr ( ARGV(0) );
		bstring string_2 = bfromcstr ( ARGV(1) );
		
		bconcat ( string_1, string_2 );

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}

/******************************************************************************
** str_nconcat
**    Concatenate a fixed length buffer (s, len) to the end of bstring b.  The 
******************************************************************************/
// {{{
	FUNCTION( str_nconcat, STRING, "S;S;I", 3, 1, 255, 
    "USAGE: STRING str_nconcat(STRING a, STRING b, INT len)" )
    {
		bstring     string_1 = bfromcstr ( ARGV(0) );
		bstring     string_2 = bfromcstr ( ARGV(1) );
        long long   len      = *((long long*) ARGV(2) );

		bconcat ( string_1 , bmidstr ( string_2, 0, len ) );

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}

/******************************************************************************
** str_cmp
**    use BString::extern int bstrcmp (const_bstring b0, const_bstring b1);
**
**    Compare the bstrings b0 and b1 for ordering.  ...
******************************************************************************/
// {{{
	FUNCTION( str_cmp, LONG, "S;S", 2, 0, 6, 
    "USAGE: INT str_cmp(STRING a, STRING b)" )
	{
		bstring string_1 = bfromcstr ( ARGV(0) );
		bstring string_2 = bfromcstr ( ARGV(1) );

		int     retval   = bstrcmp ( string_1 , string_2 );

		RETURN_LONG( retval );
    }
// }}}
 
/******************************************************************************
** str_ncmp
**
**   Compare the bstrings b0 and b1 for at most n characters.
******************************************************************************/
// {{{
	FUNCTION( str_ncmp, LONG, "S;S;I", 3, 0, 6, 
    "USAGE: INT str_ncmp(STRING a, STRING b, INT len)" )
	{
		bstring   string_1 = bfromcstr ( ARGV(0) );
		bstring   string_2 = bfromcstr ( ARGV(1) );
		long long len      = *((long long*) ARGV(2) ); 

		int       retval   = bstrcmp ( bmidstr ( string_1, 0, len ) , bmidstr ( string_2, 0, len ) );

		RETURN_LONG( retval );
    }
// }}}
 
/******************************************************************************
** str_icmp
**
**   Compare two bstrings without differentiating between case.
******************************************************************************/
// {{{
	FUNCTION( str_icmp, LONG, "S;S", 2, 0, 6, 
    "USAGE: INT str_icmp(STRING a, STRING b)" )
	{
		bstring   string_1 = bfromcstr ( ARGV(0) );
		bstring   string_2 = bfromcstr ( ARGV(1) );

		int       retval   = bstricmp ( string_1, string_2 );

		RETURN_LONG( retval );
    }
// }}}

/******************************************************************************
** str_incmp
**
**   Compare two bstrings without differentiating between case for at most n characters.
******************************************************************************/
// {{{
	FUNCTION( str_incmp, LONG, "S;S;I", 3, 0, 6, 
    "USAGE: INT str_incmp(STRING a, STRING b, INT len)" ) 
	{
		bstring   string_1 = bfromcstr ( ARGV(0) );
		bstring   string_2 = bfromcstr ( ARGV(1) );
		long long len      = *((long long*) ARGV(2) ); 

		int       retval   = bstrnicmp ( string_1, string_2, len ); 

		RETURN_LONG( retval );
    }
// }}} 
 
/******************************************************************************
** str_set
**   use BString::extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill);   
**   Overwrite the bstring b0 starting at position pos with the bstring b1
******************************************************************************/
// {{{
	FUNCTION( str_set, STRING, "S;I;S;S", 4, 1, 255, 
    "USAGE: STRING str_set (STRING a, INT pos, STRING b, CHAR fill)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     pos      = *((long long*) ARGV(1) ); 
		bstring       string_2 = bfromcstr ( ARGV(2) );
		unsigned char fill     = *((unsigned char*) ARGV(3) ); 

		bsetstr ( string_1, pos, string_2,  fill ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
 
/******************************************************************************
** str_insert
**   use BString::extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill);
**   Inserts the bstring s2 into s1 at position pos.
******************************************************************************/
// {{{
	FUNCTION( str_insert, STRING, "S;I;S;S", 4, 1, 255, 
    "USAGE: STRING str_insert(STRING a, INT pos, STRING b, CHAR fill)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     pos      = *((long long*) ARGV(1) ); 
		bstring       string_2 = bfromcstr ( ARGV(2) );
		unsigned char fill     = *((unsigned char*) ARGV(3) ); 

		binsert ( string_1, pos, string_2,  fill ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
 
/******************************************************************************
** str_cinsert
**   use BString::extern int binsertch (bstring s1, int pos, int len, unsigned char fill);
**   Inserts the character fill repeatedly into s1 at position pos for a length len.
******************************************************************************/
// {{{
	FUNCTION( str_cinsert, STRING, "S;I;I;S", 4, 1, 255, 
    "USAGE: STRING str_cinsert(STRING a, INT pos, INT len,CHAR fill)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     pos      = *((long long*) ARGV(1) ); 
		long long     len      = *((long long*) ARGV(2) ); 
		unsigned char fill     = *((unsigned char*) ARGV(3) ); 

		binsertch ( string_1, pos, len,  fill ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
  
/******************************************************************************
** str_replace
**   use BString::extern int bfindreplace (bstring b, const_bstring find,
**                           const_bstring replace, int position);
**   Replace all occurrences of the find substring with a replace bstring 
**   after a given position in the bstring b.
******************************************************************************/
// {{{
	FUNCTION( str_replace, STRING, "S;S;S;I", 4, 1, 255, 
    "USAGE: STRING str_replace(STRING str, STRING find, STRING replace, INT pos)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		bstring       string_2 = bfromcstr ( ARGV(1) );
		bstring       string_3 = bfromcstr ( ARGV(2) );
		long long     pos      = *((long long*) ARGV(1) );  

		bfindreplace ( string_1, string_2, string_3, pos ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
  
/******************************************************************************
** str_ireplace
**   use BString::extern int bfindreplacecaseless (bstring b, const_bstring find,
**                           const_bstring replace, int position);
**   Replace all occurrences of the find substring, ignoring case, with a 
**   replace bstring after a given position in the bstring b.
******************************************************************************/
// {{{
	FUNCTION( str_ireplace, STRING, "S;S;S;I", 4, 1, 255, 
    "USAGE: STRING str_ireplace(STRING str, STRING find, STRING replace, INT pos)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		bstring       string_2 = bfromcstr ( ARGV(1) );
		bstring       string_3 = bfromcstr ( ARGV(2) );
		long long     pos      = *((long long*) ARGV(1) );  

		bfindreplacecaseless ( string_1, string_2, string_3, pos ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
 
/******************************************************************************
** str_lreplace
**   use BString::extern int breplace (bstring b1, int pos, int len, const_bstring b2, 
**                       unsigned char fill);
**   Replace a section of a bstring from pos for a length len with the bstring 
**   b2.
******************************************************************************/
// {{{
	FUNCTION( str_lreplace, STRING, "S;I;I;S;S", 5, 1, 255, 
    "USAGE: STRING str_lreplace(STRING a, INT pos, INT len, STRING b, CHAR fill)" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     pos      = *((unsigned long long*) ARGV(1) ); 
		long long     len      = *((unsigned long long*) ARGV(2) ); 
		bstring       string_2 = bfromcstr ( ARGV(3) );
		unsigned char fill     = *((unsigned char*) ARGV(4) ); 

		breplace ( string_1, pos, len, string_2,  fill ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}} 
 
/******************************************************************************
** str_trunc
**   use BString::int btrunc (bstring b, int n);
**   Truncate the bstring to at most n characters.
******************************************************************************/
// {{{
	FUNCTION( str_trunc, STRING, "S;I", 2, 1, 255, 
    "USAGE: STRING str_trunc( STRING a, INT n ) " )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     n        = *((unsigned long long*) ARGV(1) ); 

		btrunc ( string_1, n ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_repeate
**   use BString::extern int bpattern (bstring b, int len);
**   Replicate the starting bstring, b, end to end repeatedly until it 
**   surpasses len characters, then chop the result to exactly len characters.
******************************************************************************/
// {{{
	FUNCTION( str_repeate, STRING, "S;I", 2, 1, 255, 
    "USAGE: STRING str_repeate( STRING a, INT len ) " )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		long long     len      = *((unsigned long long*) ARGV(1) ); 

		bpattern ( string_1, len ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_tu
**   use BString::extern int btoupper (bstring b);
**   Convert contents of bstring to upper case. 
******************************************************************************/
// {{{
	FUNCTION( str_tu, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_tu( STRING a ) " )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) ); 

		btoupper ( string_1 ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_tl
**   use BString::extern int btolower (bstring b);
**   Convert contents of bstring to lower case 
******************************************************************************/
// {{{
	FUNCTION( str_tl, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_tl( STRING a ) " )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) ); 

		btolower ( string_1 ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_ltrim
**   use BString::extern int bltrimws (bstring b);
**   Delete whitespace contiguous from the left end of the bstring.
******************************************************************************/
// {{{
	FUNCTION( str_ltrim, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_ltrim( STRING a )" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) ); 

		bltrimws ( string_1 ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_rtrim
**   use BString::extern int brtrimws (bstring b);
**   Delete whitespace contiguous from the right end of the bstring. 
******************************************************************************/
// {{{
	FUNCTION( str_rtrim, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_rtrim( STRING a )" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) ); 

		brtrimws ( string_1 ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_trim
**   use BString::extern int btrimws (bstring b);
**   Delete whitespace contiguous from both ends of the bstring.
******************************************************************************/
// {{{
	FUNCTION( str_trim, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_trim( STRING a )" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) ); 

		btrimws ( string_1 ); 

		RETURN_STRING( bdata( string_1 ) );
    }
// }}}
 
/******************************************************************************
** str_cformat
**   use BString::extern bstring bformat (const char * fmt, ...);
**  Takes the same parameters as printf (), but rather than outputting 
**  results to stdio, it forms a bstring which contains what would have been 
**  output. Note that if there is an early generation of a '\0' character, 
**  the bstring will be truncated to this end point.
******************************************************************************/
// {{{
	FUNCTION( str_cformat, STRING, "S", 1, 1, 255, 
    "USAGE: STRING str_cformat( STRING a, STRING|REAL|INTEGER b )" )
	{
		RETURN_STRING( bdata( bformat ( ARGV(0), ARGV(1) ) ) );
    }
// }}}
 
/******************************************************************************
** str_len
**   use BString::macro int blength (const_bstring b);
**  Returns the length of the bstring. If the bstring is NULL, the length 
**  returned is 0.
******************************************************************************/
// {{{
	FUNCTION( str_len, LONG, "S", 1, 1, 255, 
    "USAGE: INT str_len( STRING a )" )
	{
		RETURN_LONG( blength ( bfromcstr ( ARGV(0) ) ) );
    }
// }}}
 
/******************************************************************************
** str_charat
**  use BString::macro char bchar (const_bstring b, int p);
**  Returns the p'th character of the bstring b.
******************************************************************************/
// {{{
	FUNCTION( str_charat, STRING, "S;I", 2, 1, 255, 
    "USAGE: STRING str_charat( STRING a, INT pos )" )
	{
		bstring       string_1 = bfromcstr ( ARGV(0) );
		unsigned char pos      = *((unsigned char*) ARGV(1) ); 

		RETURN_STRING( (char*) bchar ( string_1, pos ) ) ;
    }
// }}}

/* ____ENDOFFILE____ */