<commit_before>// @(#)root/gui:$Name:  $:$Id: TGLabel.cxx,v 1.15 2005/01/12 18:39:29 brun Exp $
// Author: Fons Rademakers   06/01/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLabel                                                              //
//                                                                      //
// This class handles GUI labels.                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGLabel.h"
#include "TGWidget.h"
#include "TGString.h"
#include "TGResourcePool.h"
#include "Riostream.h"
#include "TColor.h"

const TGFont *TGLabel::fgDefaultFont = 0;
const TGGC   *TGLabel::fgDefaultGC = 0;

ClassImp(TGLabel)

//______________________________________________________________________________
TGLabel::TGLabel(const TGWindow *p, TGString *text, GContext_t norm,
                 FontStruct_t font, UInt_t options, ULong_t back) :
    TGFrame(p, 1, 1, options, back)
{
   // Create a label GUI object. TGLabel will become the owner of the
   // text and will delete it in its dtor.

   fText        = text;
   fTMode       = kTextCenterX | kTextCenterY;
   fTextChanged = kTRUE;
   fFontStruct  = font;
   fNormGC      = norm;
   fHasOwnFont  = kFALSE;
   fDisabled    = kFALSE;

   int max_ascent, max_descent;
   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   SetWindowName();
}

//______________________________________________________________________________
TGLabel::TGLabel(const TGWindow *p, const char *text, GContext_t norm,
                 FontStruct_t font, UInt_t options, ULong_t back) :
    TGFrame(p, 1, 1, options, back)
{
   // Create a label GUI object.

   fText        = new TGString(!text && !p ? GetName() : text);
   fTMode       = kTextCenterX | kTextCenterY;
   fTextChanged = kTRUE;
   fFontStruct  = font;
   fNormGC      = norm;
   fHasOwnFont  = kFALSE;
   fDisabled    = kFALSE;

   int max_ascent, max_descent;
   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   SetWindowName();
}

//______________________________________________________________________________
TGLabel::~TGLabel()
{
   // Delete label.

   if (fText) delete fText;
   if (fHasOwnFont) delete fClient->GetGCPool()->FindGC(fNormGC);
}

