/****************************************************************************
|
**
|
** Copyright (C) 2018 The Qt Company Ltd.
|
** Contact: https://www.qt.io/licensing/
|
**
|
** This file is part of the Qt VS Tools.
|
**
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
** Commercial License Usage
|
** Licensees holding valid commercial Qt licenses may use this file in
|
** accordance with the commercial license agreement provided with the
|
** Software or, alternatively, in accordance with the terms contained in
|
** a written agreement between you and The Qt Company. For licensing terms
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
** information use the contact form at https://www.qt.io/contact-us.
|
**
|
** GNU General Public License Usage
|
** Alternatively, this file may be used under the terms of the GNU
|
** General Public License version 3 as published by the Free Software
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
** included in the packaging of this file. Please review the following
|
** information to ensure the GNU General Public License requirements will
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
**
|
** $QT_END_LICENSE$
|
**
|
****************************************************************************/
|
|
using Microsoft.VisualStudio.Debugger.Interop;
|
using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Reflection;
|
|
namespace QtVsTools.Qml.Debug.AD7
|
{
|
class InfoHelper<TDerived>
|
where TDerived : InfoHelper<TDerived>
|
{
|
public class Ref<TStruct>
|
{
|
public TStruct s = default(TStruct);
|
}
|
|
public abstract class MapField<TStruct, TFieldMask>
|
{
|
public TFieldMask FieldMaskBitCheck { get; set; }
|
public TFieldMask FieldMaskBitUpdate { get; set; }
|
public abstract void Map(TDerived infoObj, Ref<TStruct> infoStruct);
|
}
|
|
protected class MapField<TStruct, TFieldMask, T1, T2> : MapField<TStruct, TFieldMask>
|
{
|
public Func<TDerived, T1> FieldValue { get; set; }
|
public Func<T1, T2> Convert { get; set; }
|
public Func<T1, bool> IsNull { get; set; }
|
public Action<Ref<TStruct>, T2> MapToStruct { get; set; }
|
|
public override void Map(TDerived infoObj, Ref<TStruct> infoStruct)
|
{
|
if (FieldValue == null || MapToStruct == null)
|
return;
|
|
T1 fieldValue = FieldValue(infoObj);
|
if (IsNull(fieldValue))
|
return;
|
|
MapToStruct(infoStruct, Convert(fieldValue));
|
}
|
}
|
|
public abstract class Mapping
|
{ }
|
|
public class Mapping<TStruct, TFieldMask> : Mapping,
|
IEnumerable<MapField<TStruct, TFieldMask>>
|
{
|
List<MapField<TStruct, TFieldMask>> fieldMaps;
|
|
protected static Action<Ref<TStruct>, TFieldMask> UpdateMask { get; set; }
|
|
public Mapping(Action<Ref<TStruct>, TFieldMask> updateMask)
|
{
|
fieldMaps = new List<MapField<TStruct, TFieldMask>>();
|
UpdateMask = updateMask;
|
}
|
|
public void Add<T>(
|
TFieldMask fieldMaskBit,
|
Action<Ref<TStruct>, T> mapToStruct,
|
Func<TDerived, T> fieldValue)
|
where T : class
|
{
|
Add(fieldMaskBit, fieldMaskBit, mapToStruct, fieldValue);
|
}
|
|
public void Add<T>(
|
TFieldMask fieldMaskBitCheck,
|
TFieldMask fieldMaskBitUpdate,
|
Action<Ref<TStruct>, T> mapToStruct,
|
Func<TDerived, T> fieldValue)
|
where T : class
|
{
|
fieldMaps.Add(new MapField<TStruct, TFieldMask, T, T>
|
{
|
FieldMaskBitCheck = fieldMaskBitCheck,
|
FieldMaskBitUpdate = fieldMaskBitUpdate,
|
FieldValue = fieldValue,
|
MapToStruct = mapToStruct,
|
IsNull = (x => x == null),
|
Convert = (x => x)
|
});
|
}
|
|
public void Add<T>(
|
TFieldMask fieldMaskBit,
|
Action<Ref<TStruct>, T> mapToStruct,
|
Func<TDerived, T?> fieldValue)
|
where T : struct
|
{
|
Add(fieldMaskBit, fieldMaskBit, mapToStruct, fieldValue);
|
}
|
|
public void Add<T>(
|
TFieldMask fieldMaskBitCheck,
|
TFieldMask fieldMaskBitUpdate,
|
Action<Ref<TStruct>, T> mapToStruct,
|
Func<TDerived, T?> fieldValue)
|
where T : struct
|
{
|
fieldMaps.Add(new MapField<TStruct, TFieldMask, T?, T>
|
{
|
FieldMaskBitCheck = fieldMaskBitCheck,
|
FieldMaskBitUpdate = fieldMaskBitUpdate,
|
FieldValue = fieldValue,
|
MapToStruct = mapToStruct,
|
IsNull = (x => x == null),
|
Convert = (x => (x.HasValue ? x.Value : default(T)))
|
});
|
}
|
|
public IEnumerator<MapField<TStruct, TFieldMask>> GetEnumerator()
|
{
|
return fieldMaps.GetEnumerator();
|
}
|
|
IEnumerator IEnumerable.GetEnumerator()
|
{
|
return GetEnumerator();
|
}
|
|
public void Map(TDerived infoObj, TFieldMask fieldMask, out TStruct infoStruct)
|
{
|
infoStruct = default(TStruct);
|
var r = new Ref<TStruct>();
|
|
foreach (var mapping in this) {
|
if (!MaskHasValue(fieldMask, mapping.FieldMaskBitCheck))
|
continue;
|
mapping.Map(infoObj, r);
|
UpdateMask(r, mapping.FieldMaskBitUpdate);
|
}
|
infoStruct = r.s;
|
}
|
|
protected virtual bool MaskHasValue(TFieldMask fieldMask, TFieldMask fieldMaskBit)
|
{
|
if (typeof(TFieldMask).IsEnum) {
|
var enumFieldMask = fieldMask as Enum;
|
var enumFieldMaskBit = fieldMaskBit as Enum;
|
return enumFieldMask.HasFlag(enumFieldMaskBit);
|
}
|
|
try {
|
var intFieldMask = Convert.ToUInt64(fieldMask);
|
var intFieldMaskBit = Convert.ToUInt64(fieldMaskBit);
|
return (intFieldMask & intFieldMaskBit) != 0;
|
|
} catch {
|
return false;
|
}
|
}
|
}
|
|
public void Map<TStruct, TFieldMask>(
|
Mapping mapping,
|
TFieldMask fieldMask,
|
out TStruct infoStruct)
|
{
|
var mappingToStruct = mapping as Mapping<TStruct, TFieldMask>;
|
if (mappingToStruct != null)
|
mappingToStruct.Map(this as TDerived, fieldMask, out infoStruct);
|
else
|
infoStruct = default(TStruct);
|
}
|
}
|
}
|