Diff for /parser3/src/classes/math.C between versions 1.16 and 1.24.2.6

version 1.16, 2002/03/27 15:30:34 version 1.24.2.6, 2003/02/06 11:56:31
Line 1 Line 1
 /** @file  /** @file
         Parser: @b math parser class.          Parser: @b math parser class.
   
         Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)          Copyright(c) 2001-2003 ArtLebedev Group(http://www.artlebedev.com)
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru>(http://paf.design.ru)
   
         $Id$  
 */  */
   
   static const char* IDENT_MATH_C="$Date$";
   
   #include "pa_vmethod_frame.h"
   
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_vint.h"  #include "pa_vint.h"
 #include "pa_vmath.h"  #include "pa_vmath.h"
 #include "pa_request.h"  #include "pa_request.h"
   #include "pa_md5.h"
   
 #ifdef WIN32  #ifdef WIN32
   // for threadID
 #       include <windows.h>  #       include <windows.h>
 #endif  #endif
   
   #ifdef HAVE_CRYPT_H
   #include <crypt.h>
   #endif
   
 // defines  // defines
   
 #define PI 3.1415926535  #define MAX_SALT 8
 #define MATH_CLASS_NAME "math"  
   
 // class  // class
   
 class MMath : public Methoded {  class MMath : public Methoded {
 public:  public:
         MMath(Pool& pool);          MMath();
         void configure_admin(Request& r);          void configure_admin(Request& r);
   
 public: // Methoded  public: // Methoded
         bool used_directly() { return false; }          bool used_directly() { return false; }
 };  };
   
   // global variables
   
   VStateless_classPtr math_base_class(new MMath);
   
 // methods  // methods
 static unsigned int randomizer=0;  static unsigned int randomizer=0;
 static void _random(Request& r, const String& method_name, MethodParams *params) {  static inline int _random(uint top) {
           return (int)(((double)((randomizer=rand())% RAND_MAX)) / RAND_MAX * top );
   }
   static void _random(Request& r, StringPtr method_name, MethodParams& params) {
         Pool& pool=r.pool();          Pool& pool=r.pool();
   
         Value& range=params->as_junction(0, "range must be expression");          ValuePtr range=params.as_junction(0, "range must be expression");
     double top=r.process(range).as_double();      double top=r.process_to_value(range)->as_double();
     if(top<=1)      if(top<=1)
                 throw Exception("parser.runtime",                  throw Exception("parser.runtime",
                         &method_name,                          method_name,
                         "top must be above 1 (%g)", top);                          "top must be above 1(%g)", top);
                   
         Value& result=*new(pool) VInt(pool, (int)(          r.write_no_lang(ValuePtr(new VInt(_random(uint(top)))));
                 ((double)((randomizer=rand())% RAND_MAX)) / RAND_MAX * uint(top) ));  
         result.set_name(method_name);  
         r.write_no_lang(result);  
 }  }
   
   
 typedef double (*math1_func_ptr)(double);  typedef double(*math1_func_ptr)(double);
 static double frac(double param) { return param-trunc(param); }  static double frac(double param) { return param-trunc(param); }
 static double degrees(double param) { return param /PI *180; }  static double degrees(double param) { return param /PI *180; }
 static double radians(double param) { return param /180 *PI; }  static double radians(double param) { return param /180 *PI; }
   
 static void math1(Request& r,   static void math1(Request& r, 
                                   const String& method_name, MethodParams *params,                                    StringPtr method_name, MethodParams& params,
                                   math1_func_ptr func) {                                    math1_func_ptr func) {
         Pool& pool=r.pool();          ValuePtr param=params.as_junction(0, "parameter must be expression");
         Value& param=params->as_junction(0, "parameter must be expression");  
   
         Value& result=*new(pool) VDouble(pool, (*func)(r.process(param).as_double()));          double result=func(r.process_to_value(param)->as_double());
         result.set_name(method_name);          r.write_no_lang(ValuePtr(new VDouble(result)));
         r.write_no_lang(result);  
 }  }
   
 #define MATH1(name) \  #define MATH1(name) \
         static void _##name(Request& r, const String& method_name, MethodParams *params) {\          static void _##name(Request& r, StringPtr method_name, MethodParams& params) {\
                 math1(r, method_name, params, &name);\                  math1(r, method_name, params, &name);\
         }          }
 #define MATH1P(name_parser, name_c) \  #define MATH1P(name_parser, name_c) \
         static void _##name_parser(Request& r, const String& method_name, MethodParams *params) {\          static void _##name_parser(Request& r, StringPtr method_name, MethodParams& params) {\
                 math1(r, method_name, params, &name_c);\                  math1(r, method_name, params, &name_c);\
         }          }
 MATH1(round);   MATH1(floor);   MATH1P(ceiling, ceil);  MATH1(round);   MATH1(floor);   MATH1P(ceiling, ceil);