//______________________________________________________________________________
void TGLabel::SetText(TGString *new_text)
{
   // Set new text in label. After calling this method one needs to call
   // the parents frame's Layout() method to force updating of the label size.
   // The new_text is adopted by the TGLabel and will be properly deleted.

   if (fText) delete fText;
   fText        = new_text;
   fTextChanged = kTRUE;

   int max_ascent, max_descent;

   fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   // Resize is done when parent's is Layout() is called
   //Resize(fTWidth, fTHeight + 1);
   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::DoRedraw()
{
   // Redraw label widget.

   int x, y;

   TGFrame::DoRedraw();

   if (fTextChanged) {
      fTextChanged = kFALSE;
   }

   if (fTMode & kTextLeft)
      x = 0;
   else if (fTMode & kTextRight)
      x = fWidth - fTWidth;
   else
      x = (fWidth - fTWidth) >> 1;

   if (fTMode & kTextTop)
      y = 0;
   else if (fTMode & kTextBottom)
      y = fHeight - fTHeight;
   else
      y = (fHeight - fTHeight) >> 1;

   int max_ascent, max_descent;
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   if (!fDisabled) {
      fText->Draw(fId, GetBckgndGC()(), x +1, y +1 + max_ascent);
      fText->Draw(fId, fNormGC, x, y + max_ascent);
   } else {
      fText->Draw(fId, GetHilightGC()(), x + 1, y + 1 + max_ascent);
      fText->Draw(fId, GetShadowGC()(), x, y + max_ascent);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextFont(FontStruct_t font, Bool_t global)
{
   // Changes text font.
   // If global is true font is changed globally.

   FontH_t v = gVirtualX->GetFontHandle(font);
   if (!v) return;

   fTextChanged = kTRUE;

   fFontStruct = font;
   TGGC *gc = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
   if (global) {
      gc = new TGGC(*gc); // copy
      fHasOwnFont = kTRUE;
   }
   gc->SetFont(v);
   fNormGC = gc->GetGC();

   int max_ascent, max_descent;

   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   // Resize is done when parent's is Layout() is called
   //Resize(fTWidth, fTHeight + 1);
   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::SetTextFont(const char *fontName, Bool_t global)
{
   // Changes text font specified by name.
   // If global is true font is changed globally.

   TGFont *font = fClient->GetFont(fontName);
   if (font) {
      SetTextFont(font->GetFontStruct(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextFont(TGFont *font, Bool_t global)
{
   // Changes text font specified by pointer to TGFont object.
   // If global is true font is changed globally.

   if (font) {
      SetTextFont(font->GetFontStruct(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextColor(Pixel_t color, Bool_t global)
{
   // Changes text color.
   // If global is true color is changed globally

   TGGC *gc = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);

   if (!global) {
      gc = new TGGC(*gc); // copy
      fHasOwnFont = kTRUE;
   }

   gc->SetForeground(color);
   fNormGC = gc->GetGC();

   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::SetTextColor(TColor *color, Bool_t global)
{
   // Changes text color.
   // If global is true color is changed globally

   if (color) {
      SetTextColor(color->GetPixel(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextJustify(Int_t mode)
{
   // Set text justification. Mode is an OR of the bits:
   // kTextTop, kTextLeft, kTextLeft, kTextRight, kTextCenterX and
   // kTextCenterY.

   fTextChanged = kTRUE;
   fTMode = mode;

   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
Bool_t TGLabel::HasOwnFont() const
{
   // Returns kTRUE if text attributes are unique,
   // returns kFALSE if text attributes are shared (global).

   return fHasOwnFont;
}

//______________________________________________________________________________
void TGLabel::SavePrimitive(ofstream &out, Option_t *option)
{
   // Save a label widget as a C++ statement(s) on output stream out.

   char quote = '"';

   // font + GC
   option = GetName()+5;         // unique digit id of the name
   char ParGC[50], ParFont[50];
   sprintf(ParFont,"%s::GetDefaultFontStruct()",IsA()->GetName());
   sprintf(ParGC,"%s::GetDefaultGC()()",IsA()->GetName());
   if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
      TGFont *ufont = fClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
      if (ufont) {
         ufont->SavePrimitive(out, option);
         sprintf(ParFont,"ufont->GetFontStruct()");
      }

      TGGC *userGC = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
      if (userGC) {
         userGC->SavePrimitive(out, option);
         sprintf(ParGC,"uGC->GetGC()");
      }
   }

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   TString label = GetText()->GetString();
   label.ReplaceAll("\"","\\\"");

   out << "   TGLabel *";
   out << GetName() << " = new TGLabel("<< fParent->GetName()
       << "," << quote << label << quote;
   if (fBackground == GetDefaultFrameBackground()) {
      if (!GetOptions()) {
         if (fFontStruct == GetDefaultFontStruct()) {
            if (fNormGC == GetDefaultGC()()) {
               out <<");" << endl;
            } else {
               out << "," << ParGC << ");" << endl;
            }
         } else {
            out << "," << ParGC << "," << ParFont << ");" << endl;
         }
      } else {
         out << "," << ParGC << "," << ParFont << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << ParGC << "," << ParFont << "," << GetOptionString() << ",ucolor);" << endl;
   }

   if (fDisabled)
      out << "   " << GetName() << "->Disable();" << endl;
}

//______________________________________________________________________________
FontStruct_t TGLabel::GetDefaultFontStruct()
{
   // Static returning label default font struct.

   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
   return fgDefaultFont->GetFontStruct();
}

//______________________________________________________________________________
const TGGC &TGLabel::GetDefaultGC()
{
   // Static returning label default graphics context.

   if (!fgDefaultGC)
      fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
   return *fgDefaultGC;
}
<commit_msg>From Ilka: roll back change of yesterday which had nasty side effects.<commit_after>// @(#)root/gui:$Name:  $:$Id: TGLabel.cxx,v 1.16 2005/05/09 16:59:07 rdm Exp $
// Author: Fons Rademakers   06/01/98

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/
/**************************************************************************

    This source is based on Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.

    Xclass95 is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

**************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TGLabel                                                              //
//                                                                      //
// This class handles GUI labels.                                       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TGLabel.h"
#include "TGWidget.h"
#include "TGString.h"
#include "TGResourcePool.h"
#include "Riostream.h"
#include "TColor.h"

const TGFont *TGLabel::fgDefaultFont = 0;
const TGGC   *TGLabel::fgDefaultGC = 0;

ClassImp(TGLabel)

//______________________________________________________________________________
TGLabel::TGLabel(const TGWindow *p, TGString *text, GContext_t norm,
                 FontStruct_t font, UInt_t options, ULong_t back) :
    TGFrame(p, 1, 1, options, back)
{
   // Create a label GUI object. TGLabel will become the owner of the
   // text and will delete it in its dtor.

   fText        = text;
   fTMode       = kTextCenterX | kTextCenterY;
   fTextChanged = kTRUE;
   fFontStruct  = font;
   fNormGC      = norm;
   fHasOwnFont  = kFALSE;
   fDisabled    = kFALSE;

   int max_ascent, max_descent;
   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   SetWindowName();
}

//______________________________________________________________________________
TGLabel::TGLabel(const TGWindow *p, const char *text, GContext_t norm,
                 FontStruct_t font, UInt_t options, ULong_t back) :
    TGFrame(p, 1, 1, options, back)
{
   // Create a label GUI object.

   fText        = new TGString(!text && !p ? GetName() : text);
   fTMode       = kTextCenterX | kTextCenterY;
   fTextChanged = kTRUE;
   fFontStruct  = font;
   fNormGC      = norm;
   fHasOwnFont  = kFALSE;
   fDisabled    = kFALSE;

   int max_ascent, max_descent;
   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;
   Resize(fTWidth, fTHeight + 1);
   SetWindowName();
}

//______________________________________________________________________________
TGLabel::~TGLabel()
{
   // Delete label.

   if (fText) delete fText;
   if (fHasOwnFont) delete fClient->GetGCPool()->FindGC(fNormGC);
}

//______________________________________________________________________________
void TGLabel::SetText(TGString *new_text)
{
   // Set new text in label. After calling this method one needs to call
   // the parents frame's Layout() method to force updating of the label size.
   // The new_text is adopted by the TGLabel and will be properly deleted.

   if (fText) delete fText;
   fText        = new_text;
   fTextChanged = kTRUE;

   int max_ascent, max_descent;

   fTWidth = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   // Resize is done when parent's is Layout() is called
   //Resize(fTWidth, fTHeight + 1);
   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::DoRedraw()
{
   // Redraw label widget.

   int x, y;

   TGFrame::DoRedraw();

   if (fTextChanged) {
      fTextChanged = kFALSE;
   }

   if (fTMode & kTextLeft)
      x = 0;
   else if (fTMode & kTextRight)
      x = fWidth - fTWidth;
   else
      x = (fWidth - fTWidth) >> 1;

   if (fTMode & kTextTop)
      y = 0;
   else if (fTMode & kTextBottom)
      y = fHeight - fTHeight;
   else
      y = (fHeight - fTHeight) >> 1;

   int max_ascent, max_descent;
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   if (!fDisabled) {
      fText->Draw(fId, GetBckgndGC()(), x +1, y +1 + max_ascent);
      fText->Draw(fId, fNormGC, x, y + max_ascent);
   } else {
      fText->Draw(fId, GetHilightGC()(), x + 1, y + 1 + max_ascent);
      fText->Draw(fId, GetShadowGC()(), x, y + max_ascent);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextFont(FontStruct_t font, Bool_t global)
{
   // Changes text font.
   // If global is true font is changed globally.

   FontH_t v = gVirtualX->GetFontHandle(font);
   if (!v) return;

   fTextChanged = kTRUE;

   fFontStruct = font;
   TGGC *gc = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
   if (global) {
      gc = new TGGC(*gc); // copy
      fHasOwnFont = kTRUE;
   }
   gc->SetFont(v);
   fNormGC = gc->GetGC();

   int max_ascent, max_descent;

   fTWidth  = gVirtualX->TextWidth(fFontStruct, fText->GetString(), fText->GetLength());
   gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
   fTHeight = max_ascent + max_descent;

   // Resize is done when parent's is Layout() is called
   //Resize(fTWidth, fTHeight + 1);
   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::SetTextFont(const char *fontName, Bool_t global)
{
   // Changes text font specified by name.
   // If global is true font is changed globally.

   TGFont *font = fClient->GetFont(fontName);
   if (font) {
      SetTextFont(font->GetFontStruct(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextFont(TGFont *font, Bool_t global)
{
   // Changes text font specified by pointer to TGFont object.
   // If global is true font is changed globally.

   if (font) {
      SetTextFont(font->GetFontStruct(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextColor(Pixel_t color, Bool_t global)
{
   // Changes text color.
   // If global is true color is changed globally

   TGGC *gc = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);

   if (global) {
      gc = new TGGC(*gc); // copy
      fHasOwnFont = kTRUE;
   }

   gc->SetForeground(color);
   fNormGC = gc->GetGC();

   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
void TGLabel::SetTextColor(TColor *color, Bool_t global)
{
   // Changes text color.
   // If global is true color is changed globally

   if (color) {
      SetTextColor(color->GetPixel(), global);
   }
}

//______________________________________________________________________________
void TGLabel::SetTextJustify(Int_t mode)
{
   // Set text justification. Mode is an OR of the bits:
   // kTextTop, kTextLeft, kTextLeft, kTextRight, kTextCenterX and
   // kTextCenterY.

   fTextChanged = kTRUE;
   fTMode = mode;

   fClient->NeedRedraw(this);
}

//______________________________________________________________________________
Bool_t TGLabel::HasOwnFont() const
{
   // Returns kTRUE if text attributes are unique,
   // returns kFALSE if text attributes are shared (global).

   return fHasOwnFont;
}

//______________________________________________________________________________
void TGLabel::SavePrimitive(ofstream &out, Option_t *option)
{
   // Save a label widget as a C++ statement(s) on output stream out.

   char quote = '"';

   // font + GC
   option = GetName()+5;         // unique digit id of the name
   char ParGC[50], ParFont[50];
   sprintf(ParFont,"%s::GetDefaultFontStruct()",IsA()->GetName());
   sprintf(ParGC,"%s::GetDefaultGC()()",IsA()->GetName());
   if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
      TGFont *ufont = fClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
      if (ufont) {
         ufont->SavePrimitive(out, option);
         sprintf(ParFont,"ufont->GetFontStruct()");
      }

      TGGC *userGC = fClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
      if (userGC) {
         userGC->SavePrimitive(out, option);
         sprintf(ParGC,"uGC->GetGC()");
      }
   }

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   TString label = GetText()->GetString();
   label.ReplaceAll("\"","\\\"");

   out << "   TGLabel *";
   out << GetName() << " = new TGLabel("<< fParent->GetName()
       << "," << quote << label << quote;
   if (fBackground == GetDefaultFrameBackground()) {
      if (!GetOptions()) {
         if (fFontStruct == GetDefaultFontStruct()) {
            if (fNormGC == GetDefaultGC()()) {
               out <<");" << endl;
            } else {
               out << "," << ParGC << ");" << endl;
            }
         } else {
            out << "," << ParGC << "," << ParFont << ");" << endl;
         }
      } else {
         out << "," << ParGC << "," << ParFont << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << ParGC << "," << ParFont << "," << GetOptionString() << ",ucolor);" << endl;
   }

   if (fDisabled)
      out << "   " << GetName() << "->Disable();" << endl;
}

//______________________________________________________________________________
FontStruct_t TGLabel::GetDefaultFontStruct()
{
   // Static returning label default font struct.

   if (!fgDefaultFont)
      fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
   return fgDefaultFont->GetFontStruct();
}

//______________________________________________________________________________
const TGGC &TGLabel::GetDefaultGC()
{
   // Static returning label default graphics context.

   if (!fgDefaultGC)
      fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
   return *fgDefaultGC;
}
<|endoftext|>


<commit_before><commit_msg>Update default option<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include "test.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/convolution.hpp>
#include <miopen/miopen.h>
#include <miopen/tensor.hpp>
#include <miopen/tensor_ops.hpp>
#include <utility>

#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

#define MIO_OPS_DEBUG 0

template <class T>
struct tensor_ops_base
{
    tensor<T> a;
    tensor<T> b;
    tensor<T> c;

    void fail(float = 0) const
    {
        std::cout << "A tensor: " << a.desc.ToString() << std::endl;
        std::cout << "B tensor: " << b.desc.ToString() << std::endl;
        std::cout << "C tensor: " << a.desc.ToString() << std::endl;
    }
};

template <class T>
struct verify_tensor_ops : tensor_ops_base<T>
{
    using tensor_ops_base<T>::a;
    using tensor_ops_base<T>::b;
    using tensor_ops_base<T>::c;

    int Aoffset;
    int Boffset;
    int Coffset;

    float alpha0;
    float alpha1;
    float beta;

    verify_tensor_ops(const tensor<T>& pa,
                      const tensor<T>& pb,
                      const tensor<T>& pc,
                      std::vector<int>& offsets,
                      float palpha0 = 1,
                      float palpha1 = 1,
                      float pbeta   = 0)
    {
        a = pa;
        b = pb;
        c = pc;

        Aoffset = offsets[0];
        Boffset = offsets[1];
        Coffset = offsets[2];

        alpha0 = palpha0;
        alpha1 = palpha1;
        beta   = pbeta;
    }

    // verify_tensor_ops(const tensor<T>& pa, const tensor<T>& pb, const tensor<T>& pc, const
    // std::vector<T>& dims)
    //{
    // a = pa(dims);
    // b = pb(dims);
    // c = pc(dims);
    //}

    static T add_elem(T aelem, T belem) { return aelem + belem; }
    static T mul_elem(T aelem, T belem) { return aelem * belem; }
    static T max_elem(T aelem, T belem) { return ((aelem > belem) ? aelem : belem); }
    static T min_elem(T aelem, T belem) { return ((aelem < belem) ? aelem : belem); }

    static void tensor_for_loop(const tensor<T>& aten,
                                const tensor<T>& bten,
                                tensor<T>& cten,
                                const std::vector<size_t>& a_dims,
                                const std::vector<size_t>& b_dims,
                                float palpha0,
                                float palpha1,
                                float pbeta,
                                int recurr_aoffset,
                                int recurr_boffset,
                                int recurr_coffset,
                                int dim,
                                int AtenOffset,
                                int BtenOffset,
                                int CtenOffset)
    {

        int astride = aten.desc.GetStrides()[dim];
        int bstride = bten.desc.GetStrides()[dim];
        int cstride = cten.desc.GetStrides()[dim];

        // printf("cstride: %d\n", cstride);

        for(int idx = 0; idx < a_dims[dim]; idx++)
        {
            size_t aindex = recurr_aoffset + astride * idx;
            size_t cindex = recurr_coffset + cstride * idx;
            size_t bindex =
                (b_dims[dim] == a_dims[dim]) ? recurr_boffset + bstride * idx : recurr_boffset;

            // if((bindex < bten.desc.GetElementSize()) && (dim == a_dims.size() - 1))
            if(dim == (a_dims.size() - 1))
            {
#if(MIO_OPS_DEBUG)
                printf("c[%lu](%f) = a[%lu](%f) + b[%lu](%f)\n",
                       cindex + CtenOffset,
                       cten[cindex + CtenOffset],
                       aindex + AtenOffset,
                       aten[aindex + AtenOffset],
                       bindex + Boffset,
                       bten[bindex + Boffset]);
#endif
                cten[cindex + CtenOffset] =
                    // add_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    // max_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    // min_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    mul_elem(aten[aindex + AtenOffset] * palpha0,
                             bten[bindex + BtenOffset] * palpha1) +
                    pbeta * cten[cindex + CtenOffset];
            }
            if(dim < (a_dims.size() - 1))
            {

                tensor_for_loop(aten,
                                bten,
                                cten,
                                a_dims,
                                b_dims,
                                palpha0,
                                palpha1,
                                pbeta,
                                aindex,
                                bindex,
                                cindex,
                                dim + 1,
                                AtenOffset,
                                BtenOffset,
                                CtenOffset);
            }
        }
    }

    tensor<T> cpu() const
    {
        auto r = c;
        std::fill(r.begin(), r.end(), 1);
        auto clens    = r.desc.GetLengths();
        auto blens    = b.desc.GetLengths();
        auto bstrides = b.desc.GetStrides();
        auto cstrides = r.desc.GetStrides();

        tensor_for_loop(
            a, b, r, clens, blens, alpha0, alpha1, beta, 0, 0, 0, 0, Aoffset, Boffset, Coffset);

#if(MIO_OPS_DEBUG)
        for(int i = 0; i < r.desc.GetElementSize(); i++)
            printf("CPU_C[%d]: %f\n", i, r.data[i + Coffset]);
#endif
        return r;
    }

    tensor<T> gpu() const
    {
        auto&& handle = get_handle();
        auto r        = c;

        // return c;
        std::fill(r.begin(), r.end(), 1);

        auto c_dev = handle.Write(r.data);
        auto a_dev = handle.Write(a.data);
        auto b_dev = handle.Write(b.data);

        miopen::OpTensor(handle,
                         // miopenTensorOpAdd,
                         // miopenTensorOpMax,
                         // miopenTensorOpMin,
                         miopenTensorOpMul,
                         &alpha0,
                         a.desc,
                         a_dev.get(),
                         &alpha1,
                         b.desc,
                         b_dev.get(),
                         &beta,
                         r.desc,
                         c_dev.get(),
                         Aoffset,
                         Boffset,
                         Coffset);

        r.data = handle.Read<T>(c_dev, r.data.size());

#if(MIO_OPS_DEBUG)
        handle.Finish();
        auto clens    = r.desc.GetLengths();
        auto cstrides = r.desc.GetStrides();
        for(int i = 0; i < r.desc.GetElementSize(); i++)
            printf("GPU_C[%d]: %f\n", i, c.data[i + Coffset]);
#endif
        return r;
    }

    void fail(int = 0) const
    {
        std::cout << "TensorOp: " << std::endl;
        this->tensor_ops_base<T>::fail();
    }
};

template <class T>
struct tensor_ops_driver : test_driver
{

    tensor<T> super_a;
    tensor<T> super_b;
    tensor<T> super_c;

    std::vector<int> tensorlens_ac;
    std::vector<int> tensorlens_b;
    std::vector<int> offsets;
    std::vector<float> alphabeta;
    bool packed = false;

    std::vector<std::vector<int>> get_sub_tensor_a()
    {
        return {{32, 16, 8, 4, 4}, {16, 20, 16, 8}, {20, 16, 8}, {16, 8}, {8}};
    }

    std::vector<std::vector<int>> get_sub_tensor_b()
    {
        return {{32, 16, 8, 4, 4},
                {32, 16, 1, 1, 1},
                {1, 16, 8, 1, 1},
                {1, 1, 8, 4, 1},
                {16, 20, 16, 8},
                {16, 20, 16, 1},
                {16, 20, 1, 1},
                {16, 1, 1, 1},
                {1, 20, 16, 8},
                {1, 20, 16, 1},
                {1, 20, 1, 1},
                {1, 1, 16, 8},
                {1, 1, 1, 8},
                {20, 16, 8},
                {20, 16, 1},
                {1, 16, 8},
                {1, 16, 1},
                {20, 1, 1},
                {16, 8},
                {16, 1},
                {1, 8},
                {8},
                {1}};
    }

    tensor_ops_driver()
    {

        std::vector<int> alens = {{32, 16, 20, 16, 8}};
        std::vector<int> blens = {{32, 16, 20, 16, 8}};
        std::vector<int> clens = {{32, 16, 20, 16, 8}};

        super_a = tensor<T>{alens}.generate(rand_gen{});
        super_b = tensor<T>{blens}.generate(rand_gen{});
        super_c = tensor<T>{clens}.generate(rand_gen{});

        std::vector<std::vector<int>> get_offsets     = {{64, 32, 16}, {32, 16, 32}, {32, 16, 32}};
        std::vector<std::vector<float>> get_alphabeta = {{1, 1, 0}, {-1, 1, 1}, {1.0, 0.5, 0.3}};

        add(tensorlens_ac, "a", generate_data(get_sub_tensor_a()));
        add(tensorlens_b, "b", generate_data(get_sub_tensor_b()));
        add(offsets, "offsets", generate_data(get_offsets));
        add(alphabeta, "alpha-beta", generate_data(get_alphabeta));
        add(packed, "packed", generate_data({false, true}));
    }

    tensor<T> get_subtensors(tensor<T>& super_tensor, std::vector<int>& lens)
    {
        std::vector<size_t> superStrides = super_tensor.desc.GetStrides();
        std::vector<int> strides(superStrides.begin() + (5 - lens.size()), superStrides.end());
        auto tDesc = miopen::TensorDescriptor{
            miopenFloat, lens.data(), strides.data(), static_cast<int>(lens.size())};
        tensor<T> t = tensor<T>{tDesc};
        t.data      = super_tensor.data;
        return t;
    }

    void run()
    {
        if(tensorlens_ac.size() == tensorlens_b.size())
        {
            tensor<T> aTensor = packed ? tensorlens_ac : get_subtensors(super_a, tensorlens_ac);
            tensor<T> bTensor = packed ? tensorlens_b : get_subtensors(super_b, tensorlens_b);
            tensor<T> cTensor = packed ? tensorlens_ac : get_subtensors(super_c, tensorlens_ac);

            verify(verify_tensor_ops<T>{
                aTensor, bTensor, cTensor, offsets, alphabeta[0], alphabeta[1], alphabeta[2]});
        }
    }
};

int main(int argc, const char* argv[]) { test_drive<tensor_ops_driver>(argc, argv); }
<commit_msg>Set offsets to 0, when using packed<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2017 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/
#include "test.hpp"
#include <array>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <miopen/convolution.hpp>
#include <miopen/miopen.h>
#include <miopen/tensor.hpp>
#include <miopen/tensor_ops.hpp>
#include <utility>

#include "driver.hpp"
#include "get_handle.hpp"
#include "tensor_holder.hpp"
#include "verify.hpp"

#define MIO_OPS_DEBUG 0

template <class T>
struct verify_tensor_ops
{
    tensor<T> a;
    tensor<T> b;
    tensor<T> c;

    int Aoffset;
    int Boffset;
    int Coffset;

    float alpha0;
    float alpha1;
    float beta;

    verify_tensor_ops(const tensor<T>& pa,
                      const tensor<T>& pb,
                      const tensor<T>& pc,
                      std::vector<int>& offsets,
                      float palpha0 = 1,
                      float palpha1 = 1,
                      float pbeta   = 0)
    {
        a = pa;
        b = pb;
        c = pc;

        Aoffset = offsets[0];
        Boffset = offsets[1];
        Coffset = offsets[2];

        alpha0 = palpha0;
        alpha1 = palpha1;
        beta   = pbeta;
    }

    // verify_tensor_ops(const tensor<T>& pa, const tensor<T>& pb, const tensor<T>& pc, const
    // std::vector<T>& dims)
    //{
    // a = pa(dims);
    // b = pb(dims);
    // c = pc(dims);
    //}

    static T add_elem(T aelem, T belem) { return aelem + belem; }
    static T mul_elem(T aelem, T belem) { return aelem * belem; }
    static T max_elem(T aelem, T belem) { return ((aelem > belem) ? aelem : belem); }
    static T min_elem(T aelem, T belem) { return ((aelem < belem) ? aelem : belem); }

    static void tensor_for_loop(const tensor<T>& aten,
                                const tensor<T>& bten,
                                tensor<T>& cten,
                                const std::vector<size_t>& a_dims,
                                const std::vector<size_t>& b_dims,
                                float palpha0,
                                float palpha1,
                                float pbeta,
                                int recurr_aoffset,
                                int recurr_boffset,
                                int recurr_coffset,
                                int dim,
                                int AtenOffset,
                                int BtenOffset,
                                int CtenOffset)
    {

        int astride = aten.desc.GetStrides()[dim];
        int bstride = bten.desc.GetStrides()[dim];
        int cstride = cten.desc.GetStrides()[dim];

        // printf("cstride: %d\n", cstride);

        for(int idx = 0; idx < a_dims[dim]; idx++)
        {
            size_t aindex = recurr_aoffset + astride * idx;
            size_t cindex = recurr_coffset + cstride * idx;
            size_t bindex =
                (b_dims[dim] == a_dims[dim]) ? recurr_boffset + bstride * idx : recurr_boffset;

            // if((bindex < bten.desc.GetElementSize()) && (dim == a_dims.size() - 1))
            if(dim == (a_dims.size() - 1))
            {
#if(MIO_OPS_DEBUG)
                printf("c[%lu](%f) = a[%lu](%f) + b[%lu](%f)\n",
                       cindex + CtenOffset,
                       cten[cindex + CtenOffset],
                       aindex + AtenOffset,
                       aten[aindex + AtenOffset],
                       bindex + Boffset,
                       bten[bindex + Boffset]);
#endif
                cten[cindex + CtenOffset] =
                    // add_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    // max_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    // min_elem(aten[aindex + AtenOffset] * palpha0, bten[bindex + BtenOffset] *
                    // palpha1) +
                    mul_elem(aten[aindex + AtenOffset] * palpha0,
                             bten[bindex + BtenOffset] * palpha1) +
                    pbeta * cten[cindex + CtenOffset];
            }
            if(dim < (a_dims.size() - 1))
            {

                tensor_for_loop(aten,
                                bten,
                                cten,
                                a_dims,
                                b_dims,
                                palpha0,
                                palpha1,
                                pbeta,
                                aindex,
                                bindex,
                                cindex,
                                dim + 1,
                                AtenOffset,
                                BtenOffset,
                                CtenOffset);
            }
        }
    }

    tensor<T> cpu() const
    {
        auto r = c;
        std::fill(r.begin(), r.end(), 1);
        auto clens    = r.desc.GetLengths();
        auto blens    = b.desc.GetLengths();
        auto bstrides = b.desc.GetStrides();
        auto cstrides = r.desc.GetStrides();

        tensor_for_loop(
            a, b, r, clens, blens, alpha0, alpha1, beta, 0, 0, 0, 0, Aoffset, Boffset, Coffset);

#if(MIO_OPS_DEBUG)
        for(int i = 0; i < r.desc.GetElementSize(); i++)
            printf("CPU_C[%d]: %f\n", i, r.data[i + Coffset]);
#endif
        return r;
    }

    tensor<T> gpu() const
    {
        auto&& handle = get_handle();
        auto r        = c;

        // return c;
        std::fill(r.begin(), r.end(), 1);

        auto c_dev = handle.Write(r.data);
        auto a_dev = handle.Write(a.data);
        auto b_dev = handle.Write(b.data);

        miopen::OpTensor(handle,
                         // miopenTensorOpAdd,
                         // miopenTensorOpMax,
                         // miopenTensorOpMin,
                         miopenTensorOpMul,
                         &alpha0,
                         a.desc,
                         a_dev.get(),
                         &alpha1,
                         b.desc,
                         b_dev.get(),
                         &beta,
                         r.desc,
                         c_dev.get(),
                         Aoffset,
                         Boffset,
                         Coffset);

        r.data = handle.Read<T>(c_dev, r.data.size());

#if(MIO_OPS_DEBUG)
        handle.Finish();
        auto clens    = r.desc.GetLengths();
        auto cstrides = r.desc.GetStrides();
        for(int i = 0; i < r.desc.GetElementSize(); i++)
            printf("GPU_C[%d]: %f\n", i, c.data[i + Coffset]);
#endif
        return r;
    }

    void fail(int = 0) const
    {
        std::cout << "TensorOp: " << std::endl;
        std::cout << "A tensor: " << a.desc.ToString() << std::endl;
        std::cout << "B tensor: " << b.desc.ToString() << std::endl;
        std::cout << "C tensor: " << a.desc.ToString() << std::endl;
        std::cout << "Offsets: " << Aoffset << "," << Boffset << "," << Coffset << std::endl;
    }
};

template <class T>
struct tensor_ops_driver : test_driver
{

    tensor<T> super_a;
    tensor<T> super_b;
    tensor<T> super_c;

    std::vector<int> tensorlens_ac;
    std::vector<int> tensorlens_b;
    std::vector<int> offsets;
    std::vector<float> alphabeta;
    bool packed = false;

    std::vector<std::vector<int>> get_sub_tensor_a()
    {
        return {{32, 16, 8, 4, 4}, {16, 20, 16, 8}, {20, 16, 8}, {16, 8}, {8}};
    }

    std::vector<std::vector<int>> get_sub_tensor_b()
    {
        return {{32, 16, 8, 4, 4},
                {32, 16, 1, 1, 1},
                {1, 16, 8, 1, 1},
                {1, 1, 8, 4, 1},
                {16, 20, 16, 8},
                {16, 20, 16, 1},
                {16, 20, 1, 1},
                {16, 1, 1, 1},
                {1, 20, 16, 8},
                {1, 20, 16, 1},
                {1, 20, 1, 1},
                {1, 1, 16, 8},
                {1, 1, 1, 8},
                {20, 16, 8},
                {20, 16, 1},
                {1, 16, 8},
                {1, 16, 1},
                {20, 1, 1},
                {16, 8},
                {16, 1},
                {1, 8},
                {8},
                {1}};
    }

    tensor_ops_driver()
    {

        std::vector<int> alens = {{32, 16, 20, 16, 8}};
        std::vector<int> blens = {{32, 16, 20, 16, 8}};
        std::vector<int> clens = {{32, 16, 20, 16, 8}};

        super_a = tensor<T>{alens}.generate(rand_gen{});
        super_b = tensor<T>{blens}.generate(rand_gen{});
        super_c = tensor<T>{clens}.generate(rand_gen{});

        std::vector<std::vector<int>> get_offsets     = {{64, 32, 16}, {32, 16, 32}, {32, 16, 32}};
        std::vector<std::vector<float>> get_alphabeta = {{1, 1, 0}, {-1, 1, 1}, {1.0, 0.5, 0.3}};

        add(tensorlens_ac, "a", generate_data(get_sub_tensor_a()));
        add(tensorlens_b, "b", generate_data(get_sub_tensor_b()));
        add(offsets, "offsets", generate_data(get_offsets));
        add(alphabeta, "alpha-beta", generate_data(get_alphabeta));
        add(packed, "packed", generate_data({false, true}));
    }

    tensor<T> get_subtensors(tensor<T>& super_tensor, std::vector<int>& lens)
    {
        std::vector<size_t> superStrides = super_tensor.desc.GetStrides();
        std::vector<int> strides(superStrides.begin() + (5 - lens.size()), superStrides.end());
        auto tDesc = miopen::TensorDescriptor{
            miopenFloat, lens.data(), strides.data(), static_cast<int>(lens.size())};
        tensor<T> t = tensor<T>{tDesc};
        t.data      = super_tensor.data;
        return t;
    }

    void run()
    {
        if(tensorlens_ac.size() == tensorlens_b.size())
        {
            tensor<T> aTensor = packed ? tensorlens_ac : get_subtensors(super_a, tensorlens_ac);
            tensor<T> bTensor = packed ? tensorlens_b : get_subtensors(super_b, tensorlens_b);
            tensor<T> cTensor = packed ? tensorlens_ac : get_subtensors(super_c, tensorlens_ac);

            if(packed) offsets = {0, 0, 0, 0, 0};

            verify(verify_tensor_ops<T>{
                aTensor, bTensor, cTensor, offsets, alphabeta[0], alphabeta[1], alphabeta[2]});
        }
    }
};

int main(int argc, const char* argv[]) { test_drive<tensor_ops_driver>(argc, argv); }
<|endoftext|>


<commit_before><commit_msg>Build Passing -> NODE config Parsing Done<commit_after><|endoftext|>


<commit_before>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  (C) 2002, 2003 by David Jarvie  software@astrojar.org.uk
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  As a special exception, permission is given to link this program
 *  with any edition of Qt, and distribute the resulting executable,
 *  without including the source code for Qt in the source distribution.
 */
#include "kalarm.h"
#include <stdlib.h>

#include <qtooltip.h>
#include <qlabel.h>

#include <kapplication.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kdebug.h>

#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "daemongui.h"
#include "prefsettings.h"
#include "traywindow.moc"

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/

TrayWindow::TrayWindow(KAlarmMainWindow* parent, const char* name)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0), name),
	  mAssocMainWindow(parent),
	  mQuitReplaced(false),
	  mActionCollection(this)
{
	kdDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
//	KGlobal::iconLoader()->addAppDir(kapp->aboutData()->appName());
//	mPixmapEnabled  = KGlobal::iconLoader()->loadIcon("kalarm", KIcon::Panel);
//	mPixmapDisabled = KGlobal::iconLoader()->loadIcon("kalarm_disabled", KIcon::Panel);
	mPixmapEnabled  = BarIcon("kalarm");
	mPixmapDisabled = BarIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Can't load system tray icon!"),
		                         i18n("%1 Error").arg(kapp->aboutData()->programName()));

	mActionQuit = KStdAction::quit(this, SLOT(slotQuit()), &mActionCollection);

	// Set up the context menu
	ActionAlarmsEnabled* a = theApp()->actionAlarmEnable();
	mAlarmsEnabledId = a->itemId(a->plug(contextMenu()));
	connect(a, SIGNAL(alarmsEnabledChange(bool)), this, SLOT(setEnabledStatus(bool)));
	theApp()->actionPreferences()->plug(contextMenu());
	theApp()->actionDaemonControl()->plug(contextMenu());

	// Set icon to correspond with the alarms enabled menu status
	DaemonGuiHandler* daemonGui = theApp()->daemonGuiHandler();
	daemonGui->checkStatus();
	setEnabledStatus(daemonGui->monitoringAlarms());

	QToolTip::add(this, kapp->aboutData()->programName());
}

TrayWindow::~TrayWindow()
{
	kdDebug(5950) << "TrayWindow::~TrayWindow()\n";
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Modify the Quit context menu item to only close the system tray widget.
*/
void TrayWindow::contextMenuAboutToShow(KPopupMenu* menu)
{
	if (!mQuitReplaced)
	{
		// Prevent Quit from quitting the program
		QString quitText = mActionQuit->text();
		for (unsigned n = 0;  n < menu->count();  ++n)
		{
			QString txt = menu->text(menu->idAt(n));
			if (txt.startsWith(quitText))
			{
				menu->removeItemAt(n);
				break;
			}
		}
		mActionQuit->plug(menu);
		mQuitReplaced = true;
	}

	// Update the Alarms Enabled item status
	theApp()->daemonGuiHandler()->checkStatus();
}

/******************************************************************************
* Called when the Quit context menu item is selected.
* Closes the system tray window, and if in 'run in system tray' mode closes all
* main windows, but does not exit the program if other windows are still open.
*/
void TrayWindow::slotQuit()
{
	kdDebug(5950)<<"TrayWindow::slotQuit()\n";
	if (theApp()->alarmsDisabledIfStopped()
	&&  KMessageBox::warningYesNo(this, i18n("Quitting will disable alarms\n"
		                                     "(once any alarm message windows are closed)."),
		                          QString::null, mActionQuit->text(), KStdGuiItem::cancel(),
		                          QString::fromLatin1("QuitWarn")
		                         ) != KMessageBox::Yes)
		return;
	if (theApp()->wantRunInSystemTray())
	{
		if (!MessageWin::instanceCount())
			theApp()->quit();
		else
			KAlarmMainWindow::closeAll();
	}
	theApp()->displayTrayIcon(false);
}

/******************************************************************************
* Called to allow quit warning messages again.
*/
void TrayWindow::allowQuitWarning()
{
	KConfig* config = kapp->config();
	config->setGroup(QString::fromLatin1("Notification Messages"));
	config->writeEntry(QString::fromLatin1("QuitWarn"), false);
	config->sync();
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kdDebug(5950)<<"TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
	contextMenu()->setItemChecked(mAlarmsEnabledId, status);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{

	if (e->button() == LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = KAlarmMainWindow::toggleWindow(mAssocMainWindow);
	}
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{

	if (e->button() == LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->setActiveWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(KAlarmMainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#ifdef HAVE_X11_HEADERS
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#ifdef HAVE_X11_HEADERS
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
  // Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(qt_xdisplay(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}
<commit_msg>Minor tidy up<commit_after>/*
 *  traywindow.cpp  -  the KDE system tray applet
 *  Program:  kalarm
 *  (C) 2002, 2003 by David Jarvie  software@astrojar.org.uk
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  As a special exception, permission is given to link this program
 *  with any edition of Qt, and distribute the resulting executable,
 *  without including the source code for Qt in the source distribution.
 */
#include "kalarm.h"
#include <stdlib.h>

#include <qtooltip.h>
#include <qlabel.h>

#include <kapplication.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kstdaction.h>
#include <kaboutdata.h>
#include <kpopupmenu.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstdguiitem.h>
#include <kconfig.h>
#include <kdebug.h>

#include "kalarmapp.h"
#include "mainwindow.h"
#include "messagewin.h"
#include "daemongui.h"
#include "prefsettings.h"
#include "traywindow.moc"

/*=============================================================================
= Class: TrayWindow
= The KDE system tray window.
=============================================================================*/

TrayWindow::TrayWindow(KAlarmMainWindow* parent, const char* name)
	: KSystemTray((theApp()->wantRunInSystemTray() ? parent : 0), name),
	  mAssocMainWindow(parent),
	  mQuitReplaced(false),
	  mActionCollection(this)
{
	kdDebug(5950) << "TrayWindow::TrayWindow()\n";
	// Set up GUI icons
//	KGlobal::iconLoader()->addAppDir(kapp->aboutData()->appName());
//	mPixmapEnabled  = KGlobal::iconLoader()->loadIcon("kalarm", KIcon::Panel);
//	mPixmapDisabled = KGlobal::iconLoader()->loadIcon("kalarm_disabled", KIcon::Panel);
	mPixmapEnabled  = BarIcon("kalarm");
	mPixmapDisabled = BarIcon("kalarm_disabled");
	if (mPixmapEnabled.isNull() || mPixmapDisabled.isNull())
		KMessageBox::sorry(this, i18n("Can't load system tray icon!"),
		                         i18n("%1 Error").arg(kapp->aboutData()->programName()));

	mActionQuit = KStdAction::quit(this, SLOT(slotQuit()), &mActionCollection);

	// Set up the context menu
	ActionAlarmsEnabled* a = theApp()->actionAlarmEnable();
	mAlarmsEnabledId = a->itemId(a->plug(contextMenu()));
	connect(a, SIGNAL(alarmsEnabledChange(bool)), this, SLOT(setEnabledStatus(bool)));
	theApp()->actionPreferences()->plug(contextMenu());
	theApp()->actionDaemonControl()->plug(contextMenu());

	// Set icon to correspond with the alarms enabled menu status
	DaemonGuiHandler* daemonGui = theApp()->daemonGuiHandler();
	daemonGui->checkStatus();
	setEnabledStatus(daemonGui->monitoringAlarms());

	QToolTip::add(this, kapp->aboutData()->programName());
}

TrayWindow::~TrayWindow()
{
	kdDebug(5950) << "TrayWindow::~TrayWindow()\n";
	theApp()->removeWindow(this);
	emit deleted();
}

/******************************************************************************
* Called just before the context menu is displayed.
* Modify the Quit context menu item to only close the system tray widget.
*/
void TrayWindow::contextMenuAboutToShow(KPopupMenu* menu)
{
	if (!mQuitReplaced)
	{
		// Prevent Quit from quitting the program
		QString quitText = mActionQuit->text();
		for (unsigned n = 0;  n < menu->count();  ++n)
		{
			QString txt = menu->text(menu->idAt(n));
			if (txt.startsWith(quitText))
			{
				menu->removeItemAt(n);
				break;
			}
		}
		mActionQuit->plug(menu);
		mQuitReplaced = true;
	}

	// Update the Alarms Enabled item status
	theApp()->daemonGuiHandler()->checkStatus();
}

/******************************************************************************
* Called when the Quit context menu item is selected.
* Closes the system tray window, and if in 'run in system tray' mode closes all
* main windows, but does not exit the program if other windows are still open.
*/
void TrayWindow::slotQuit()
{
	kdDebug(5950)<<"TrayWindow::slotQuit()\n";
	if (theApp()->alarmsDisabledIfStopped()
	&&  KMessageBox::warningYesNo(this, i18n("Quitting will disable alarms\n"
	                                         "(once any alarm message windows are closed)."),
	                              QString::null, mActionQuit->text(), KStdGuiItem::cancel(),
	                              QString::fromLatin1("QuitWarn")
	                             ) != KMessageBox::Yes)
		return;
	if (theApp()->wantRunInSystemTray())
	{
		if (!MessageWin::instanceCount())
			theApp()->quit();
		else
			KAlarmMainWindow::closeAll();
	}
	theApp()->displayTrayIcon(false);
}

/******************************************************************************
* Called to allow quit warning messages again.
*/
void TrayWindow::allowQuitWarning()
{
	KConfig* config = kapp->config();
	config->setGroup(QString::fromLatin1("Notification Messages"));
	config->writeEntry(QString::fromLatin1("QuitWarn"), false);
	config->sync();
}

/******************************************************************************
* Called when the Alarms Enabled action status has changed.
* Updates the alarms enabled menu item check state, and the icon pixmap.
*/
void TrayWindow::setEnabledStatus(bool status)
{
	kdDebug(5950)<<"TrayWindow::setEnabledStatus(" << (int)status << ")\n";
	setPixmap(status ? mPixmapEnabled : mPixmapDisabled);
	contextMenu()->setItemChecked(mAlarmsEnabledId, status);
}

/******************************************************************************
*  Called when the mouse is clicked over the panel icon.
*  A left click displays the KAlarm main window.
*/
void TrayWindow::mousePressEvent(QMouseEvent* e)
{

	if (e->button() == LeftButton  &&  !theApp()->wantRunInSystemTray())
	{
		// Left click: display/hide the first main window
		mAssocMainWindow = KAlarmMainWindow::toggleWindow(mAssocMainWindow);
	}
	else
		KSystemTray::mousePressEvent(e);
}

/******************************************************************************
*  Called when the mouse is released over the panel icon.
*  The main window (if not hidden) is raised and made the active window.
*  If this is done in mousePressEvent(), it doesn't work.
*/
void TrayWindow::mouseReleaseEvent(QMouseEvent* e)
{

	if (e->button() == LeftButton  &&  mAssocMainWindow  &&  mAssocMainWindow->isVisible())
	{
		mAssocMainWindow->raise();
		mAssocMainWindow->setActiveWindow();
	}
	else
		KSystemTray::mouseReleaseEvent(e);
}

/******************************************************************************
* Called when the associated main window is closed.
*/
void TrayWindow::removeWindow(KAlarmMainWindow* win)
{
	if (win == mAssocMainWindow)
		mAssocMainWindow = 0;
}

#ifdef HAVE_X11_HEADERS
	#include <X11/X.h>
	#include <X11/Xlib.h>
	#include <X11/Xutil.h>
#endif

/******************************************************************************
* Check whether the widget is in the system tray.
* Note that it is only sometime AFTER the show event that the system tray
* becomes the widget's parent. So for a definitive status, call this method
* only after waiting a bit...
* Reply = true if the widget is in the system tray, or its status can't be determined.
*       = false if it is not currently in the system tray.
*/
bool TrayWindow::inSystemTray() const
{
#ifdef HAVE_X11_HEADERS
	Window  xParent;    // receives parent window
	Window  root;
	Window* children = 0;
	unsigned int nchildren;
  // Find the X parent window of the widget. This is not the same as the Qt parent widget.
	if (!XQueryTree(qt_xdisplay(), winId(), &root, &xParent, &children, &nchildren))
		return true;    // error determining its parent X window
	if (children)
		XFree(children);

	// If it is in the system tray, the system tray window will be its X parent.
	// Otherwise, the root window will be its X parent.
	return xParent != root;
#else
	return true;
#endif // HAVE_X11_HEADERS
}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <string>
#include <boost/asio.hpp>

#include "util.h"
#include "Log.h"

#ifdef WIN32
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sysinfoapi.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <shlobj.h>

#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif // _MSC_VER

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

// inet_pton exists Windows since Vista, but XP haven't that function!
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
int inet_pton_xp(int af, const char *src, void *dst)
{
	struct sockaddr_storage ss;
	int size = sizeof (ss);
	char src_copy[INET6_ADDRSTRLEN + 1];

	ZeroMemory (&ss, sizeof (ss));
	strncpy (src_copy, src, INET6_ADDRSTRLEN + 1);
	src_copy[INET6_ADDRSTRLEN] = 0;

	if (WSAStringToAddress (src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
	{
		switch (af)
		{
		case AF_INET:
			*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
			return 1;
		case AF_INET6:
			*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
			return 1;
		}
	}
	return 0;
}
#else /* !WIN32 => UNIX */
#include <sys/types.h>
#include <ifaddrs.h>
#endif

namespace i2p
{
namespace util
{
namespace net
{
#ifdef WIN32
	bool IsWindowsXPorLater()
	{
		OSVERSIONINFO osvi;

		ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
		GetVersionEx(&osvi);

		if (osvi.dwMajorVersion <= 5)
			return true;
		else
			return false;
	}

	int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;

			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv4 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr;
				if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					return result;
				}
				pUnicast = pUnicast->Next;
			}
			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv4 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindowsIpv6(sockaddr_in6 inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		bool found_address = false;
		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;
			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv6 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr;

				for (int j = 0; j != 8; ++j)
				{
					if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j])
						break;
					else
						found_address = true;
				}

				if (found_address)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					pAddresses = nullptr;
					return result;
				}
				pUnicast = pUnicast->Next;
			}

			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv6 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback)
	{
#ifdef UNICODE
		string localAddress_temporary = localAddress.to_string();
		wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end());
#else
		std::string localAddressUniversal = localAddress.to_string();
#endif

		if (IsWindowsXPorLater())
		{
			#define inet_pton inet_pton_xp
		}

		if(localAddress.is_v4())
		{
			sockaddr_in inputAddress;
			inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
			return GetMTUWindowsIpv4(inputAddress, fallback);
		}
		else if(localAddress.is_v6())
		{
			sockaddr_in6 inputAddress;
			inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
			return GetMTUWindowsIpv6(inputAddress, fallback);
		} else {
			LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
			return fallback;
		}
	}
#else // assume unix
	int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback)
	{
		ifaddrs* ifaddr, *ifa = nullptr;
		if(getifaddrs(&ifaddr) == -1)
		{
			LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno));
			return fallback;
		}

		int family = 0;
		// look for interface matching local address
		for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
		{
			if(!ifa->ifa_addr)
				continue;

			family = ifa->ifa_addr->sa_family;
			if(family == AF_INET && localAddress.is_v4())
			{
				sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr;
				if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4))
					break; // address matches
			}
			else if(family == AF_INET6 && localAddress.is_v6())
			{
				sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr;
				if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16))
					break; // address matches
			}
		}
		int mtu = fallback;
		if(ifa && family)
		{ // interface found?
			int fd = socket(family, SOCK_DGRAM, 0);
			if(fd > 0)
			{
				ifreq ifr;
				strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query
				if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0)
					mtu = ifr.ifr_mtu; // MTU
				else
					LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno));
				close(fd);
			}
			else
				LogPrint(eLogError, "NetIface: Failed to create datagram socket");
		}
		else
			LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found");
		freeifaddrs(ifaddr);

		return mtu;
	}
#endif // WIN32

	int GetMTU(const boost::asio::ip::address& localAddress)
	{
		const int fallback = 576; // fallback MTU

#ifdef WIN32
		return GetMTUWindows(localAddress, fallback);
#else
		return GetMTUUnix(localAddress, fallback);
#endif
		return fallback;
	}

	const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
	{
#ifdef WIN32
		LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
		if(ipv6)
			return boost::asio::ip::address::from_string("::1");
		else
			return boost::asio::ip::address::from_string("127.0.0.1");
#else
		int af = (ipv6 ? AF_INET6 : AF_INET);
		ifaddrs * addrs = nullptr;
		if(getifaddrs(&addrs) == 0)
		{
			// got ifaddrs
			ifaddrs * cur = addrs;
			while(cur)
			{
				std::string cur_ifname(cur->ifa_name);
				if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
				{
					// match
					char  addr[INET6_ADDRSTRLEN];
					memset (addr, 0, INET6_ADDRSTRLEN);
					if(af == AF_INET)
						inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
					else
						inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN);
					freeifaddrs(addrs);
					std::string cur_ifaddr(addr);
					return boost::asio::ip::address::from_string(cur_ifaddr);
				}
				cur = cur->ifa_next;
			}
		}
		if(addrs) freeifaddrs(addrs);
		std::string fallback;
		if(ipv6)
		{
			fallback = "::1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname);
		} else {
			fallback = "127.0.0.1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
		}
		return boost::asio::ip::address::from_string(fallback);

#endif
	}
}
} // util
} // i2p
<commit_msg>correct implementation of GetMTUWindows for WindowsXP<commit_after>#include <cstdlib>
#include <string>
#include <boost/asio.hpp>

#include "util.h"
#include "Log.h"

#ifdef WIN32
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sysinfoapi.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <shlobj.h>

#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif // _MSC_VER

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

// inet_pton exists Windows since Vista, but XP haven't that function!
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
int inet_pton_xp(int af, const char *src, void *dst)
{
	struct sockaddr_storage ss;
	int size = sizeof (ss);
	char src_copy[INET6_ADDRSTRLEN + 1];

	ZeroMemory (&ss, sizeof (ss));
	strncpy (src_copy, src, INET6_ADDRSTRLEN + 1);
	src_copy[INET6_ADDRSTRLEN] = 0;

	if (WSAStringToAddress (src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
	{
		switch (af)
		{
		case AF_INET:
			*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
			return 1;
		case AF_INET6:
			*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
			return 1;
		}
	}
	return 0;
}
#else /* !WIN32 => UNIX */
#include <sys/types.h>
#include <ifaddrs.h>
#endif

namespace i2p
{
namespace util
{
namespace net
{
#ifdef WIN32
	bool IsWindowsXPorLater()
	{
	    static bool isRequested = false;
	    static bool isXP = false;
	    if (!isRequested)
	    {
	        // request
            OSVERSIONINFO osvi;

            ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
            osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
            GetVersionEx(&osvi);

            isXP = osvi.dwMajorVersion <= 5;
            isRequested = true;
        }
        return isXP;
	}

	int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;

			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv4 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr;
				if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					return result;
				}
				pUnicast = pUnicast->Next;
			}
			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv4 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindowsIpv6(sockaddr_in6 inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		bool found_address = false;
		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;
			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv6 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr;

				for (int j = 0; j != 8; ++j)
				{
					if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j])
						break;
					else
						found_address = true;
				}

				if (found_address)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					pAddresses = nullptr;
					return result;
				}
				pUnicast = pUnicast->Next;
			}

			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv6 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback)
	{
#ifdef UNICODE
		string localAddress_temporary = localAddress.to_string();
		wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end());
#else
		std::string localAddressUniversal = localAddress.to_string();
#endif

		bool isXP = IsWindowsXPorLater();
		{
			#define inet_pton inet_pton_xp
		}

		if(localAddress.is_v4())
		{
			sockaddr_in inputAddress;
			if (isXP)
                inet_pton_xp(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
            else
                inet_pton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
			return GetMTUWindowsIpv4(inputAddress, fallback);
		}
		else if(localAddress.is_v6())
		{
			sockaddr_in6 inputAddress;
			if (isXP)
                 inet_pton_xp(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
            else
                inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
			return GetMTUWindowsIpv6(inputAddress, fallback);
		} else {
			LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
			return fallback;
		}
	}
#else // assume unix
	int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback)
	{
		ifaddrs* ifaddr, *ifa = nullptr;
		if(getifaddrs(&ifaddr) == -1)
		{
			LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno));
			return fallback;
		}

		int family = 0;
		// look for interface matching local address
		for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
		{
			if(!ifa->ifa_addr)
				continue;

			family = ifa->ifa_addr->sa_family;
			if(family == AF_INET && localAddress.is_v4())
			{
				sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr;
				if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4))
					break; // address matches
			}
			else if(family == AF_INET6 && localAddress.is_v6())
			{
				sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr;
				if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16))
					break; // address matches
			}
		}
		int mtu = fallback;
		if(ifa && family)
		{ // interface found?
			int fd = socket(family, SOCK_DGRAM, 0);
			if(fd > 0)
			{
				ifreq ifr;
				strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query
				if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0)
					mtu = ifr.ifr_mtu; // MTU
				else
					LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno));
				close(fd);
			}
			else
				LogPrint(eLogError, "NetIface: Failed to create datagram socket");
		}
		else
			LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found");
		freeifaddrs(ifaddr);

		return mtu;
	}
