Index: cpp/frams/param/param.cpp
===================================================================
--- cpp/frams/param/param.cpp	(revision 324)
+++ cpp/frams/param/param.cpp	(revision 325)
@@ -37,8 +37,6 @@
 static const char *strchrlimit(const char *t, int ch, const char *limit)
 {
-	int n = (int)(limit - t);
-	for (; (n > 0) && *t; t++, n--)
-		if (*t == ch) return t;
-	return 0;
+	if (limit<t) return NULL;
+	return (const char*)memchr((const void*)t,ch,limit-t);
 }
 
@@ -1000,9 +998,9 @@
 		//                     ^ ^-t (after)           ^ ^_next_field
 		//                     \_t (before)            \_field_end
-		while (strchr(" \n\r\t", *t)) if (t < end) t++; else return fields_loaded;
+		while (isspace(*t)) if (t < end) t++; else return fields_loaded;
 
 		field_end = strchrlimit(t, ',', end); if (!field_end) field_end = end;
 		next_field=field_end;
-		while ((field_end>t) && strchr(" \t",field_end[-1])) field_end--;
+		while ((field_end>t) && isblank(field_end[-1])) field_end--;
 		quote = strchrlimit(t, '\"', field_end);
 		if (quote)
Index: cpp/frams/util/extvalue.cpp
===================================================================
--- cpp/frams/util/extvalue.cpp	(revision 324)
+++ cpp/frams/util/extvalue.cpp	(revision 325)
@@ -12,4 +12,5 @@
 #include <common/nonstd_math.h>
 #include <common/Convert.h>
+#include <climits>
 
 #ifndef NO_BARRIER
@@ -609,36 +610,45 @@
 }
 
-paInt ExtValue::getInt(const char* s)
-{
-if ((s[0]=='0')&&(s[1]=='x'))
-	{
-	paInt val;
-	sscanf(s+2,PA_INT_SCANF_X,&val);
-	return val;
-	}
-else
-	{
-	if (strchr(s,'e')||(strchr(s,'E')))
-		return (paInt)atof(s);
-	else
-		return atoi(s);
-	}
+bool ExtValue::parseInt(const char* s, paInt &result, bool strict)
+{
+	ExtValue tmp;
+	const char* after = tmp.parseNumber(s, strict ? TInt : TUnknown);
+	if (after == NULL) return false;
+	if (after[0] != 0) return false;
+	result = tmp.getInt();
+	return true;
+}
+
+bool ExtValue::parseDouble(const char* s, double &result)
+{
+	ExtValue tmp;
+	const char* after = tmp.parseNumber(s, TDouble);
+	if (after == NULL) return false;
+	if (after[0] != 0) return false;
+	result = tmp.getDouble();
+	return true;
+}
+
+paInt ExtValue::getInt(const char* s,bool strict)
+{
+	paInt result;
+	if (parseInt(s, result, strict))
+		return result;
+	FMprintf("ExtValue", "getInt", FMLV_ERROR, "Could not parse '%s'%s", s, strict?" (strict)":"");
+	return 0;
 }
 
 double ExtValue::getDouble(const char* s)
 {
-if ((s[0]=='0')&&(s[1]=='x'))
-	{
-	paInt val;
-	sscanf(s+2,PA_INT_SCANF_X,&val);
-	return val;
-	}
-else
-	return atof(s);
+	double result;
+	if (parseDouble(s, result))
+		return result;
+	FMprintf("ExtValue", "getDouble", FMLV_ERROR, "Could not parse '%s'", s);
+	return 0;
 }
 
 paInt ExtValue::getInt() const
 {
-switch(type)
+	switch (type)
 	{
 	case TInt: return idata();
@@ -646,14 +656,14 @@
 	case TString: return getInt((const char*)sdata());
 	case TObj:
-		FMprintf("ExtValue","getInt",FMLV_WARN,"Getting integer value from object reference (%s)",(const char*)getString());
+		FMprintf("ExtValue", "getInt", FMLV_WARN, "Getting integer value from object reference (%s)", (const char*)getString());
 		return (paInt)(intptr_t)odata().param;
 	default:;
 	}
-return 0;
+	return 0;
 }
 
 double ExtValue::getDouble() const
 {
-switch(type)
+	switch (type)
 	{
 	case TDouble: return ddata();
@@ -661,13 +671,14 @@
 	case TString: return getDouble((const char*)sdata());
 	case TObj:
-		FMprintf("ExtValue","getDouble",FMLV_WARN,"Getting floating point value from object reference (%s)",(const char*)getString());
+		FMprintf("ExtValue", "getDouble", FMLV_WARN, "Getting floating point value from object reference (%s)", (const char*)getString());
 		return (double)(intptr_t)odata().param;
 	default:;
 	}
-return 0.0;
-}
+	return 0.0;
+}
+
 SString ExtValue::getString() const
 {
-switch(type)
+	switch (type)
 	{
 	case TString: return sdata();
@@ -682,7 +693,7 @@
 const SString* ExtValue::getStringPtr() const
 {
-if (type==TString)
-	return &sdata();
-return NULL;
+	if (type == TString)
+		return &sdata();
+	return NULL;
 }
 
@@ -710,39 +721,52 @@
 }
 
-//returns the first character after the parsed number or NULL if not a number
-const char* ExtValue::parseNumber(const char* in)
-{
-if (isdigit(*in)||((*in=='-')&&(isdigit(in[1]))))
-	{
-	const char* p=in;
-	if (*p=='-') p++;
-	while(isdigit(*p)) p++;
-	bool fp=false;
-	if ((*p=='.') && isdigit(p[1]))
-		{
-		p++;
-		while(isdigit(*p)) p++;
-		fp=true;
-		}
-	if (((*p=='e')||(*p=='E')) && (isdigit(p[1]) || (((p[1]=='-') || (p[1]=='+')) && isdigit(p[2]))))
-		{
-		p++;
-		if ((*p=='-')||(*p=='+')) p++;
-		while(isdigit(*p)) p++;
-		fp=true;
-		}
-
-	if (fp)
-		{
-		setDouble(atof(in));
-		return p;
-		}
-	else
-		{
-		setInt(atoi(in));
-		return p;
-		}
-	}
-return NULL;
+/// returns the first character after the parsed number, or NULL if not a number
+/// @param strict_type = restrict the allowed return value (TUnknown = unrestricted)
+const char* ExtValue::parseNumber(const char* in, ExtPType strict_type)
+{
+	char* after;
+	if (in == NULL) return NULL;
+	if (in[0] == 0) return NULL;
+	while (isspace(*in)) in++;
+	bool minus = false;
+	if (((in[0] == '0') && (in[1] == 'x'))
+		|| (((minus = (in[0] == '-')) && (in[1] == '0') && (in[2] == 'x'))))
+	{
+		in += minus ? 3 : 2;
+		if (isspace(*in)) return NULL;
+		errno = 0;
+		unsigned long intvalue = strtoul(in, &after, 16);
+		if ((after > in) && (errno == 0) && (intvalue <= 0xffffffff))
+		{
+			if (strict_type == TDouble)
+				setDouble(minus ? -(double)intvalue : (double)intvalue);
+			else
+				setInt(minus ? -intvalue : intvalue);
+			return after;
+		}
+		else
+			return NULL;
+	}
+
+	errno = 0;
+	double fpvalue = strtod(in, &after);
+	if ((after > in) && (errno == 0))
+	{
+		if (strict_type != TDouble)
+		{
+			if ((memchr(in, '.', after - in) == NULL) && (memchr(in, 'e', after - in) == NULL) && (memchr(in, 'E', after - in) == NULL) // no "special" characters
+				&& (fpvalue == floor(fpvalue)) // value is integer
+				&& (fpvalue >= INT_MIN) && (fpvalue <= INT_MAX)) // within limits
+			{
+				setInt(fpvalue);
+				return after;
+			}
+			else if (strict_type == TInt)
+				return NULL;
+		}
+		setDouble(fpvalue);
+		return after;
+	}
+	return NULL;
 }
 
@@ -858,5 +882,5 @@
 	in++;
 	ExtValue ref;
-	ret=ref.parseNumber(in);
+	ret=ref.parseNumber(in,TInt);
 	if (ret && (ref.getType()==TInt))
 		{
Index: cpp/frams/util/extvalue.h
===================================================================
--- cpp/frams/util/extvalue.h	(revision 324)
+++ cpp/frams/util/extvalue.h	(revision 325)
@@ -12,86 +12,92 @@
 
 #define EXTVALUEUNION
-template <int A,int B> struct CompileTimeMax {enum {val=A>B?A:B}; };
+template <int A, int B> struct CompileTimeMax { enum { val = A > B ? A : B }; };
 #define EXTVALUEUNIONSIZE CompileTimeMax<sizeof(ExtObject),sizeof(SString)>::val
 
 enum ExtPType
-{TUnknown=0,TInt,TDouble,TString,TObj,TInvalid};
+{
+	TUnknown = 0, TInt, TDouble, TString, TObj, TInvalid
+};
 
 /**
    destructable object
- */
+   */
 class DestrBase
 {
 public:
-int refcount;
-DestrBase():refcount(0) {}
-void incref() {refcount++;}
-void decref() {refcount--; if (refcount==0) delete this;}
-virtual ~DestrBase() {}
+	int refcount;
+	DestrBase() :refcount(0) {}
+	void incref() { refcount++; }
+	void decref() { refcount--; if (refcount == 0) delete this; }
+	virtual ~DestrBase() {}
 };
 
 /**
    object reference.
- */
+   */
 class ExtObject
 {
-int subtype;                    //< 0/1=Generic/DPC Object,  0/2=Standalone/Shared Param
-void incref() const;
-void decref() const;
-  public:
-union { void* object;           //< generic object, will use param
-DestrBase *dbobject;};  //< object with refcounting, will be deleted if refcount goes to 0
-union { Param* param;           //< if object!=0
-	ParamInterface *paraminterface;}; //< if object==0
-
-void copyFrom(const ExtObject& src)  {subtype=src.subtype;object=src.object;param=src.param;}
-
-void* operator new(size_t s, void* mem) {return mem;}
+	int subtype;                    //< 0/1=Generic/DPC Object,  0/2=Standalone/Shared Param
+	void incref() const;
+	void decref() const;
+public:
+	union {
+		void* object;           //< generic object, will use param
+		DestrBase *dbobject;	//< object with refcounting, will be deleted if refcount goes to 0
+	};
+	union {
+		Param* param;           //< if object!=0
+		ParamInterface *paraminterface; //< if object==0
+	};
+
+	void copyFrom(const ExtObject& src)  { subtype = src.subtype; object = src.object; param = src.param; }
+
+	void* operator new(size_t s, void* mem){ return mem; }
 #ifdef _MSC_VER
-void operator delete(void* mem,void* t) {}
-#endif
-void* operator new(size_t s) {return malloc(sizeof(ExtObject));}
-void operator delete(void* mem) {free(mem);}
-///@param tmp_param can be used for temporary storage, the result ParamInterface* is only valid for as long as tmp_param is valid
-ParamInterface *getParamInterface(Param &tmp_param) const  {if(subtype&2){tmp_param.setParamTab(param->getParamTab());tmp_param.select(object);return &tmp_param;} return paraminterface;}
-const char* interfaceName() const {if (isEmpty()) return "Empty"; return (subtype&2)?param->getName():paraminterface->getName();}
-bool matchesInterfaceName(ParamInterface* pi) const {return !strcmp(interfaceName(),pi->getName());}
-void* getTarget() const {return (subtype&1)?dbobject:object;}
-void* getTarget(const char* classname, bool through_barrier=true, bool warn=true) const;
-void setEmpty() {decref();subtype=0;param=NULL;object=NULL;}
-int isEmpty() const {return !param;}
-static const ExtObject& empty() { static const ExtObject& e((ParamInterface*)NULL); return e; }
-ExtObject(const ExtObject& src)      {src.incref();copyFrom(src);}
-void operator=(const ExtObject& src) {src.incref();decref();copyFrom(src);}
-bool makeUnique();//< @return false if nothing has changed
-
-bool operator==(const ExtObject& src) const;
-
-SString toString() const;
-SString serialize_inner() const;
-SString serialize() const;
-
-ExtObject(Param *p,void *o):subtype(2),object(o),param(p){}
-ExtObject(ParamInterface *p=0):subtype(0),object(0),paraminterface(p){}
-ExtObject(Param *p,DestrBase *o):subtype(1+2),dbobject(o),param(p){incref();}
-ExtObject(ParamInterface *p,DestrBase *o):subtype(1),dbobject(o),paraminterface(p){incref();}
-
-~ExtObject(){decref();}
-
-class Serialization
-{
-std::vector<ExtObject> refs;
-int level;
-  public:
-Serialization():level(0) {}
-void begin();
-void end();
-int add(const ExtObject& o);
-void replace(const ExtObject& o,const ExtObject& other);
-void remove(const ExtObject& o);
-const ExtObject* get(int ref);
-};
-
-static THREAD_LOCAL_DECL(Serialization,serialization);
+		void operator delete(void* mem, void* t) {}
+#endif
+	void* operator new(size_t s){ return malloc(sizeof(ExtObject)); }
+	void operator delete(void* mem) { free(mem); }
+	///@param tmp_param can be used for temporary storage, the result ParamInterface* is only valid for as long as tmp_param is valid
+	ParamInterface *getParamInterface(Param &tmp_param) const  { if (subtype & 2){ tmp_param.setParamTab(param->getParamTab()); tmp_param.select(object); return &tmp_param; } return paraminterface; }
+	const char* interfaceName() const { if (isEmpty()) return "Empty"; return (subtype & 2) ? param->getName() : paraminterface->getName(); }
+	bool matchesInterfaceName(ParamInterface* pi) const { return !strcmp(interfaceName(), pi->getName()); }
+	void* getTarget() const { return (subtype & 1) ? dbobject : object; }
+	void* getTarget(const char* classname, bool through_barrier = true, bool warn = true) const;
+	void setEmpty() { decref(); subtype = 0; param = NULL; object = NULL; }
+	int isEmpty() const { return !param; }
+	static const ExtObject& empty() { static const ExtObject& e((ParamInterface*)NULL); return e; }
+	ExtObject(const ExtObject& src)      { src.incref(); copyFrom(src); }
+	void operator=(const ExtObject& src) { src.incref(); decref(); copyFrom(src); }
+	bool makeUnique();//< @return false if nothing has changed
+
+	bool operator==(const ExtObject& src) const;
+
+	SString toString() const;
+	SString serialize_inner() const;
+	SString serialize() const;
+
+	ExtObject(Param *p, void *o) :subtype(2), object(o), param(p){}
+	ExtObject(ParamInterface *p = 0) :subtype(0), object(0), paraminterface(p){}
+	ExtObject(Param *p, DestrBase *o) :subtype(1 + 2), dbobject(o), param(p){ incref(); }
+	ExtObject(ParamInterface *p, DestrBase *o) :subtype(1), dbobject(o), paraminterface(p){ incref(); }
+
+	~ExtObject(){ decref(); }
+
+	class Serialization
+	{
+		std::vector<ExtObject> refs;
+		int level;
+	public:
+		Serialization() :level(0) {}
+		void begin();
+		void end();
+		int add(const ExtObject& o);
+		void replace(const ExtObject& o, const ExtObject& other);
+		void remove(const ExtObject& o);
+		const ExtObject* get(int ref);
+	};
+
+	static THREAD_LOCAL_DECL(Serialization, serialization);
 };
 
@@ -99,97 +105,103 @@
 {
 public:
-ExtPType type;
+	ExtPType type;
 #ifdef EXTVALUEUNION
-long data[(EXTVALUEUNIONSIZE+sizeof(long)-1)/sizeof(long)];
-paInt& idata() const {return (paInt&)data[0];};
-double& ddata() const {return *(double*)data;};
-ExtObject& odata() const {return *(ExtObject*)data;};
-SString& sdata() const {return *(SString*)data;};
+	long data[(EXTVALUEUNIONSIZE + sizeof(long) - 1) / sizeof(long)];
+	paInt& idata() const { return (paInt&)data[0]; };
+	double& ddata() const { return *(double*)data; };
+	ExtObject& odata() const { return *(ExtObject*)data; };
+	SString& sdata() const { return *(SString*)data; };
 #else
-union {
-paInt i;
-double d;
-SString *s;
-ExtObject *o;
-};
-paInt& idata() const {return (paInt&)i;};
-double& ddata() const {return (double&)d;};
-ExtObject& odata() const {return *o;};
-SString& sdata() const {return *s;};
-#endif
-
-void* operator new(size_t s, void* mem) {return mem;}
-void* operator new(size_t s) {return ::operator new(s);}
-
-ExtValue():type(TUnknown){}
-~ExtValue() {setEmpty();}
-ExtValue(paInt v) {seti(v);}
-ExtValue(double v) {setd(v);}
-ExtValue(const SString &v) {sets(v);}
-ExtValue(const ExtObject &srco) {seto(srco);}
-static ExtValue invalid() {ExtValue v; v.setInvalid(); return v;}
-static const ExtValue& empty() { static const ExtValue v; return v; }
-int compare(const ExtValue& src) const;
-int operator==(const ExtValue& src) const;
-void operator+=(const ExtValue& src);
-void operator-=(const ExtValue& src);
-void operator*=(const ExtValue& src);
-void operator/=(const ExtValue& src);
-void operator%=(const ExtValue& src);
-void operator=(const ExtValue& src)
-	{setr(src);}
-ExtValue(const ExtValue& src)
-	:type(TUnknown) {set(src);}
-void setEmpty();
-void setInvalid() {setEmpty();type=TInvalid;}
-bool makeUnique() {return (type==TObj) && odata().makeUnique();} //< @return false if nothing has changed
-ExtPType getType() {return type;}
-void *getObjectTarget(const char* classname,bool warn=true) const;
-void setInt(paInt v) {if (type!=TInt) setri(v); else idata()=v;}
-void setDouble(double v) {if (type!=TDouble) setrd(v); else ddata()=v;}
-void setString(const SString &v) {if (type!=TString) setrs(v); else sdata()=v;}
-void setObject(const ExtObject &src) {if (type!=TObj) setro(src); else odata()=src;}
-static paInt getInt(const char* s);
-static double getDouble(const char* s);
-paInt getInt() const;
-double getDouble() const;
-SString getString() const;
-const SString* getStringPtr() const;//< @return pointer to the internal sstring object or NULL if the current type is not string
-SString serialize() const;
-ExtObject getObject() const;
-bool isNull() const {return (type==TUnknown)||((type==TObj)&&odata().isEmpty());}
-SString typeDescription() const;//< @return human readable type name (used in error messages)
-const char* parseNumber(const char* in);
-const char* deserialize(const char* in);//< @return first character after the succesfully parsed string or NULL if failed
-const char* deserialize_inner(const char* in);
-static ParamInterface *findDeserializableClass(const char* name);
-static PtrListTempl<ParamInterface*> &getDeserializableClasses();
-template<typename T> class AddDeserializable
-{
-  public:
-AddDeserializable() {ExtValue::getDeserializableClasses()+=&T::getStaticParam();}
-};
-
-static SString format(SString& fmt,const ExtValue **values,int count);
-
-ExtValue getExtType();
-
-  private: // setrx - release and set, setx - assume released
-void setr(const ExtValue& src){setEmpty();set(src);}
-void set(const ExtValue& src);
-void setri(paInt v) {setEmpty();seti(v);}
-void setrd(double v) {setEmpty();setd(v);}
-void seti(paInt v) {type=TInt;idata()=v;}
-void setd(double v) {type=TDouble;ddata()=v;}
+	union {
+		paInt i;
+		double d;
+		SString *s;
+		ExtObject *o;
+	};
+	paInt& idata() const {return (paInt&)i;};
+	double& ddata() const {return (double&)d;};
+	ExtObject& odata() const {return *o;};
+	SString& sdata() const {return *s;};
+#endif
+
+	void* operator new(size_t s, void* mem){ return mem; }
+	void* operator new(size_t s){ return ::operator new(s); }
+
+		ExtValue() :type(TUnknown){}
+	~ExtValue() { setEmpty(); }
+	ExtValue(paInt v) { seti(v); }
+	ExtValue(double v) { setd(v); }
+	ExtValue(const SString &v) { sets(v); }
+	ExtValue(const ExtObject &srco) { seto(srco); }
+	static ExtValue invalid() { ExtValue v; v.setInvalid(); return v; }
+	static const ExtValue& empty() { static const ExtValue v; return v; }
+	int compare(const ExtValue& src) const;
+	int operator==(const ExtValue& src) const;
+	void operator+=(const ExtValue& src);
+	void operator-=(const ExtValue& src);
+	void operator*=(const ExtValue& src);
+	void operator/=(const ExtValue& src);
+	void operator%=(const ExtValue& src);
+	void operator=(const ExtValue& src)
+	{
+		setr(src);
+	}
+	ExtValue(const ExtValue& src)
+		:type(TUnknown) {
+		set(src);
+	}
+	void setEmpty();
+	void setInvalid() { setEmpty(); type = TInvalid; }
+	bool makeUnique() { return (type == TObj) && odata().makeUnique(); } //< @return false if nothing has changed
+	ExtPType getType() { return type; }
+	void *getObjectTarget(const char* classname, bool warn = true) const;
+	void setInt(paInt v) { if (type != TInt) setri(v); else idata() = v; }
+	void setDouble(double v) { if (type != TDouble) setrd(v); else ddata() = v; }
+	void setString(const SString &v) { if (type != TString) setrs(v); else sdata() = v; }
+	void setObject(const ExtObject &src) { if (type != TObj) setro(src); else odata() = src; }
+	static bool parseInt(const char* s, paInt &result, bool strict = false);
+	static bool parseDouble(const char* s, double &result);
+	static paInt getInt(const char* s, bool strict = false);//< @param strict=true will fail on floating point
+	static double getDouble(const char* s);
+	paInt getInt() const;
+	double getDouble() const;
+	SString getString() const;
+	const SString* getStringPtr() const;//< @return pointer to the internal sstring object or NULL if the current type is not string
+	SString serialize() const;
+	ExtObject getObject() const;
+	bool isNull() const { return (type == TUnknown) || ((type == TObj) && odata().isEmpty()); }
+	SString typeDescription() const;//< @return human readable type name (used in error messages)
+	const char* parseNumber(const char* in, ExtPType strict_type = TUnknown);
+	const char* deserialize(const char* in);//< @return first character after the succesfully parsed string or NULL if failed
+	const char* deserialize_inner(const char* in);
+	static ParamInterface *findDeserializableClass(const char* name);
+	static PtrListTempl<ParamInterface*> &getDeserializableClasses();
+	template<typename T> class AddDeserializable
+	{
+	public:
+		AddDeserializable() { ExtValue::getDeserializableClasses() += &T::getStaticParam(); }
+	};
+
+	static SString format(SString& fmt, const ExtValue **values, int count);
+
+	ExtValue getExtType();
+
+private: // setrx - release and set, setx - assume released
+	void setr(const ExtValue& src){ setEmpty(); set(src); }
+	void set(const ExtValue& src);
+	void setri(paInt v) { setEmpty(); seti(v); }
+	void setrd(double v) { setEmpty(); setd(v); }
+	void seti(paInt v) { type = TInt; idata() = v; }
+	void setd(double v) { type = TDouble; ddata() = v; }
 #ifdef EXTVALUEUNION
-void setrs(const SString &v) {setEmpty();sets(v);}
-void setro(const ExtObject &src) {setEmpty();seto(src);}
-void sets(const SString &v) {type=TString;new(data) SString(v);}
-void seto(const ExtObject &src) {type=TObj;new(data) ExtObject(src);}
+	void setrs(const SString &v) { setEmpty(); sets(v); }
+	void setro(const ExtObject &src) { setEmpty(); seto(src); }
+	void sets(const SString &v) { type = TString; new(data)SString(v); }
+	void seto(const ExtObject &src) { type = TObj; new(data)ExtObject(src); }
 #else
-void setrs(const SString &v) {setEmpty();sets(v);}
-void setro(const ExtObject &src) {setEmpty();seto(src);}
-void sets(const SString &v) {type=TString;s=new SString(v);}
-void seto(const ExtObject &src) {type=TObj;o=new ExtObject(src);}
+	void setrs(const SString &v) {setEmpty();sets(v);}
+	void setro(const ExtObject &src) {setEmpty();seto(src);}
+	void sets(const SString &v) {type=TString;s=new SString(v);}
+	void seto(const ExtObject &src) {type=TObj;o=new ExtObject(src);}
 #endif
 
