Локальные переменные для операторов Natvis Visual Studio

В настоящее время я пишу визуализатор для типа даты в natvis. Тип даты хранит секунды с 1970 года обычным способом unix, но получение года, месяца и дня месяца из этого чрезвычайно долго, если не использовать временные переменные. Я хотел бы иметь возможность хранить рабочие переменные, чтобы разумно оценивать визуализатор. Это возможно?

Решение, к которому я пришел, выглядит так:

struct SLowResAbsoluteTime
{
    SLowResAbsoluteTime() : mTime(0) { calcDOE(); }
    SLowResAbsoluteTime(int year, SDate::EMonth m, SDate::EDayOfWeek day, UINT8 hour, UINT8 minute, UINT8 seconds);
    SLowResAbsoluteTime(const SDate &date);
    SLowResAbsoluteTime(unsigned long long time) : mTime(time) { calcDOE(); }
    SLowResAbsoluteTime(const SLowResAbsoluteTime &other) : mTime(other.mTime) { calcDOE(); }

    SDate getDate() const; //calculate date object from given time
    UINT32 getHour() const; 
    UINT32 getMinutes() const;
    UINT32 getSeconds() const;

    bool operator < (const SLowResAbsoluteTime &other) const { return mTime < other.mTime; }
    bool operator > (const SLowResAbsoluteTime &other) const { return mTime > other.mTime; }
    bool operator <= (const SLowResAbsoluteTime &other) const { return mTime <= other.mTime; }
    bool operator >= (const SLowResAbsoluteTime &other) const { return mTime >= other.mTime; }
    bool operator == (const SLowResAbsoluteTime &other) const { return mTime == other.mTime; }
    bool operator != (const SLowResAbsoluteTime &other) const { return mTime != other.mTime; }
    SLowResAbsoluteTime operator -(const SLowResAbsoluteTime &time) const { return SLowResAbsoluteTime(mTime - time.mTime); }
    SLowResAbsoluteTime operator +(const SLowResAbsoluteTime &time) const { return SLowResAbsoluteTime(mTime + time.mTime); }
    const SLowResAbsoluteTime &operator -=(const SLowResAbsoluteTime &time) { mTime -= time.mTime; return *this; }
    const SLowResAbsoluteTime &operator +=(const SLowResAbsoluteTime &time) { mTime += time.mTime; return *this; }
    unsigned long long mTime;
    void invalidate() { mTime = -1; }
    bool isValid() const {return mTime != UINT64(-1); }
    operator unsigned long() const { return (long)mTime; }
    void calcDOE();
#ifdef USING_DEBUG_TIMER_DOE
    struct { UINT16 y; UINT8 m; UINT8 d; } mDOE;
#endif
};

Обратите внимание на раздел «USING_DEBUG_TIMER_DOE». Это рассчитывается так:

void SLowResAbsoluteTime::calcDOE()
{
#ifdef USING_DEBUG_TIMER_DOE
    int ts = mTime / (60 * 60 * 24);
    int z = ts + 719468;
    int doe = (z - ((z >= 0 ? z : z - 146096) / 146097) * 146097);
    int yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;  // [0, 399]
    int era = (z >= 0 ? z : z - 146096) / 146097;
    int y = (yoe) + era * 400;
    int doy = doe - (365 * yoe + yoe / 4 - yoe / 100);                // [0, 365]
    int mp = (5 * doy + 2) / 153;                                   // [0, 11]
    int d = doy - (153 * mp + 2) / 5 + 1;                             // [1, 31]
    int m = mp + (mp < 10 ? 3 : -9);                            // [1, 12]
    mDOE.y = y + (m <= 2);
    mDOE.m = m;
    mDOE.d = d; 
#endif  
}

и natvis для их визуализации:

<Type Name="SLowResAbsoluteTime">

    <DisplayString>{{time = { (mTime / (60 * 60)) % 24  }:{(mTime / 60) % 60}:{mTime % 60} } day-1970: {mTime / (60 * 60 * 24)} }</DisplayString>

    <Expand>        
        <Item Name="month">(int)mDOE.m</Item>
        <Item Name="day">(int)mDOE.d</Item>-->
        <Item Name="secs since 1/1/1970"> mTime</Item>  
    </Expand>
</Type>

person Luther    schedule 19.04.2020    source источник
comment
Оказывается, невозможно сделать это сумасшедшим длинным способом из-за переполнения, в любом случае, не без серьезной переработки математики, и это слишком много усилий для этого. Я «решил» проблему, добавив дополнительные переменные в код C++ в сборке отладки, с которыми может справиться NatVis, но я хотел бы знать, есть ли там более мощные приемы. Полноценный язык сценариев, такой как python или js, был бы полезен.   -  person Luther    schedule 19.04.2020
comment
Не могли бы вы поделиться минимально воспроизводимым примером/что вы уже закодировали!?   -  person Werner Henze    schedule 05.05.2020
comment
Конечно, я отредактировал исходный пост, чтобы показать, что я сделал.   -  person Luther    schedule 07.05.2020


Ответы (1)


Если вы хотите исключить calcDOE и mDOE из своего кода и сделать расчет в соответствующем натвисе - да, это возможно. Используйте Intrinsic функции:

  <Type Name="SLowResAbsoluteTime">
    <Intrinsic Name="ts"   Expression="mTime / (60 * 60 * 24)                                       "/>
    <Intrinsic Name="z"    Expression="ts() + 719468                                                "/>
    <Intrinsic Name="doe"  Expression="(z() - ((z() &gt;= 0 ? z() : z() - 146096) / 146097) * 146097)"/>
    <Intrinsic Name="yoe"  Expression="(doe() - doe() / 1460 + doe() / 36524 - doe() / 146096) / 365"/>
    <Intrinsic Name="era"  Expression="(z() &gt;= 0 ? z() : z() - 146096) / 146097                  "/>
    <Intrinsic Name="y"    Expression="yoe() + era() * 400                                          "/>
    <Intrinsic Name="doy"  Expression="doe() - (365 * yoe() + yoe() / 4 - yoe() / 100)              "/>
    <Intrinsic Name="mp"   Expression="(5 * doy() + 2) / 153                                        "/>
    <Intrinsic Name="d"    Expression="doy() - (153 * mp() + 2) / 5 + 1                             "/>
    <Intrinsic Name="m"    Expression="mp() + (mp() &lt; 10 ? 3 : -9)                               "/>
    <Intrinsic Name="DOEy" Expression="y() + (m() &lt;= 2)                                          "/>
    <Expand>
      <Item Name="day">d()</Item>
      <Item Name="month">m()</Item>
      <Item Name="year">DOEy()</Item>
    </Expand>
  </Type>
person mr NAE    schedule 07.05.2020
comment
Ах, посмотрите на это, как раз то, что я хотел. Я не знал о ключевом слове «внутреннее» и не встречал его в документах, которые читал. - person Luther; 07.05.2020