#endif // WIN32

	int GetMTU(const boost::asio::ip::address& localAddress)
	{
		const int fallback = 576; // fallback MTU

#ifdef WIN32
		return GetMTUWindows(localAddress, fallback);
#else
		return GetMTUUnix(localAddress, fallback);
#endif
		return fallback;
	}

	const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
	{
#ifdef WIN32
		LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
		if(ipv6)
			return boost::asio::ip::address::from_string("::1");
		else
			return boost::asio::ip::address::from_string("127.0.0.1");
#else
		int af = (ipv6 ? AF_INET6 : AF_INET);
		ifaddrs * addrs = nullptr;
		if(getifaddrs(&addrs) == 0)
		{
			// got ifaddrs
			ifaddrs * cur = addrs;
			while(cur)
			{
				std::string cur_ifname(cur->ifa_name);
				if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
				{
					// match
					char  addr[INET6_ADDRSTRLEN];
					memset (addr, 0, INET6_ADDRSTRLEN);
					if(af == AF_INET)
						inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
					else
						inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN);
					freeifaddrs(addrs);
					std::string cur_ifaddr(addr);
					return boost::asio::ip::address::from_string(cur_ifaddr);
				}
				cur = cur->ifa_next;
			}
		}
		if(addrs) freeifaddrs(addrs);
		std::string fallback;
		if(ipv6)
		{
			fallback = "::1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname);
		} else {
			fallback = "127.0.0.1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
		}
		return boost::asio::ip::address::from_string(fallback);

#endif
	}
}
} // util
} // i2p
<|endoftext|>


<commit_before>#include "gtest/gtest.h"
TEST(DISABLED_Punishers, PunisherDaemon) {}
//
//#include <forward_list>
//
//#include "ZBE/core/daemons/Daemon.h"
//#include "ZBE/core/daemons/PunisherDaemon.h"
//#include "ZBE/core/daemons/Punishers.h"
//
//#include "ZBE/core/behaviors/Behavior.h"
//#include "ZBE/core/drawers/Drawer.h"
//
//#include "ZBE/core/tools/containers/ListManager.h"
//
//namespace Punishers {
//
//class MockEntity {
//  public:
//    MockEntity():data(0){}
//    int data;
//};
//
//class MockPunish {
//  public:
//    void apply(MockEntity * e) { e->data = 1; };
//};
//
//class MockBehavior: public zbe::Behavior<MockEntity> {
//  public:
//    void apply(MockEntity * e, uint64_t) { e->data = 2; };
//};
//
//class MockDrawer: public zbe::Drawer<MockEntity> {
//  public:
//    void apply(MockEntity * e) { e->data = 3; };
//};
//
//TEST(Punishers, PunisherDaemon) {
//    MockEntity a,b,c,d;
//    zbe::ListManager<std::forward_list<MockEntity*> > & lm =zbe::ListManager<std::forward_list<MockEntity*> >::getInstance();
//    lm.insert(0,new std::forward_list<MockEntity*>());
//    lm.insert(1,new std::forward_list<MockEntity*>());
//    std::forward_list<MockEntity*> * eList0 = lm.get(0);
//    std::forward_list<MockEntity*> * eList1 = lm.get(1);
//    eList0->push_front(&a);
//    eList0->push_front(&b);
//    eList1->push_front(&c);
//    eList1->push_front(&d);
//    zbe::Daemon* daemon = new zbe::PunisherDaemon<MockPunish,std::forward_list<MockEntity*> >(new MockPunish, 0);
//    daemon->run();
//    EXPECT_EQ(1, a.data) << "a must has been punished";
//    EXPECT_EQ(1, b.data) << "b must has been punished";
//    EXPECT_EQ(0, c.data) << "c must has not been punished";
//    EXPECT_EQ(0, d.data) << "d must has not been punished";
//    delete eList0;
//    delete eList1;
//}
//
//TEST(Punishers, BehaviorDaemon) {
//    MockEntity a,b,c,d;
//    zbe::ListManager<std::forward_list<MockEntity*> > & lm =zbe::ListManager<std::forward_list<MockEntity*> >::getInstance();
//    lm.insert(0,new std::forward_list<MockEntity*>());
//    lm.insert(1,new std::forward_list<MockEntity*>());
//    std::forward_list<MockEntity*> * eList0 = lm.get(0);
//    std::forward_list<MockEntity*> * eList1 = lm.get(1);
//    eList0->push_front(&a);
//    eList0->push_front(&b);
//    eList1->push_front(&c);
//    eList1->push_front(&d);
//    zbe::Daemon* daemon = new zbe::BehaviorDaemon<MockEntity, std::forward_list<MockEntity*> >(new MockBehavior, 0);
//    daemon->run();
//    EXPECT_EQ(2, a.data) << "a must has been punished";
//    EXPECT_EQ(2, b.data) << "b must has been punished";
//    EXPECT_EQ(0, c.data) << "c must has not been punished";
//    EXPECT_EQ(0, d.data) << "d must has not been punished";
//    delete eList0;
//    delete eList1;
//} //BehaviorDaemon //DrawerDaemon
//
//TEST(Punishers, DrawerDaemon) {
//    MockEntity a,b,c,d;
//    zbe::ListManager<std::forward_list<MockEntity*> > & lm =zbe::ListManager<std::forward_list<MockEntity*> >::getInstance();
//    lm.insert(0,new std::forward_list<MockEntity*>());
//    lm.insert(1,new std::forward_list<MockEntity*>());
//    std::forward_list<MockEntity*> * eList0 = lm.get(0);
//    std::forward_list<MockEntity*> * eList1 = lm.get(1);
//    eList0->push_front(&a);
//    eList0->push_front(&b);
//    eList1->push_front(&c);
//    eList1->push_front(&d);
//    zbe::Daemon* daemon = new zbe::DrawerDaemon<MockEntity, std::forward_list<MockEntity*> >(new MockDrawer, 0);
//    daemon->run();
//    EXPECT_EQ(3, a.data) << "a must has been punished";
//    EXPECT_EQ(3, b.data) << "b must has been punished";
//    EXPECT_EQ(0, c.data) << "c must has not been punished";
//    EXPECT_EQ(0, d.data) << "d must has not been punished";
//    delete eList0;
//    delete eList1;
//}
//
//}
//
<commit_msg>issue #52. Done.<commit_after>#include "gtest/gtest.h"

#include <forward_list>

#include "ZBE/core/daemons/Daemon.h"
#include "ZBE/core/daemons/PunisherDaemon.h"
#include "ZBE/core/daemons/Punishers.h"

#include "ZBE/core/behaviors/Behavior.h"
#include "ZBE/core/drawers/Drawer.h"

#include "ZBE/core/tools/containers/ListManager.h"

namespace Punishers {

class MockEntity {
  public:
    MockEntity() : data(0){}
    int data;
};

class MockPunish {
  public:
    void apply(MockEntity * me) { me->data = 1; };
};

class MockTimedPunish {
  public:
    void apply(MockEntity * me, int64_t) { me->data = 2; };
};

TEST(PunisherDaemon, PunisherDaemon) {
    MockEntity a,b,c,d;
    zbe::ListManager<std::forward_list<MockEntity*> > & lm =zbe::ListManager<std::forward_list<MockEntity*> >::getInstance();
    lm.insert(0,new std::forward_list<MockEntity*>());
    lm.insert(1,new std::forward_list<MockEntity*>());
    std::forward_list<MockEntity*> * eList0 = lm.get(0);
    std::forward_list<MockEntity*> * eList1 = lm.get(1);
    eList0->push_front(&a);
    eList0->push_front(&b);
    eList1->push_front(&c);
    eList1->push_front(&d);
    zbe::Daemon* daemon = new zbe::PunisherDaemon<MockPunish, std::forward_list<MockEntity*> >(std::make_shared<MockPunish>(), 0);
    daemon->run();
    EXPECT_EQ(1, a.data) << "a must has been punished";
    EXPECT_EQ(1, b.data) << "b must has been punished";
    EXPECT_EQ(0, c.data) << "c must has not been punished";
    EXPECT_EQ(0, d.data) << "d must has not been punished";
    delete eList0;
    delete eList1;
}

TEST(PunisherDaemon, TimedPunisherDaemon) {
    MockEntity a,b,c,d;
    zbe::ListManager<std::forward_list<MockEntity*> > & lm =zbe::ListManager<std::forward_list<MockEntity*> >::getInstance();
    lm.insert(0,new std::forward_list<MockEntity*>());
    lm.insert(1,new std::forward_list<MockEntity*>());
    std::forward_list<MockEntity*> * eList0 = lm.get(0);
    std::forward_list<MockEntity*> * eList1 = lm.get(1);
    eList0->push_front(&a);
    eList0->push_front(&b);
    eList1->push_front(&c);
    eList1->push_front(&d);
    zbe::TimedDaemon* daemon = new zbe::TimedPunisherDaemon<MockTimedPunish, std::forward_list<MockEntity*> >(std::make_shared<MockTimedPunish>(), 0);
    daemon->run(42);
    EXPECT_EQ(2, a.data) << "a must has been punished";
    EXPECT_EQ(2, b.data) << "b must has been punished";
    EXPECT_EQ(0, c.data) << "c must has not been punished";
    EXPECT_EQ(0, d.data) << "d must has not been punished";
    delete eList0;
    delete eList1;
}

}
<|endoftext|>