--- parser3/src/classes/math.C 2009/01/25 01:58:17 1.55 +++ parser3/src/classes/math.C 2012/05/23 20:51:40 1.60 @@ -1,15 +1,13 @@ /** @file Parser: @b math parser class. - Copyright(c) 2001-2005 ArtLebedev Group(http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) portions from gen_uuid.c, Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. */ -static const char * const IDENT_MATH_C="$Date: 2009/01/25 01:58:17 $"; - #include "pa_vmethod_frame.h" #include "pa_common.h" #include "pa_vint.h" @@ -32,6 +30,8 @@ static const char * const IDENT_MATH_C=" extern char *crypt(const char* , const char* ); #endif +volatile const char * IDENT_MATH_C="$Id: math.C,v 1.60 2012/05/23 20:51:40 moko Exp $"; + // defines #define MAX_SALT 8 @@ -314,7 +314,7 @@ static void _sha1(Request& r, MethodPara if(!SHA1Result(&c)) throw Exception (PARSER_RUNTIME, 0, "Can not compute SHA1"); - const size_t bufsize=40+/*zero-teminator*/+1/*for faulty snprintfs*/; + const size_t bufsize=40+1/*zero-teminator*/+1/*for faulty snprintfs*/; char* cstr=new(PointerFreeGC) char[bufsize]; snprintf(cstr, bufsize, @@ -357,6 +357,60 @@ static void _crc32(Request& r, MethodPar r.write_no_lang(*new VInt(pa_crc32(string, strlen(string)))); } +static void toBase(unsigned long value, unsigned int base, char*& ptr){ + static const char* hex="0123456789ABCDEF"; + int rest = value % base; + if(value >= base) + toBase( (value-rest)/base, base, ptr); + *ptr++=(char)hex[rest]; +} + +static void _convert(Request& r, MethodParams& params) { + const char *str=params.as_string(0, PARAMETER_MUST_BE_STRING).cstr(); + + int base_from=params.as_int(1, "base from must be integer", r); + if(base_from < 2 || base_from > 16) + throw Exception(PARSER_RUNTIME, 0, "base from must be an integer from 2 to 16"); + + int base_to=params.as_int(2, "base to must be integer", r); + if(base_to < 2 || base_to > 16) + throw Exception(PARSER_RUNTIME, 0, "base to must be an integer from 2 to 16"); + + while(*str && isspace((unsigned char)*str)) + str++; + + if(!*str) + return; + + char *error_pos; + + bool negative=false; + if(str[0]=='-') { + negative=true; + str++; + } else if(str[0]=='+') { + str++; + } + + errno=0; + unsigned long value=strtoul(str, &error_pos, base_from); + if(errno==ERANGE) + throw Exception("number.format", 0, "'%s' is out of range (int)", str); + + while(char c=*error_pos++) + if(!isspace((unsigned char)c)) + throw Exception("number.format", 0, "'%s' is invalid number (int)", str); + + char result_cstr[sizeof(unsigned long)*8+1/*minus for negative number*/+1/*terminator*/]; + char* ptr=result_cstr; + if(negative) + *ptr++='-'; + + toBase(value, base_to, ptr); + *ptr=0; + r.write_pass_lang(*new String(pa_strdup(result_cstr))); +} + // constructor MMath::MMath(): Methoded("math") { @@ -399,4 +453,7 @@ MMath::MMath(): Methoded("math") { // ^math:uid64[] ADD0(uid64); + + // ^math:convert[number](base-from;base-to) + add_native_method("convert", Method::CT_STATIC, _convert, 3, 3); }