Line 88  MATH1(sqrt); Line 97  MATH1(sqrt);
   
 typedef double (*math2_func_ptr)(double, double);  typedef double (*math2_func_ptr)(double, double);
 static void math2(Request& r,   static void math2(Request& r, 
                                   const String& method_name, MethodParams *params,                                    StringPtr method_name, MethodParams& params,
                                   math2_func_ptr func) {                                    math2_func_ptr func) {
         Pool& pool=r.pool();          ValuePtr a=params.as_junction(0, "parameter must be expression");
         Value& a=params->as_junction(0, "parameter must be expression");          ValuePtr b=params.as_junction(1, "parameter must be expression");
         Value& b=params->as_junction(1, "parameter must be expression");  
   
         Value& result=*new(pool) VDouble(pool, (*func)(          double result=func(
                 r.process(a).as_double(),                  r.process_to_value(a)->as_double(),
                 r.process(b).as_double()));                  r.process_to_value(b)->as_double());
         result.set_name(method_name);          r.write_no_lang(ValuePtr(new VDouble(result)));
         r.write_no_lang(result);  
 }  }
   
 #define MATH2(name) \  #define MATH2(name) \
         static void _##name(Request& r, const String& method_name, MethodParams *params) {\          static void _##name(Request& r, StringPtr method_name, MethodParams& params) {\
                 math2(r, method_name, params, &name);\                  math2(r, method_name, params, &name);\
         }          }
 MATH2(pow);  MATH2(pow);
   
   inline bool is_salt_body_char(int c) {
           return isalnum(c) || c == '.' || c=='/';
   }
   static size_t calc_prefix_size(const char* salt) {
           if(size_t salt_size=strlen(salt)) {
                   if(!is_salt_body_char(salt[0])) { // $...  {...
                           const char* cur=salt+1; // skip
                           while(is_salt_body_char(*cur++)) // ...$  ...}
                                   ;
                           return cur-salt;
                   } else
                           return 0;
           } else
                   return 0;
   }
   static void _crypt(Request& r, StringPtr method_name, MethodParams& params) {
           Pool& pool=r.pool();
           CharPtr password=params.as_string(0, "password must be string")->cstr();
           CharPtr maybe_bodyless_salt=params.as_string(1, "salt must be string")->cstr();
   
           size_t prefix_size=calc_prefix_size(maybe_bodyless_salt);
           const char* normal_salt;
           char normalize_buf[MAX_STRING];
           if(prefix_size==strlen(maybe_bodyless_salt)) { // bodyless?
                   strncpy(normalize_buf, maybe_bodyless_salt, MAX_STRING-MAX_SALT-1);
                   char *cur=normalize_buf+strlen(normalize_buf);
                   // sould add up MAX_SALT random chars
                   static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
                   "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                   for(int i=0; i<MAX_SALT; i++)
                           *cur++=itoa64[_random(64)];
                   *cur=0;
                   normal_salt=normalize_buf;
           } else
                   normal_salt=maybe_bodyless_salt;
   
       /* FreeBSD style MD5 string 
        */
       if(strncmp(normal_salt, PA_MD5PW_ID, PA_MD5PW_IDLEN) == 0) {
                   const size_t sample_size=120;
                   char *sample_buf=new(pool) char[sample_size];
                   pa_MD5Encode((const unsigned char *)password.get(),
                                   (const unsigned char *)normal_salt, sample_buf, sample_size);
                   String sample(sample_buf);
                   r.write_pass_lang(sample);
       } else {
   #ifdef HAVE_CRYPT
                   const char* static_sample_buf=crypt(password, normal_salt);
                   if(!static_sample_buf  // nothing generated
                           || !static_sample_buf[0] // generated nothing
                           || strncmp(static_sample_buf, normal_salt, prefix_size)!=0) // salt prefix not preserved
                           throw Exception("parser.runtime",
                                   method_name,
                                   "on this platform does not support '%.*s' salt prefix", prefix_size, normal_salt);
                   
                   r.write_pass_lang(StringPtr(new String(pool.copy(static_sample_buf))));
   #else
                   throw Exception("parser.runtime",
                           method_name,
                           "salt must start with '" PA_MD5PW_ID "'");
   #endif
           }
   }
   
 // constructor  // constructor
   
 MMath::MMath(Pool& apool) : Methoded(apool) {  MMath::MMath(): Methoded("math") {
         set_name(*NEW String(pool(), MATH_CLASS_NAME));  
           
         // ^FUNC(expr)            // ^FUNC(expr)  
 #define ADD1(name) \  #define ADD1(name) \
         add_native_method(#name, Method::CT_STATIC, _##name, 1, 1)          add_native_method(#name, Method::CT_STATIC, _##name, 1, 1)
Line 133  MMath::MMath(Pool& apool) : Methoded(apo Line 202  MMath::MMath(Pool& apool) : Methoded(apo
         // ^pow(x;y)          // ^pow(x;y)
         ADD2(pow);          ADD2(pow);
   
           // ^crypt[password;salt]
           ADD2(crypt);
 }  }
   
 // in MSVC each thread has it's own pseudo-random sequence  // in MSVC each thread has it's own pseudo-random sequence
Line 147  void MMath::configure_admin(Request&) { Line 218  void MMath::configure_admin(Request&) {
 #else  #else
                 ^ getpid()                  ^ getpid()
 #endif  #endif
                 ^ (unsigned int)time(NULL)                  ^(unsigned int)time(NULL)
         );          );
         if(!randomizer)          if(!randomizer)
                 randomizer=rand();                  randomizer=rand();
 }  }
   
 // global variables  
   
 Methoded *math_base_class;  
 Hash *math_consts;  
   
 // creator  
   
 Methoded *MMath_create(Pool& pool) {  
         math_consts=new(pool) Hash(pool);  
         math_consts->put(  
                 *new(pool) String(pool, "PI"),   
                 new(pool) VDouble(pool, PI));  
   
         return math_base_class=new(pool) MMath(pool);  
 }  

Removed from v.1.16  
changed lines
  Added in v.1.24.2.6


E-mail: