(1) boost variant size =20, JSONValue variant=6
(2) v.which() = index
(3) using =typedef and decltype is to get typeinfo
(4) (n,N) recursion, Compile constant N=0, N+1 force n recurs 1 more time to get to n=N
(5) have not see example Max,Max get called
#pragma once
#include <string>
#include <boost\variant.hpp>
#include "render.hpp"
#include "get2.hpp"
using namespace std;
template<size_t N, size_t Max>
struct apply_at
{
template<typename R, typename T, typename F, typename...Fs>
static string apply(T&& t, size_t n, F&& f, Fs&&... fs)
{
if (n == N)
{
return forward<F>(f)(get2<N>(boost::forward<T>(t)));
}
else
{
return apply_at<N + 1, Max>::template apply<R, T, Fs...>(
boost::forward<T>(t),
n,
forward<Fs>(fs)...);
}
}
};
template<size_t Max>
struct apply_at<Max, Max>
{
template<typename R, typename T, typename...Fs>
static string apply(T, size_t, Fs...)
{
return R();
}
};
template<typename T,typename F, typename...Fs>
static string fold_at(T&& t, size_t n, F&& f, Fs&&... fs)
{
using R = decltype(f(get2<0>(t)));
return apply_at<0, sizeof...(Fs)+1>::template apply<R,T, F, Fs...>(
boost::forward<T>(t),
n,
forward<F>(f),
forward<Fs>(fs)...
);
};
template <typename... Ts, typename... Fs>
string fold(const boost::variant<Ts...>& v, Fs&&... fs)
{
// size boost::variant=60, JSONValue=6, so assert fail
//static_assert(sizeof...(Ts) == sizeof...(Fs), "# of fun and variant not matching.");
return fold_at(
v, v.which(), forward<Fs>(fs)...
);
};
Saturday, December 3, 2016
fold.cpp recursion with compile time constant
6 function of JSON render matching 6 type in JSON variant
#pragma once
#include <string>
#include <sstream>
#include "JSONWrapper.hpp"
#include "join.hpp"
#include "fold.hpp"
#include <iomanip>
using namespace std;
string render_bool(bool b) { return b ? "true" : "false"; }
string render_double(double d) { return to_string(d); }
string render_null(nullptr_t) { return "null"; }
string render_string(const string& s)
{
stringstream ss;
ss << std::quoted(s);
return ss.str();
}
string render_json_value(const JSONValue& jsv);
string render_object(const JSONObject& obj)
{
return string{ "[" }+
join(obj.begin(), obj.end(), string{ "." },
[](const JSONObject::value_type& jsv) {
return render_string(jsv.first) + ":" + render_json_value(jsv.second);
}) + "]";
}
string render_array(const JSONArray& a)
{
return string{ "[" }+
join(a.begin(), a.end(), string{ "," },
[](const JSONValue& jsv) {
return render_json_value(jsv);
}) + "]";
}
string render_json_value(const JSONValue& jsv)
{
return fold(jsv,
render_bool, render_double, render_string,
render_null, render_array, render_object);
}
join.cpp on iterator though vector and map
#pragma once
#include "JSONWrapper.hpp"
#include <functional>
#include <string>
using namespace std;
string join(JSONObject::const_iterator first, JSONObject::const_iterator last, string delimitor,
std::function<string(const JSONObject::value_type&)> func)
{
string ret = "";
for (;first!= last; first++)
{
ret += func(*first) + delimitor;
}
return ret;
}
string join(JSONArray::const_iterator first, JSONArray::const_iterator last, string delimitor,
std::function<string(const JSONValue&)> func)
{
string ret = "";
for (;first!= last; first++)
{
ret += func(*first) + delimitor;
}
return ret;
}
Friday, December 2, 2016
get boost variant value using template specialization on literal value
It seems C++17 will have get<0> and get<N> but boost does not have that yet.
boost only have get<type> and which=0,1,2,3,4,5
The following specialization can hack get<N> for now
#pragma once
#include <boost\variant\get.hpp>
#include "JSONWrapper.hpp"
#include <string>
template<int N>
auto get2(JSONValue jsv);
template<>
auto get2<0>(JSONValue jsv)
{
return boost::get<bool>(jsv);
}
template<>
auto get2<1>(JSONValue jsv)
{
return boost::get<double>(jsv);
}
template<>
auto get2<2>(JSONValue jsv)
{
return boost::get<std::string>(jsv);
}
template<>
auto get2<3>(JSONValue jsv)
{
return boost::get<nullptr_t>(jsv);
}
template<>
auto get2<4>(JSONValue jsv)
{
return boost::get<JSONArray>(jsv);
}
template<>
auto get2<5>(JSONValue jsv)
{
return boost::get<JSONObject>(jsv);
}
boost variant defines JSON Wrapper
Note operator JSONValue&() const meant jw.operator const JSONValue&() the same as jw as in
cout<<render_json_value(jw)<<endl;
#include <vector>
#include <map>
#include <boost\variant.hpp>
typedef decltype(nullptr) nullptr_t;
struct JSONWrapper;
using JSONArray = std::vector<JSONWrapper>;
typedef std::map<std::string, JSONArray> JSONObject;
using JSONValue = boost::variant<bool, double, std::string, nullptr_t, JSONArray, JSONObject>;
struct JSONWrapper {
JSONValue value;
operator JSONValue&() { return value; }
operator const JSONValue&() const { return value; }
};
Tuesday, November 22, 2016
Validate Two properties
to make sure one property change trigger the other property run validation logic,
must call OnVilidate Code into IDataErrorInfo type of logic in its property Setter
<TextBox Grid.Column="1" Text="{Binding ...,ValidatesOnDataErrors=True,NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextBoxWithValidationStyle}">
[MustBeGreaterLessThanAllowSuffix("TheOther", false, true, ErrorMessage = "Please specify ..")]
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class MustBeGreaterLessThanAllowSuffixAttribute : ValidationAttribute
{
public string CompareToPropertyName { get; private set; }
public bool Greater { get; private set; }
public bool IncludeEqual { get; private set; }
public object[] Values { get; private set; }
private static readonly char[] SUFFIXES = new char[4] { 'M', 'm', 'K', 'k' };
public MustBeGreaterLessThanAllowSuffixAttribute(string compareToPropertyName,bool greater,bool includeEqual, params object[] values)
{
CompareToPropertyName = compareToPropertyName;
Greater = greater;
IncludeEqual = includeEqual;
Values = values;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var compToProperty = validationContext.ObjectType.GetProperty(CompareToPropertyName);
var compToValue = compToProperty.GetValue(validationContext.ObjectInstance, null);
return VerifyValidGreaterThanCondition(value, compToValue) ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
private bool VerifyValidGreaterThanCondition(object value, object compToValue)
{
if (value == null || compToValue == null)
{
return true;
}
string valueNoSuffix = value.ToString().TrimEnd(SUFFIXES);
string compToValueNoSuffix = compToValue.ToString().TrimEnd(SUFFIXES);
double dValue, dCompToValue;
if (!double.TryParse(valueNoSuffix, out dValue) || !double.TryParse(compToValueNoSuffix, out dCompToValue))
{
return true;
}
var dValueMutiplied = dValue * GetMultiplier(value);
var dCompToValueMutiplied = dCompToValue * GetMultiplier(compToValue);
if (Greater)
{
return IncludeEqual ? dValueMutiplied >= dCompToValueMutiplied : dValueMutiplied > dCompToValueMutiplied;
}
return IncludeEqual ? dValueMutiplied <= dCompToValueMutiplied : dValueMutiplied < dCompToValueMutiplied;
}
private double GetMultiplier(object value)
{
if(value==null)
return 1.0;
char suffix = value.ToString().LastOrDefault();
switch (suffix)
{
case 'M':
case 'm':
return 1E6;
case 'K':
case 'k':
return 1E3;
}
return 1.0;
}
[CustomValidation(typeof(VegaTraderSettingValidator), "Check")]
using System.ComponentModel.DataAnnotations;
public class VegaTraderSettingValidator
{
public static ValidationResult Check(string s)
{
return ValidationResult.Success;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class MutualExclusiveDataEntryAttribute : ValidationAttribute
{
public string MutualExclusivePropertyName { get; private set; }
public MutualExclusiveDataEntryAttribute(string mutualExclusivePropertyName)
{
MutualExclusivePropertyName = mutualExclusivePropertyName;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var mutProperty = validationContext.ObjectType.GetProperty(MutualExclusivePropertyName);
if (mutProperty == null)
return ValidationResult.Success;
var mutValue = mutProperty.GetValue(validationContext.ObjectInstance, null);
return VerifyMutualExclsivity(value, mutValue) ? ValidationResult.Success : new ValidationResult(ErrorMessage);
}
private bool VerifyMutualExclsivity(object value, object mutValue)
{
if (value == null || mutValue == null)
return true;
if (!value.IsDefault() && !mutValue.IsDefault())
return false;
return true;
}
}
Saturday, November 19, 2016
Attached Property based TextBox RegEx mask
{ var localTxt = lastValidText; var proposedText = GetProposedText(tbInstance, e1.Text); if (!maskRegEx.IsMatch(proposedText)) { e1.Handled = true; } }; tbInstance.Loaded += (s, e1) => { if (maskRegEx.IsMatch(tbInstance.Text)) { lastValidText = tbInstance.Text; SetHasRegExMisMatch(tbInstance,false); } else { SetHasRegExMisMatch(tbInstance, true); } }; tbInstance.TextChanged += (s, e1) => { if (maskRegEx.IsMatch(tbInstance.Text)) { lastValidText = tbInstance.Text; SetHasRegExMisMatch(tbInstance, false); } else { SetHasRegExMisMatch(tbInstance, true); } }; tbInstance.PreviewLostKeyboardFocus += (s, e1) => { var localTxt = lastValidText; if (!maskRegEx.IsMatch(tbInstance.Text)) { SetHasRegExMisMatch(tbInstance, true); e1.Handled = true; tbInstance.Text = localTxt; tbInstance.CaretIndex = 99; } else { SetHasRegExMisMatch(tbInstance, false); } }; } private static string GetProposedText(TextBox textBox, string newText) { var text = textBox.Text; if (textBox.SelectionStart != -1) { text = text.Remove(textBox.SelectionStart, textBox.SelectionLength); } text = text.Insert(textBox.CaretIndex, newText); return text; } }
Subscribe to:
Posts (Atom)