<commit_before>// @(#)root/ged:$Id$
// Author: Guido Volpi 12/10/2007

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TPieEditor                                                          //
//                                                                      //
//  Implements GUI for pie-chart attributes.                            //
//                                                                      //
//  Title': set the title of the graph                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
//Begin_Html
/*

*/
//End_Html

#include "TGedEditor.h"
#include "TGComboBox.h"
#include "TGButtonGroup.h"
#include "TPieEditor.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGToolTip.h"
#include "TGLabel.h"
#include "TPie.h"
#include "TVirtualPad.h"
#include "TGColorSelect.h"
#include "TGComboBox.h"
#include "TColor.h"
#include "TBox.h"
#include "TPaveLabel.h"

ClassImp(TPieEditor)

enum EPieWid {
   kPie = 0,
   kPIE_HOR,
   kPIE_RAD,
   kPIE_TAN,
   kPIE_FILL,
   kPIE_OUTLINE,
   kPIE_TITLE,
   kPIE_3D,
   kPIE_3DANGLE,
   kPIE_3DTHICKNESS,
   kFONT_COLOR,
   kFONT_SIZE,
   kFONT_STYLE
};

//______________________________________________________________________________
TPieEditor::TPieEditor(const TGWindow *p, Int_t width,
                         Int_t height, UInt_t options, Pixel_t back)
   : TGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor of graph editor.

   fPie = 0;
   // TextEntry to change the title
   MakeTitle("Pie Chart");

   fTitle = new TGTextEntry(this, new TGTextBuffer(50), kPIE_TITLE);
   fTitle->Resize(135, fTitle->GetDefaultHeight());
   fTitle->SetToolTipText("Enter the pie title string");
   // better take kLHintsLeft and Right - Right is not working at the moment
   AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   // Radio Buttons to change the draw options of the graph
   TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
   fgr = new TGButtonGroup(f2,3,1,3,5,"Label direction");
   fgr->SetRadioButtonExclusive(kTRUE);
   fLblDirH = new TGRadioButton(fgr,"Horizontal",kPIE_HOR);   // no draw option
   fLblDirH->SetToolTipText("Draw horizontal labels");
   fLblDirR = new TGRadioButton(fgr,"Radial",kPIE_RAD);  // option C
   fLblDirR->SetToolTipText("Draw labels radially");
   fLblDirT = new TGRadioButton(fgr,"Tangential",kPIE_TAN); // option L
   fLblDirT->SetToolTipText("Draw labels tangential to the piechart");

   fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fLblDirH);
   fgr->Show();
   fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
   f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));

   // CheckBox to activate/deactivate the drawing of the Marker
   fOutlineOnOff = new TGCheckButton(f2,"Outline",kPIE_OUTLINE);
   fOutlineOnOff->SetToolTipText("Draw a line to mark the pie");
   f2->AddFrame(fOutlineOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
   AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));

   // Exclusion zone parameters
   MakeTitle("3D options");
   TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));

   fIs3D = new TGCheckButton(f3,"3D",kPIE_3D);
   fIs3D->SetToolTipText("Draw a 3D charts");
   f3->AddFrame(fIs3D, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));

   f3DAngle = new TGNumberEntry(f3, 0, 2, kPIE_3DANGLE,  TGNumberEntry::kNESInteger, TGNumberEntry::kNEANonNegative,TGNumberFormat::kNELLimitMinMax, 0, 90);
   //f3DAngle->SetToolTipText("3D angle: 0-90")
   f3DAngle->Resize(50, 20);
   f3->AddFrame(f3DAngle, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DAngle->Associate(f3);

   f3DHeight = new TGNumberEntry(f3, 0, 3, kPIE_3DTHICKNESS,  TGNumberEntry::kNESReal, TGNumberEntry::kNEANonNegative);
   //f3DHeight->SetToolTipText("3D thick")
   f3DHeight->Resize(50, 20);
   f3->AddFrame(f3DHeight, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DHeight->Associate(f3);

   MakeTitle("Text");
   TGCompositeFrame *f4 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   fColorSelect = new TGColorSelect(f4, 0, kFONT_COLOR);
   f4->AddFrame(fColorSelect, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
   fColorSelect->Associate(this);
   fSizeCombo = BuildFontSizeComboBox(f4, kFONT_SIZE);
   f4->AddFrame(fSizeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
   fSizeCombo->Resize(91, 20);
   fSizeCombo->Associate(this);
   AddFrame(f4, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
   fTypeCombo = new TGFontTypeComboBox(this, kFONT_STYLE);
   fTypeCombo->Resize(137, 20);
   AddFrame(fTypeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
}

//______________________________________________________________________________
TPieEditor::~TPieEditor()
{
   // Destructor of pie editor.
}

//_____________________________________________________________________________
void TPieEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.

   fTitle->Connect("TextChanged(const char *)","TPieEditor",this,"DoTitle(const char *)");
   fgr->Connect("Clicked(Int_t)","TPieEditor",this,"DoShape()");
   fOutlineOnOff->Connect("Toggled(Bool_t)","TPieEditor",this,"DoMarkerOnOff(Bool_t)");
   f3DAngle->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   f3DHeight->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   fIs3D->Connect("Clicked()","TPieEditor",this,"DoGraphLineWidth()");

   // text attributes connection
   fTypeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fSizeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fColorSelect->Connect("ColorSelected(Pixel_t)","TPieEditor",this,"DoTextChange()");

   fInit = kFALSE;  // connect the slots to the signals only once
}

//______________________________________________________________________________
void TPieEditor::ActivateBaseClassEditors(TClass* cl)
{
   // Exclude TAttTextEditor from this interface.

   TGedEditor *gedEditor = GetGedEditor();
   gedEditor->ExcludeClassEditor(TAttText::Class());
   TGedFrame::ActivateBaseClassEditors(cl);
}

//______________________________________________________________________________
void TPieEditor::SetModel(TObject* obj)
{
   // Pick up the used values of graph attributes.

   fPie = (TPie *)obj;
   fAvoidSignal = kTRUE;

   // set the Title TextEntry
   const char *text = fPie->GetTitle();
   fTitle->SetText(text);

   TString soption = GetDrawOption();

   bool optionSame(kFALSE);

   // For the label orientation there are 3 possibilities:
   //   0: horizontal
   //   1: radial
   //   2: tangent
   Int_t lblor(0);

   // Parse the options
   Int_t idx;
   // Paint the TPie in an existing canvas
   if ( (idx=soption.Index("same"))>=0 ) {
      optionSame = kTRUE;
      soption.Remove(idx,4);
   }

   if ( (idx=soption.Index("nol"))>=0 ) {
      fOutlineOnOff->SetState(kButtonUp,kFALSE);
      soption.Remove(idx,3);
   }
   else {
      fOutlineOnOff->SetState(kButtonDown,kFALSE);
   }

   // check if is active the pseudo-3d
   if ( (idx=soption.Index("3d"))>=0 ) {
      fIs3D->SetState(kButtonDown, kFALSE);
      f3DAngle->SetNumber(fPie->GetAngle3D());
      f3DHeight->SetNumber(fPie->GetHeight());
      soption.Remove(idx,2);
   } else {
      fIs3D->SetState(kButtonUp, kFALSE);
   }

   // seek if have to draw the labels around the pie chart
   if ( (idx=soption.Index("t"))>=0 ) {
      lblor = 2;
      soption.Remove(idx,1);
   }

   // Seek if have to paint the labels along the radii
   if ( (idx=soption.Index("r"))>=0 ) {
      lblor = 1;
      soption.Remove(idx,1);
   }

   switch(lblor) {
   case 0:
      fLblDirH->SetState(kButtonDown,kTRUE);
      break;
   case 1:
      fLblDirR->SetState(kButtonDown,kTRUE);
      break;
   case 2:
      fLblDirT->SetState(kButtonDown,kTRUE);
      break;
   }

   // set text attributes
   fTypeCombo->Select(fPie->GetTextFont() / 10);

   Color_t c = fPie->GetTextColor();
   Pixel_t p = TColor::Number2Pixel(c);
   fColorSelect->SetColor(p, kFALSE);

   Float_t s = fPie->GetTextSize();
   Float_t dy;

   if (obj->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)obj;
      dy = s * (pl->GetY2() - pl->GetY1());
   }
   else
      dy = s * (fGedEditor->GetPad()->GetY2() - fGedEditor->GetPad()->GetY1());

   Int_t size = fGedEditor->GetPad()->YtoPixel(0.0) - fGedEditor->GetPad()->YtoPixel(dy);
   if (size > 50) size = 50;
   if (size < 0)  size = 0;
   fSizeCombo->Select(size, kFALSE);

   if (fInit) ConnectSignals2Slots();
   fAvoidSignal = kFALSE;
}

//______________________________________________________________________________
void TPieEditor::DoTitle(const char *text)
{
   // Slot for setting the graph title.

   if (fAvoidSignal) return;
   fPie->SetTitle(text);
   Update();
}

//______________________________________________________________________________
void TPieEditor::DoShape()
{
   // Slot connected to the draw options.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();

   if (fLblDirH->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }
   else if (fLblDirR->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (!opt.Contains("r")) opt += "r";
   }
   else if (fLblDirT->GetState()==kButtonDown) {
      if (!opt.Contains("t")) opt += "t";
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }

   SetDrawOption(opt);
   if (gPad) gPad->GetVirtCanvas()->SetCursor(kPointer);
   gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
}

//______________________________________________________________________________
void TPieEditor::DoMarkerOnOff(Bool_t)
{
   // Slot for setting markers as visible/invisible.

   if (fAvoidSignal) return;
   TString t = GetDrawOption();

   if (t.Contains("nol") && fOutlineOnOff->GetState() == kButtonDown) {
      t.Remove(t.First("nol"),3);
   }
   else if (!t.Contains("nol") && fOutlineOnOff->GetState() == kButtonUp) {
      t += "nol";
   }

   SetDrawOption(t);
}

//______________________________________________________________________________
void TPieEditor::DoChange3DAngle()
{
   // Slot for setting the 3D angle
   if (fAvoidSignal) return;

   fPie->SetAngle3D(static_cast<Int_t>(f3DAngle->GetNumber()));
   fPie->SetHeight(f3DHeight->GetNumber());

   Update();

}

//______________________________________________________________________________
void TPieEditor::DoGraphLineWidth()
{
   // Slot connected to the graph line width.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();
   if (!opt.Contains("3d") && fIs3D->IsDown())
      opt += "3d";
   else if (opt.Contains("3d") && !fIs3D->IsDown())
      opt.Remove(opt.First("3d"),2);

   SetDrawOption(opt);

   Update();
}

//______________________________________________________________________________
void TPieEditor::DoTextChange()
{
   // Change text.

   if (fAvoidSignal) return;

   // font color
   fPie->SetTextColor(TColor::GetColor(fColorSelect->GetColor()));

   // font type
   Int_t fontPrec = fPie->GetTextFont()%10;
   Int_t fontType = fTypeCombo->GetSelected();
   fPie->SetTextFont(fontType*10+fontPrec);

   // font size
   TVirtualPad* pad = fGedEditor->GetPad();

   Float_t val = TString(fSizeCombo->GetSelectedEntry()->GetTitle()).Atoi();

   Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY((Int_t)val);
   Float_t textSize;

   if (fGedEditor->GetModel()->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)fGedEditor->GetModel();
      textSize = dy/(pl->GetY2() - pl->GetY1());
   }
   else
      textSize = dy/(pad->GetY2() - pad->GetY1());

   fPie->SetTextSize(textSize);

   Update();

}

//______________________________________________________________________________
TGComboBox* TPieEditor::BuildFontSizeComboBox(TGFrame* parent, Int_t id)
{
   // Create text size combo box.

   char a[100];
   TGComboBox *c = new TGComboBox(parent, id);

   c->AddEntry("Default", 0);
   for (int i = 1; i <= 50; i++) {
      snprintf(a, 99, "%d", i);
      c->AddEntry(a, i);
   }

   return c;
}
<commit_msg>Fix coverity report #33681 (dereference null return)<commit_after>// @(#)root/ged:$Id$
// Author: Guido Volpi 12/10/2007

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
//  TPieEditor                                                          //
//                                                                      //
//  Implements GUI for pie-chart attributes.                            //
//                                                                      //
//  Title': set the title of the graph                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
//Begin_Html
/*

*/
//End_Html

#include "TGedEditor.h"
#include "TGComboBox.h"
#include "TGButtonGroup.h"
#include "TPieEditor.h"
#include "TGTextEntry.h"
#include "TGNumberEntry.h"
#include "TGToolTip.h"
#include "TGLabel.h"
#include "TPie.h"
#include "TVirtualPad.h"
#include "TGColorSelect.h"
#include "TGComboBox.h"
#include "TColor.h"
#include "TBox.h"
#include "TPaveLabel.h"

ClassImp(TPieEditor)

enum EPieWid {
   kPie = 0,
   kPIE_HOR,
   kPIE_RAD,
   kPIE_TAN,
   kPIE_FILL,
   kPIE_OUTLINE,
   kPIE_TITLE,
   kPIE_3D,
   kPIE_3DANGLE,
   kPIE_3DTHICKNESS,
   kFONT_COLOR,
   kFONT_SIZE,
   kFONT_STYLE
};

//______________________________________________________________________________
TPieEditor::TPieEditor(const TGWindow *p, Int_t width,
                         Int_t height, UInt_t options, Pixel_t back)
   : TGedFrame(p, width, height, options | kVerticalFrame, back)
{
   // Constructor of graph editor.

   fPie = 0;
   // TextEntry to change the title
   MakeTitle("Pie Chart");

   fTitle = new TGTextEntry(this, new TGTextBuffer(50), kPIE_TITLE);
   fTitle->Resize(135, fTitle->GetDefaultHeight());
   fTitle->SetToolTipText("Enter the pie title string");
   // better take kLHintsLeft and Right - Right is not working at the moment
   AddFrame(fTitle, new TGLayoutHints(kLHintsLeft, 3, 1, 2, 5));

   // Radio Buttons to change the draw options of the graph
   TGCompositeFrame *f2 = new TGCompositeFrame(this, 80, 20, kVerticalFrame);
   fgr = new TGButtonGroup(f2,3,1,3,5,"Label direction");
   fgr->SetRadioButtonExclusive(kTRUE);
   fLblDirH = new TGRadioButton(fgr,"Horizontal",kPIE_HOR);   // no draw option
   fLblDirH->SetToolTipText("Draw horizontal labels");
   fLblDirR = new TGRadioButton(fgr,"Radial",kPIE_RAD);  // option C
   fLblDirR->SetToolTipText("Draw labels radially");
   fLblDirT = new TGRadioButton(fgr,"Tangential",kPIE_TAN); // option L
   fLblDirT->SetToolTipText("Draw labels tangential to the piechart");

   fgr->SetLayoutHints(fShape1lh=new TGLayoutHints(kLHintsLeft, 0,3,0,0), fLblDirH);
   fgr->Show();
   fgr->ChangeOptions(kFitWidth|kChildFrame|kVerticalFrame);
   f2->AddFrame(fgr, new TGLayoutHints(kLHintsLeft, 4, 0, 0, 0));

   // CheckBox to activate/deactivate the drawing of the Marker
   fOutlineOnOff = new TGCheckButton(f2,"Outline",kPIE_OUTLINE);
   fOutlineOnOff->SetToolTipText("Draw a line to mark the pie");
   f2->AddFrame(fOutlineOnOff, new TGLayoutHints(kLHintsTop, 5, 1, 0, 3));
   AddFrame(f2, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));

   // Exclusion zone parameters
   MakeTitle("3D options");
   TGCompositeFrame *f3 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   AddFrame(f3, new TGLayoutHints(kLHintsTop, 1, 1, 5, 0));

   fIs3D = new TGCheckButton(f3,"3D",kPIE_3D);
   fIs3D->SetToolTipText("Draw a 3D charts");
   f3->AddFrame(fIs3D, new TGLayoutHints(kLHintsTop, 5, 1, 0, 0));

   f3DAngle = new TGNumberEntry(f3, 0, 2, kPIE_3DANGLE,  TGNumberEntry::kNESInteger, TGNumberEntry::kNEANonNegative,TGNumberFormat::kNELLimitMinMax, 0, 90);
   //f3DAngle->SetToolTipText("3D angle: 0-90")
   f3DAngle->Resize(50, 20);
   f3->AddFrame(f3DAngle, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DAngle->Associate(f3);

   f3DHeight = new TGNumberEntry(f3, 0, 3, kPIE_3DTHICKNESS,  TGNumberEntry::kNESReal, TGNumberEntry::kNEANonNegative);
   //f3DHeight->SetToolTipText("3D thick")
   f3DHeight->Resize(50, 20);
   f3->AddFrame(f3DHeight, new TGLayoutHints(kLHintsLeft, 7, 1, 1, 1));
   f3DHeight->Associate(f3);

   MakeTitle("Text");
   TGCompositeFrame *f4 = new TGCompositeFrame(this, 80, 20, kHorizontalFrame);
   fColorSelect = new TGColorSelect(f4, 0, kFONT_COLOR);
   f4->AddFrame(fColorSelect, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
   fColorSelect->Associate(this);
   fSizeCombo = BuildFontSizeComboBox(f4, kFONT_SIZE);
   f4->AddFrame(fSizeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
   fSizeCombo->Resize(91, 20);
   fSizeCombo->Associate(this);
   AddFrame(f4, new TGLayoutHints(kLHintsTop, 1, 1, 0, 0));
   fTypeCombo = new TGFontTypeComboBox(this, kFONT_STYLE);
   fTypeCombo->Resize(137, 20);
   AddFrame(fTypeCombo, new TGLayoutHints(kLHintsLeft, 3, 1, 1, 1));
}

//______________________________________________________________________________
TPieEditor::~TPieEditor()
{
   // Destructor of pie editor.
}

//_____________________________________________________________________________
void TPieEditor::ConnectSignals2Slots()
{
   // Connect signals to slots.

   fTitle->Connect("TextChanged(const char *)","TPieEditor",this,"DoTitle(const char *)");
   fgr->Connect("Clicked(Int_t)","TPieEditor",this,"DoShape()");
   fOutlineOnOff->Connect("Toggled(Bool_t)","TPieEditor",this,"DoMarkerOnOff(Bool_t)");
   f3DAngle->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   f3DHeight->Connect("ValueSet(Long_t)", "TPieEditor", this, "DoChange3DAngle()");
   fIs3D->Connect("Clicked()","TPieEditor",this,"DoGraphLineWidth()");

   // text attributes connection
   fTypeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fSizeCombo->Connect("Selected(Int_t)","TPieEditor",this,"DoTextChange()");
   fColorSelect->Connect("ColorSelected(Pixel_t)","TPieEditor",this,"DoTextChange()");

   fInit = kFALSE;  // connect the slots to the signals only once
}

//______________________________________________________________________________
void TPieEditor::ActivateBaseClassEditors(TClass* cl)
{
   // Exclude TAttTextEditor from this interface.

   TGedEditor *gedEditor = GetGedEditor();
   gedEditor->ExcludeClassEditor(TAttText::Class());
   TGedFrame::ActivateBaseClassEditors(cl);
}

//______________________________________________________________________________
void TPieEditor::SetModel(TObject* obj)
{
   // Pick up the used values of graph attributes.

   fPie = (TPie *)obj;
   fAvoidSignal = kTRUE;

   // set the Title TextEntry
   const char *text = fPie->GetTitle();
   fTitle->SetText(text);

   TString soption = GetDrawOption();

   bool optionSame(kFALSE);

   // For the label orientation there are 3 possibilities:
   //   0: horizontal
   //   1: radial
   //   2: tangent
   Int_t lblor(0);

   // Parse the options
   Int_t idx;
   // Paint the TPie in an existing canvas
   if ( (idx=soption.Index("same"))>=0 ) {
      optionSame = kTRUE;
      soption.Remove(idx,4);
   }

   if ( (idx=soption.Index("nol"))>=0 ) {
      fOutlineOnOff->SetState(kButtonUp,kFALSE);
      soption.Remove(idx,3);
   }
   else {
      fOutlineOnOff->SetState(kButtonDown,kFALSE);
   }

   // check if is active the pseudo-3d
   if ( (idx=soption.Index("3d"))>=0 ) {
      fIs3D->SetState(kButtonDown, kFALSE);
      f3DAngle->SetNumber(fPie->GetAngle3D());
      f3DHeight->SetNumber(fPie->GetHeight());
      soption.Remove(idx,2);
   } else {
      fIs3D->SetState(kButtonUp, kFALSE);
   }

   // seek if have to draw the labels around the pie chart
   if ( (idx=soption.Index("t"))>=0 ) {
      lblor = 2;
      soption.Remove(idx,1);
   }

   // Seek if have to paint the labels along the radii
   if ( (idx=soption.Index("r"))>=0 ) {
      lblor = 1;
      soption.Remove(idx,1);
   }

   switch(lblor) {
   case 0:
      fLblDirH->SetState(kButtonDown,kTRUE);
      break;
   case 1:
      fLblDirR->SetState(kButtonDown,kTRUE);
      break;
   case 2:
      fLblDirT->SetState(kButtonDown,kTRUE);
      break;
   }

   // set text attributes
   fTypeCombo->Select(fPie->GetTextFont() / 10);

   Color_t c = fPie->GetTextColor();
   Pixel_t p = TColor::Number2Pixel(c);
   fColorSelect->SetColor(p, kFALSE);

   Float_t s = fPie->GetTextSize();
   Float_t dy;

   if (obj->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)obj;
      dy = s * (pl->GetY2() - pl->GetY1());
   }
   else
      dy = s * (fGedEditor->GetPad()->GetY2() - fGedEditor->GetPad()->GetY1());

   Int_t size = fGedEditor->GetPad()->YtoPixel(0.0) - fGedEditor->GetPad()->YtoPixel(dy);
   if (size > 50) size = 50;
   if (size < 0)  size = 0;
   fSizeCombo->Select(size, kFALSE);

   if (fInit) ConnectSignals2Slots();
   fAvoidSignal = kFALSE;
}

//______________________________________________________________________________
void TPieEditor::DoTitle(const char *text)
{
   // Slot for setting the graph title.

   if (fAvoidSignal) return;
   fPie->SetTitle(text);
   Update();
}

//______________________________________________________________________________
void TPieEditor::DoShape()
{
   // Slot connected to the draw options.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();

   if (fLblDirH->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }
   else if (fLblDirR->GetState()==kButtonDown) {
      if (opt.Contains("t")) opt.Remove(opt.First("t"),1);
      if (!opt.Contains("r")) opt += "r";
   }
   else if (fLblDirT->GetState()==kButtonDown) {
      if (!opt.Contains("t")) opt += "t";
      if (opt.Contains("r")) opt.Remove(opt.First("r"),1);
   }

   SetDrawOption(opt);
   if (gPad && gPad->GetVirtCanvas()) gPad->GetVirtCanvas()->SetCursor(kPointer);
   gVirtualX->SetCursor(GetId(), gVirtualX->CreateCursor(kPointer));
}

//______________________________________________________________________________
void TPieEditor::DoMarkerOnOff(Bool_t)
{
   // Slot for setting markers as visible/invisible.

   if (fAvoidSignal) return;
   TString t = GetDrawOption();

   if (t.Contains("nol") && fOutlineOnOff->GetState() == kButtonDown) {
      t.Remove(t.First("nol"),3);
   }
   else if (!t.Contains("nol") && fOutlineOnOff->GetState() == kButtonUp) {
      t += "nol";
   }

   SetDrawOption(t);
}

//______________________________________________________________________________
void TPieEditor::DoChange3DAngle()
{
   // Slot for setting the 3D angle
   if (fAvoidSignal) return;

   fPie->SetAngle3D(static_cast<Int_t>(f3DAngle->GetNumber()));
   fPie->SetHeight(f3DHeight->GetNumber());

   Update();

}

//______________________________________________________________________________
void TPieEditor::DoGraphLineWidth()
{
   // Slot connected to the graph line width.

   if (fAvoidSignal) return;

   TString opt = GetDrawOption();
   if (!opt.Contains("3d") && fIs3D->IsDown())
      opt += "3d";
   else if (opt.Contains("3d") && !fIs3D->IsDown())
      opt.Remove(opt.First("3d"),2);

   SetDrawOption(opt);

   Update();
}

//______________________________________________________________________________
void TPieEditor::DoTextChange()
{
   // Change text.

   if (fAvoidSignal) return;

   // font color
   fPie->SetTextColor(TColor::GetColor(fColorSelect->GetColor()));

   // font type
   Int_t fontPrec = fPie->GetTextFont()%10;
   Int_t fontType = fTypeCombo->GetSelected();
   fPie->SetTextFont(fontType*10+fontPrec);

   // font size
   TVirtualPad* pad = fGedEditor->GetPad();

   Float_t val = TString(fSizeCombo->GetSelectedEntry()->GetTitle()).Atoi();

   Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY((Int_t)val);
   Float_t textSize;

   if (fGedEditor->GetModel()->InheritsFrom(TPaveLabel::Class())) {
      TBox *pl = (TBox*)fGedEditor->GetModel();
      textSize = dy/(pl->GetY2() - pl->GetY1());
   }
   else
      textSize = dy/(pad->GetY2() - pad->GetY1());

   fPie->SetTextSize(textSize);

   Update();

}

//______________________________________________________________________________
TGComboBox* TPieEditor::BuildFontSizeComboBox(TGFrame* parent, Int_t id)
{
   // Create text size combo box.

   char a[100];
   TGComboBox *c = new TGComboBox(parent, id);

   c->AddEntry("Default", 0);
   for (int i = 1; i <= 50; i++) {
      snprintf(a, 99, "%d", i);
      c->AddEntry(a, i);
   }

   return c;
}
<|endoftext|>


<commit_before>#pragma once

#include <cstdint>
#include <functional>
#include <string>

namespace blackhole {
inline namespace v1 {
namespace config {

template<typename T>
class option;

/// Represents the configuration tree node.
///
/// Blackhole operates with instances of this class while configuring the logging system from some
/// generic source, from file for example. It assumes that the whole configuration can be described
/// using tree data structure, like JSON, XML or YAML.
/// To be able to initialize from your own data format you must create subclass and implement its
/// converting methods as like as tree traversing using subscription operators.
///
/// Implementations are free to throw exceptions inside conversion methods on either type mismatch
/// or whatever else.
class node_t {
public:
    typedef std::function<auto(const node_t& node) -> void> each_function;
    typedef std::function<auto(const std::string& key, const node_t& node) -> void> member_function;

public:
    virtual ~node_t() = 0;

    virtual auto is_bool() const noexcept -> bool = 0;
    virtual auto is_sint64() const noexcept -> bool = 0;
    virtual auto is_uint64() const noexcept -> bool = 0;
    virtual auto is_double() const noexcept -> bool = 0;
    virtual auto is_string() const noexcept -> bool { return false; }
    virtual auto is_vector() const noexcept -> bool { return false; }
    virtual auto is_object() const noexcept -> bool { return false; }

    /// Tries to convert the underlying object to bool.
    virtual auto to_bool() const -> bool = 0;

    /// Tries to convert the underlying object to signed integer.
    virtual auto to_sint64() const -> std::int64_t = 0;

    /// Tries to convert the underlying object to unsigned integer.
    virtual auto to_uint64() const -> std::uint64_t = 0;

    /// Tries to convert the underlying object to double.
    virtual auto to_double() const -> double = 0;

    /// Tries to convert the underlying object to string.
    virtual auto to_string() const -> std::string = 0;

    /// Assuming that the underlying object is an array, performs inner iteration over it by
    /// applying the given function to each element.
    ///
    /// Should do nothing if the underlying array is empty.
    virtual auto each(const each_function& fn) const -> void = 0;

    /// Assuming that the underlying object is a map, performs inner iteration over it by applying
    /// the given function to each key-value element.
    ///
    /// Should do nothing if the underlying map is empty.
    virtual auto each_map(const member_function& fn) const -> void = 0;

    /// Assuming that the underlying object is an array performs index operation returning the
    /// option object with some node at the given index on success, none otherwise.
    ///
    /// Depending on the concrete implementation it may or not throw exceptions on out of range
    /// access.
    virtual auto operator[](const std::size_t& idx) const -> option<node_t> = 0;

    /// Assuming that the underlying object is a map performs tree traversing operation returning
    /// option object with some node at the given key on success, none otherwise.
    ///
    /// Depending on the concrete implementation it may or not throw exceptions on out of range
    /// access.
    virtual auto operator[](const std::string& key) const -> option<node_t> = 0;
};

}  // namespace config
}  // namespace v1
}  // namespace blackhole
<commit_msg>fix(config/node): purify an interface<commit_after>#pragma once

#include <cstdint>
#include <functional>
#include <string>

namespace blackhole {
inline namespace v1 {
namespace config {

template<typename T>
class option;

/// Represents the configuration tree node.
///
/// Blackhole operates with instances of this class while configuring the logging system from some
/// generic source, from file for example. It assumes that the whole configuration can be described
/// using tree data structure, like JSON, XML or YAML.
/// To be able to initialize from your own data format you must create subclass and implement its
/// converting methods as like as tree traversing using subscription operators.
///
/// Implementations are free to throw exceptions inside conversion methods on either type mismatch
/// or whatever else.
class node_t {
public:
    typedef std::function<auto(const node_t& node) -> void> each_function;
    typedef std::function<auto(const std::string& key, const node_t& node) -> void> member_function;

public:
    virtual ~node_t() = 0;

    virtual auto is_bool() const noexcept -> bool = 0;
    virtual auto is_sint64() const noexcept -> bool = 0;
    virtual auto is_uint64() const noexcept -> bool = 0;
    virtual auto is_double() const noexcept -> bool = 0;
    virtual auto is_string() const noexcept -> bool = 0;
    virtual auto is_vector() const noexcept -> bool = 0;
    virtual auto is_object() const noexcept -> bool = 0;

    /// Tries to convert the underlying object to bool.
    virtual auto to_bool() const -> bool = 0;

    /// Tries to convert the underlying object to signed integer.
    virtual auto to_sint64() const -> std::int64_t = 0;

    /// Tries to convert the underlying object to unsigned integer.
    virtual auto to_uint64() const -> std::uint64_t = 0;

    /// Tries to convert the underlying object to double.
    virtual auto to_double() const -> double = 0;

    /// Tries to convert the underlying object to string.
    virtual auto to_string() const -> std::string = 0;

    /// Assuming that the underlying object is an array, performs inner iteration over it by
    /// applying the given function to each element.
    ///
    /// Should do nothing if the underlying array is empty.
    virtual auto each(const each_function& fn) const -> void = 0;

    /// Assuming that the underlying object is a map, performs inner iteration over it by applying
    /// the given function to each key-value element.
    ///
    /// Should do nothing if the underlying map is empty.
    virtual auto each_map(const member_function& fn) const -> void = 0;

    /// Assuming that the underlying object is an array performs index operation returning the
    /// option object with some node at the given index on success, none otherwise.
    ///
    /// Depending on the concrete implementation it may or not throw exceptions on out of range
    /// access.
    virtual auto operator[](const std::size_t& idx) const -> option<node_t> = 0;

    /// Assuming that the underlying object is a map performs tree traversing operation returning
    /// option object with some node at the given key on success, none otherwise.
    ///
    /// Depending on the concrete implementation it may or not throw exceptions on out of range
    /// access.
    virtual auto operator[](const std::string& key) const -> option<node_t> = 0;
};

}  // namespace config
}  // namespace v1
}  // namespace blackhole
<|endoftext|>


<commit_before>#include "index.h"
#include "crc32c.h"
#include "exception.h"

namespace LeviDB {
    static constexpr uint32_t page_size_ = 4096;

    size_t BDNode::size() const noexcept {
        if (full()) {
            return _ptrs.size();
        }
        size_t lo = 0;
        size_t hi = IndexConst::rank_;
        while (lo < hi) {
            size_t mid = (lo + hi) / 2;
            if (_ptrs[mid].isNull()) {
                hi = mid;
            } else {
                lo = mid + 1;
            }
        }
        return lo;
    }

    bool BDEmpty::verify() const noexcept {
        return CRC32C::verify(reinterpret_cast<const char *>(this), offsetof(BDEmpty, _checksum), &_checksum[0]);
    }

    void BDEmpty::updateChecksum() noexcept {
        uint32_t checksum = CRC32C::value(reinterpret_cast<const char *>(this), offsetof(BDEmpty, _checksum));
        memcpy(&_checksum[0], &checksum, sizeof(checksum));
    }

    bool BDNode::verify() const noexcept {
        return _padding_[0] == 0 && _padding_[1] == 0
               && CRC32C::verify(reinterpret_cast<const char *>(this), offsetof(BDNode, _checksum), &_checksum[0]);
    }

    void BDNode::updateChecksum() noexcept {
        uint32_t checksum = CRC32C::value(reinterpret_cast<const char *>(this), offsetof(BDNode, _checksum));
        memcpy(&_checksum[0], &checksum, sizeof(checksum));
    }

    BDNode * BitDegradeTree::offToMemNode(OffsetToNode node) const {
        assert(sysconf(_SC_PAGESIZE) == page_size_);
        auto * mem_node = reinterpret_cast<BDNode *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region())
                                                     + node.val);
        char vec[1]{};
        if (mincore(mem_node, page_size_, vec) != 0) { throw Exception::corruptionException("mincore fail"); };
        if ((vec[0] & 1) != 1 && !mem_node->verify()) {
            throw Exception::corruptionException("i-node checksum mismatch");
        };
        return mem_node;
    }

    BDNode * BitDegradeTree::offToMemNodeUnchecked(OffsetToNode node) const noexcept {
        return reinterpret_cast<BDNode *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region()) + node.val);
    }

    BDEmpty * BitDegradeTree::offToMemEmpty(OffsetToEmpty empty) const {
        auto * mem_empty = reinterpret_cast<BDEmpty *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region())
                                                       + empty.val);
        if (!mem_empty->verify()) {
            throw Exception::corruptionException("e-node checksum mismatch");
        };
        return mem_empty;
    }

    class MatcherDebugOffset : public Matcher { // 仅用于 debug, 真正的实现由继承覆盖
    private:
        uint32_t _val; // 相当于 char[4]

    public:
        explicit MatcherDebugOffset(OffsetToData data) noexcept : _val(data.val) {}

        DEFAULT_MOVE(MatcherDebugOffset);
        DEFAULT_COPY(MatcherDebugOffset);

        ~MatcherDebugOffset() noexcept override = default;

        char operator[](size_t idx) const override {
            return reinterpret_cast<const char *>(&_val)[idx];
        };

        bool operator==(const Matcher & another) const override {
            return toString() == another.toString();
        };

        bool operator==(const Slice & another) const override {
            return toString() == another.toString();
        };

        size_t size() const override {
            return sizeof(_val);
        };

        std::string toString() const override {
            return std::string(reinterpret_cast<const char *>(&_val), sizeof(_val));
        };
    };

    std::unique_ptr<Matcher> BitDegradeTree::offToMatcher(OffsetToData data) const noexcept {
        return std::make_unique<MatcherDebugOffset>(data);
    }

    class MatcherDebugSlice : public Matcher {
    private:
        Slice _slice;

    public:
        explicit MatcherDebugSlice(const Slice & slice) noexcept : _slice(slice) {}

        DEFAULT_MOVE(MatcherDebugSlice);
        DEFAULT_COPY(MatcherDebugSlice);

        ~MatcherDebugSlice() noexcept override = default;

        char operator[](size_t idx) const override {
            return _slice[idx];
        };

        bool operator==(const Matcher & another) const override {
            return toString() == another.toString();
        };

        bool operator==(const Slice & another) const override {
            return toString() == another.toString();
        };

        size_t size() const override {
            return _slice.size();
        };

        std::string toString() const override {
            return _slice.toString();
        };
    };

    std::unique_ptr<Matcher> BitDegradeTree::sliceToMatcher(const Slice & slice) const noexcept {
        return std::make_unique<MatcherDebugSlice>(slice);
    }

    OffsetToNode BitDegradeTree::mallocNode() {
        if (_empty.val == IndexConst::disk_null_) {
            OffsetToNode res{static_cast<uint32_t>(_dst.immut_length())};
            _dst.grow();
            for (uint32_t cursor = res.val + page_size_; cursor < _dst.immut_length(); cursor += page_size_) {
                freeNode(OffsetToNode{cursor});
            }
            return res;
        }
        OffsetToNode res{_empty.val};
        _empty = offToMemEmpty(_empty)->immut_next();
        return res;
    }

    void BitDegradeTree::freeNode(OffsetToNode node) noexcept {
        auto empty = new(offToMemNodeUnchecked(node)) BDEmpty;
        empty->mut_next() = _empty;
        empty->updateChecksum();
        _empty.val = node.val;
    }
}<commit_msg>Unix/Linux conflict<commit_after>#include "index.h"
#include "crc32c.h"
#include "exception.h"

namespace LeviDB {
    static constexpr uint32_t page_size_ = 4096;

    size_t BDNode::size() const noexcept {
        if (full()) {
            return _ptrs.size();
        }
        size_t lo = 0;
        size_t hi = IndexConst::rank_;
        while (lo < hi) {
            size_t mid = (lo + hi) / 2;
            if (_ptrs[mid].isNull()) {
                hi = mid;
            } else {
                lo = mid + 1;
            }
        }
        return lo;
    }

    bool BDEmpty::verify() const noexcept {
        return CRC32C::verify(reinterpret_cast<const char *>(this), offsetof(BDEmpty, _checksum), &_checksum[0]);
    }

    void BDEmpty::updateChecksum() noexcept {
        uint32_t checksum = CRC32C::value(reinterpret_cast<const char *>(this), offsetof(BDEmpty, _checksum));
        memcpy(&_checksum[0], &checksum, sizeof(checksum));
    }

    bool BDNode::verify() const noexcept {
        return _padding_[0] == 0 && _padding_[1] == 0
               && CRC32C::verify(reinterpret_cast<const char *>(this), offsetof(BDNode, _checksum), &_checksum[0]);
    }

    void BDNode::updateChecksum() noexcept {
        uint32_t checksum = CRC32C::value(reinterpret_cast<const char *>(this), offsetof(BDNode, _checksum));
        memcpy(&_checksum[0], &checksum, sizeof(checksum));
    }

    BDNode * BitDegradeTree::offToMemNode(OffsetToNode node) const {
        assert(sysconf(_SC_PAGESIZE) == page_size_);
        auto * mem_node = reinterpret_cast<BDNode *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region())
                                                     + node.val);
#ifdef __linux__
        unsigned
#else
        static_assert(MINCORE_INCORE == 1, "Unix/Linux conflict");
#endif
        char vec[1]{};
        if (mincore(mem_node, page_size_, vec) != 0) { throw Exception::corruptionException("mincore fail"); };
        if ((vec[0] & 1) != 1 && !mem_node->verify()) {
            throw Exception::corruptionException("i-node checksum mismatch");
        };
        return mem_node;
    }

    BDNode * BitDegradeTree::offToMemNodeUnchecked(OffsetToNode node) const noexcept {
        return reinterpret_cast<BDNode *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region()) + node.val);
    }

    BDEmpty * BitDegradeTree::offToMemEmpty(OffsetToEmpty empty) const {
        auto * mem_empty = reinterpret_cast<BDEmpty *>(reinterpret_cast<uintptr_t>(_dst.immut_mmaped_region())
                                                       + empty.val);
        if (!mem_empty->verify()) {
            throw Exception::corruptionException("e-node checksum mismatch");
        };
        return mem_empty;
    }

    class MatcherDebugOffset : public Matcher { // 仅用于 debug, 真正的实现由继承覆盖
    private:
        uint32_t _val; // 相当于 char[4]

    public:
        explicit MatcherDebugOffset(OffsetToData data) noexcept : _val(data.val) {}

        DEFAULT_MOVE(MatcherDebugOffset);
        DEFAULT_COPY(MatcherDebugOffset);

        ~MatcherDebugOffset() noexcept override = default;

        char operator[](size_t idx) const override {
            return reinterpret_cast<const char *>(&_val)[idx];
        };

        bool operator==(const Matcher & another) const override {
            return toString() == another.toString();
        };

        bool operator==(const Slice & another) const override {
            return toString() == another.toString();
        };

        size_t size() const override {
            return sizeof(_val);
        };

        std::string toString() const override {
            return std::string(reinterpret_cast<const char *>(&_val), sizeof(_val));
        };
    };

    std::unique_ptr<Matcher> BitDegradeTree::offToMatcher(OffsetToData data) const noexcept {
        return std::make_unique<MatcherDebugOffset>(data);
    }

    class MatcherDebugSlice : public Matcher {
    private:
        Slice _slice;

    public:
        explicit MatcherDebugSlice(const Slice & slice) noexcept : _slice(slice) {}

        DEFAULT_MOVE(MatcherDebugSlice);
        DEFAULT_COPY(MatcherDebugSlice);

        ~MatcherDebugSlice() noexcept override = default;

        char operator[](size_t idx) const override {
            return _slice[idx];
        };

        bool operator==(const Matcher & another) const override {
            return toString() == another.toString();
        };

        bool operator==(const Slice & another) const override {
            return toString() == another.toString();
        };

        size_t size() const override {
            return _slice.size();
        };

        std::string toString() const override {
            return _slice.toString();
        };
    };

    std::unique_ptr<Matcher> BitDegradeTree::sliceToMatcher(const Slice & slice) const noexcept {
        return std::make_unique<MatcherDebugSlice>(slice);
    }

    OffsetToNode BitDegradeTree::mallocNode() {
        if (_empty.val == IndexConst::disk_null_) {
            OffsetToNode res{static_cast<uint32_t>(_dst.immut_length())};
            _dst.grow();
            for (uint32_t cursor = res.val + page_size_; cursor < _dst.immut_length(); cursor += page_size_) {
                freeNode(OffsetToNode{cursor});
            }
            return res;
        }
        OffsetToNode res{_empty.val};
        _empty = offToMemEmpty(_empty)->immut_next();
        return res;
    }

    void BitDegradeTree::freeNode(OffsetToNode node) noexcept {
        auto empty = new(offToMemNodeUnchecked(node)) BDEmpty;
        empty->mut_next() = _empty;
        empty->updateChecksum();
        _empty.val = node.val;
    }
}<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file scalar_matrix.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__SCALAR_MATRIX_HPP
#define FL__UTIL__SCALAR_MATRIX_HPP

#include <Eigen/Dense>
#include <fl/util/types.hpp>

namespace fl
{

/**
 * \ingroup types
 *
 * Represents a matrix of the size 1x1. This Matrix can be used in the same way
 * as a scalar.
 */
class ScalarMatrix
    : public Eigen::Matrix<Real, 1, 1>
{
public:
    /**
     * \brief Default constructor.
     * Creates ScalarMatrix with no arguments. The initial value is zero by
     * default.
     */
    ScalarMatrix()
    {
        (*this)(0) = Real(0);
    }

    /**
     * \brief Creates a ScalarMatrix with an initial value or converts a scalar
     * into a ScalarMatrix.
     * \param value initial value
     */
    ScalarMatrix(Real value)
    {
        (*this)(0) = value;
    }

    /**
     * \brief Constructor copying the value of the ScalarMatrix \a other
     */
    ScalarMatrix(const ScalarMatrix& other)
    {
        (*this)(0) = other(0);
    }

    /**
     * \brief Constructor copying the value of the expression \a other
     */
    template <typename OtherDerived>
    ScalarMatrix(const Eigen::MatrixBase<OtherDerived> &other)
    {
        (*this)(0) = other(0);
    }

    /**
     * \brief operator Real() implicit typecast conversion of a ScalarMatrix
     * into a scalar
     */
    operator Real() const
    {
        return Real((*this)(0));
    }

    /**
     * \brief operator+= adds a scalar value to this matrix and assigns
     */
    void operator+=(Real value)
    {
        (*this)(0) += value;
    }

    /**
     * \brief operator-= subtracts a scalar value to this matrix and assigns
     */
    void operator-=(Real value)
    {
        (*this)(0) -= value;
    }

    /**
     * \brief operator*= multiplies a scalar value with this this matrix and
     * assigns
     */
    void operator*=(Real value)
    {
        (*this)(0) *= value;
    }

    /**
     * \brief operator/= divide a scalar value with this this matrix and
     * assigns
     */
    void operator/=(Real value)
    {
        (*this)(0) /= value;
    }

    /**
     * \brief prefix operator ++ which increments the matrix value by 1.
     */
    ScalarMatrix& operator++()
    {
        ++(*this)(0);
        return *this;
    }

    /**
     * \brief postfix operator ++ which increments the matrix value by 1.
     */
    ScalarMatrix operator++(int)
    {
        ScalarMatrix r = *this;
        ++(*this);
        return r;
    }

    /**
     * \brief prefix operator -- which decrements the matrix value by 1.
     */
    ScalarMatrix& operator--()
    {
        --(*this)(0);
        return *this;
    }

    /**
     * \brief postfix operator -- which decrements the matrix value by 1.
     */
    ScalarMatrix operator--(int)
    {
        ScalarMatrix r = *this;
        --(*this);
        return r;
    }
};

}

#endif
<commit_msg>accessing data directly<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file scalar_matrix.hpp
 * \date August 2015
 * \author Jan Issac (jan.issac@gmail.com)
 */

#ifndef FL__UTIL__SCALAR_MATRIX_HPP
#define FL__UTIL__SCALAR_MATRIX_HPP

#include <Eigen/Dense>
#include <fl/util/types.hpp>

namespace fl
{

/**
 * \ingroup types
 *
 * Represents a matrix of the size 1x1. This Matrix can be used in the same way
 * as a scalar.
 */
class ScalarMatrix
    : public Eigen::Matrix<Real, 1, 1>
{
public:
    /**
     * \brief Default constructor.
     * Creates ScalarMatrix with no arguments. The initial value is zero by
     * default.
     */
    ScalarMatrix()
    {
        this->data()[0] = Real(0);
    }

    /**
     * \brief Creates a ScalarMatrix with an initial value or converts a scalar
     * into a ScalarMatrix.
     * \param value initial value
     */
    ScalarMatrix(Real value)
    {
        this->data()[0] = value;
    }

    /**
     * \brief Constructor copying the value of the ScalarMatrix \a other
     */
    ScalarMatrix(const ScalarMatrix& other)
    {
        this->data()[0] = other.data()[0];
    }

    /**
     * \brief Constructor copying the value of the expression \a other
     */
    template <typename OtherDerived>
    ScalarMatrix(const Eigen::MatrixBase<OtherDerived> &other)
    {
        this->data()[0] = other(0);
    }

    /**
     * \brief operator Real() implicit typecast conversion of a ScalarMatrix
     * into a scalar
     */
    operator Real() const
    {
        return Real(this->data()[0]);
    }

    /**
     * \brief operator+= adds a scalar value to this matrix and assigns
     */
    void operator+=(Real value)
    {
        this->data()[0] += value;
    }

    /**
     * \brief operator-= subtracts a scalar value to this matrix and assigns
     */
    void operator-=(Real value)
    {
        this->data()[0] -= value;
    }

    /**
     * \brief operator*= multiplies a scalar value with this this matrix and
     * assigns
     */
    void operator*=(Real value)
    {
        this->data()[0] *= value;
    }

    /**
     * \brief operator/= divide a scalar value with this this matrix and
     * assigns
     */
    void operator/=(Real value)
    {
        this->data()[0] /= value;
    }

    /**
     * \brief prefix operator ++ which increments the matrix value by 1.
     */
    ScalarMatrix& operator++()
    {
        return (++this->data()[0], *this);
    }

    /**
     * \brief postfix operator ++ which increments the matrix value by 1.
     */
    ScalarMatrix operator++(int)
    {
        auto r = ScalarMatrix(this->data()[0]++); // RVO
        return r;
    }

    /**
     * \brief prefix operator -- which decrements the matrix value by 1.
     */
    ScalarMatrix& operator--()
    {
        return (--this->data()[0], *this);
    }

    /**
     * \brief postfix operator -- which decrements the matrix value by 1.
     */
    ScalarMatrix operator--(int)
    {
        auto r = ScalarMatrix(this->data()[0]--); // RVO
        return r;
    }
};

}

#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <test/bootstrapfixture.hxx>
#include "document.hxx"
#include "docsh.hxx"

#include "rangelst.hxx"

class Test : public test::BootstrapFixture {

public:
    virtual void setUp();
    virtual void tearDown();

    void testDeleteArea_4Ranges();
    void testDeleteArea_2Ranges();
    void testDeleteArea_2Ranges_Case2();
    void testDeleteArea_0Ranges();

    void testUpdateReference_DeleteRow();
    void testUpdateReference_DeleteCol();

    CPPUNIT_TEST_SUITE(Test);
    CPPUNIT_TEST(testDeleteArea_4Ranges);
    CPPUNIT_TEST(testDeleteArea_2Ranges);
    CPPUNIT_TEST(testDeleteArea_2Ranges_Case2);
    CPPUNIT_TEST(testDeleteArea_0Ranges);
    CPPUNIT_TEST(testUpdateReference_DeleteRow);
    CPPUNIT_TEST(testUpdateReference_DeleteCol);
    CPPUNIT_TEST_SUITE_END();

private:
    ScDocument *m_pDoc;
    ScDocShellRef m_xDocShRef;
};

void Test::setUp()
{
    BootstrapFixture::setUp();

    ScDLL::Init();
    m_xDocShRef = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);

    m_pDoc = m_xDocShRef->GetDocument();
}

void Test::tearDown()
{
    m_xDocShRef.Clear();
    BootstrapFixture::tearDown();
}

void Test::testDeleteArea_4Ranges()
{
    ScRangeList aList(ScRange(0,0,0,5,5,0));
    aList.DeleteArea(2,2,0,3,3,0);

    CPPUNIT_ASSERT_EQUAL(aList.size(), static_cast<size_t>(4));
    for(SCCOL nCol = 0; nCol <= 5; ++nCol)
    {
        for(SCROW nRow = 0; nRow <= 5; ++nRow)
        {
            if((nCol == 2 || nCol == 3) && ( nRow == 2 || nRow == 3))
                CPPUNIT_ASSERT(!aList.Intersects(ScRange(nCol, nRow, 0)));
            else
                CPPUNIT_ASSERT(aList.Intersects(ScRange(nCol, nRow, 0)));
        }
    }
}

void Test::testDeleteArea_2Ranges()
{
    ScRangeList aList(ScRange(0,0,0,5,5,5));
    ScRangeList aList2(aList);

    aList.DeleteArea(4,4,0,6,7,0);
    aList2.DeleteArea(4,4,0,6,7,0);
    CPPUNIT_ASSERT_EQUAL(aList.size(), static_cast<size_t>(2));
    CPPUNIT_ASSERT_EQUAL(aList2.size(), static_cast<size_t>(2));

    for(SCCOL nCol = 0; nCol <= 5; ++nCol)
    {
        for(SCROW nRow = 0; nRow <= 5; ++nRow)
        {
            if(nCol>=4 && nRow >= 4)
                CPPUNIT_ASSERT(!aList.Intersects(ScRange(nCol, nRow, 0)));
            else
                CPPUNIT_ASSERT(aList.Intersects(ScRange(nCol, nRow, 0)));
        }
    }
}

void Test::testDeleteArea_2Ranges_Case2()
{
    ScRangeList aList(ScRange(1,1,0,1,5,0));
    aList.DeleteArea(0,3,0,MAXCOL,3,0);

    for(SCROW nRow = 1; nRow <= 5; ++nRow)
    {
        if(nRow == 3)
            CPPUNIT_ASSERT(!aList.Intersects(ScRange(1,3,0)));
        else
            CPPUNIT_ASSERT(aList.Intersects(ScRange(1,nRow,0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), aList.GetCellCount());
}

void Test::testDeleteArea_0Ranges()
{
    ScRangeList aList(ScRange(1,1,0,3,3,0));
    aList.DeleteArea(1,1,0,3,3,0);

    CPPUNIT_ASSERT(aList.empty());

    ScRangeList aList2(ScRange(1,1,0,3,3,0));
    aList2.DeleteArea(0,0,0,4,4,0);

    CPPUNIT_ASSERT(aList.empty());
}

void Test::testUpdateReference_DeleteRow()
{
    ScRangeList aList(ScRange(1,1,0,4,4,0));
    bool bUpdated = aList.UpdateReference(URM_INSDEL, m_pDoc, ScRange(0,3,0,MAXCOL,MAXROW,0), 0, -1, 0);
    CPPUNIT_ASSERT(bUpdated);

    for(SCCOL nCol = 1; nCol <= 4; ++nCol)
    {
        for(SCROW nRow = 1; nRow <= 3; ++nRow)
        {
            CPPUNIT_ASSERT(aList.Intersects(ScRange(nCol, nRow, 0)));
        }
        CPPUNIT_ASSERT(!aList.Intersects(ScRange(nCol, 4, 0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(12), aList.GetCellCount());
}

void Test::testUpdateReference_DeleteCol()
{
    ScRangeList aList(ScRange(1,1,0,4,4,0));
    bool bUpdated = aList.UpdateReference(URM_INSDEL, m_pDoc, ScRange(3,0,0,MAXCOL,MAXROW,0), -1, 0, 0);
    CPPUNIT_ASSERT(bUpdated);

    for(SCROW nRow = 1; nRow <= 4; ++nRow)
    {
        for(SCCOL nCol = 1; nCol <= 3; ++nCol)
        {
            CPPUNIT_ASSERT(aList.Intersects(ScRange(nCol, nRow, 0)));
        }
        CPPUNIT_ASSERT(!aList.Intersects(ScRange(4, nRow, 0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(12), aList.GetCellCount());
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>it is better to use ScRangeList::In than Intersects<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <sal/config.h>
#include <test/bootstrapfixture.hxx>
#include "document.hxx"
#include "docsh.hxx"

#include "rangelst.hxx"

class Test : public test::BootstrapFixture {

public:
    virtual void setUp();
    virtual void tearDown();

    void testDeleteArea_4Ranges();
    void testDeleteArea_2Ranges();
    void testDeleteArea_2Ranges_Case2();
    void testDeleteArea_0Ranges();

    void testUpdateReference_DeleteRow();
    void testUpdateReference_DeleteCol();

    CPPUNIT_TEST_SUITE(Test);
    CPPUNIT_TEST(testDeleteArea_4Ranges);
    CPPUNIT_TEST(testDeleteArea_2Ranges);
    CPPUNIT_TEST(testDeleteArea_2Ranges_Case2);
    CPPUNIT_TEST(testDeleteArea_0Ranges);
    CPPUNIT_TEST(testUpdateReference_DeleteRow);
    CPPUNIT_TEST(testUpdateReference_DeleteCol);
    CPPUNIT_TEST_SUITE_END();

private:
    ScDocument *m_pDoc;
    ScDocShellRef m_xDocShRef;
};

void Test::setUp()
{
    BootstrapFixture::setUp();

    ScDLL::Init();
    m_xDocShRef = new ScDocShell(
        SFXMODEL_STANDARD |
        SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
        SFXMODEL_DISABLE_DOCUMENT_RECOVERY);

    m_pDoc = m_xDocShRef->GetDocument();
}

void Test::tearDown()
{
    m_xDocShRef.Clear();
    BootstrapFixture::tearDown();
}

void Test::testDeleteArea_4Ranges()
{
    ScRangeList aList(ScRange(0,0,0,5,5,0));
    aList.DeleteArea(2,2,0,3,3,0);

    CPPUNIT_ASSERT_EQUAL(aList.size(), static_cast<size_t>(4));
    for(SCCOL nCol = 0; nCol <= 5; ++nCol)
    {
        for(SCROW nRow = 0; nRow <= 5; ++nRow)
        {
            if((nCol == 2 || nCol == 3) && ( nRow == 2 || nRow == 3))
                CPPUNIT_ASSERT(!aList.In(ScRange(nCol, nRow, 0)));
            else
                CPPUNIT_ASSERT(aList.In(ScRange(nCol, nRow, 0)));
        }
    }
}

void Test::testDeleteArea_2Ranges()
{
    ScRangeList aList(ScRange(0,0,0,5,5,5));
    ScRangeList aList2(aList);

    aList.DeleteArea(4,4,0,6,7,0);
    aList2.DeleteArea(4,4,0,6,7,0);
    CPPUNIT_ASSERT_EQUAL(aList.size(), static_cast<size_t>(2));
    CPPUNIT_ASSERT_EQUAL(aList2.size(), static_cast<size_t>(2));

    for(SCCOL nCol = 0; nCol <= 5; ++nCol)
    {
        for(SCROW nRow = 0; nRow <= 5; ++nRow)
        {
            if(nCol>=4 && nRow >= 4)
                CPPUNIT_ASSERT(!aList.In(ScRange(nCol, nRow, 0)));
            else
                CPPUNIT_ASSERT(aList.In(ScRange(nCol, nRow, 0)));
        }
    }
}

void Test::testDeleteArea_2Ranges_Case2()
{
    ScRangeList aList(ScRange(1,1,0,1,5,0));
    aList.DeleteArea(0,3,0,MAXCOL,3,0);

    for(SCROW nRow = 1; nRow <= 5; ++nRow)
    {
        if(nRow == 3)
            CPPUNIT_ASSERT(!aList.In(ScRange(1,3,0)));
        else
            CPPUNIT_ASSERT(aList.In(ScRange(1,nRow,0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), aList.GetCellCount());
}

void Test::testDeleteArea_0Ranges()
{
    ScRangeList aList(ScRange(1,1,0,3,3,0));
    aList.DeleteArea(1,1,0,3,3,0);

    CPPUNIT_ASSERT(aList.empty());

    ScRangeList aList2(ScRange(1,1,0,3,3,0));
    aList2.DeleteArea(0,0,0,4,4,0);

    CPPUNIT_ASSERT(aList.empty());
}

void Test::testUpdateReference_DeleteRow()
{
    ScRangeList aList(ScRange(1,1,0,4,4,0));
    bool bUpdated = aList.UpdateReference(URM_INSDEL, m_pDoc, ScRange(0,3,0,MAXCOL,MAXROW,0), 0, -1, 0);
    CPPUNIT_ASSERT(bUpdated);

    for(SCCOL nCol = 1; nCol <= 4; ++nCol)
    {
        for(SCROW nRow = 1; nRow <= 3; ++nRow)
        {
            CPPUNIT_ASSERT(aList.In(ScRange(nCol, nRow, 0)));
        }
        CPPUNIT_ASSERT(!aList.In(ScRange(nCol, 4, 0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(12), aList.GetCellCount());
}

void Test::testUpdateReference_DeleteCol()
{
    ScRangeList aList(ScRange(1,1,0,4,4,0));
    bool bUpdated = aList.UpdateReference(URM_INSDEL, m_pDoc, ScRange(3,0,0,MAXCOL,MAXROW,0), -1, 0, 0);
    CPPUNIT_ASSERT(bUpdated);

    for(SCROW nRow = 1; nRow <= 4; ++nRow)
    {
        for(SCCOL nCol = 1; nCol <= 3; ++nCol)
        {
            CPPUNIT_ASSERT(aList.In(ScRange(nCol, nRow, 0)));
        }
        CPPUNIT_ASSERT(!aList.In(ScRange(4, nRow, 0)));
    }
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(12), aList.GetCellCount());
}

CPPUNIT_TEST_SUITE_REGISTRATION(Test);

CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_I2P_STREAM_HPP_INCLUDED
#define TORRENT_I2P_STREAM_HPP_INCLUDED

#include "libtorrent/config.hpp"

#if TORRENT_USE_I2P

#include <list>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/bind.hpp>
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/session_settings.hpp"

namespace libtorrent {

	namespace i2p_error {

		enum i2p_error_code
		{
			no_error = 0,
			parse_failed,
			cant_reach_peer,
			i2p_error,
			invalid_key,
			invalid_id,
			timeout,
			key_not_found,
			num_errors
		};
	}

struct TORRENT_EXPORT i2p_error_category : boost::system::error_category
{
	virtual const char* name() const;
	virtual std::string message(int ev) const;
	virtual boost::system::error_condition default_error_condition(int ev) const
	{ return boost::system::error_condition(ev, *this); }
};

extern i2p_error_category i2p_category;

class i2p_stream : public proxy_base
{
public:

	explicit i2p_stream(io_service& io_service)
		: proxy_base(io_service)
		, m_id(0)
		, m_command(cmd_create_session)
		, m_state(0)
	{}

	enum command_t
	{
		cmd_none,
		cmd_create_session,
		cmd_connect,
		cmd_accept,
		cmd_name_lookup,
		cmd_incoming
	};

	void set_command(command_t c) { m_command = c; }

	void set_session_id(char const* id) { m_id = id; }

	void set_destination(std::string const& d) { m_dest = d; }
	std::string const& destination() { return m_dest; }

	typedef boost::function<void(error_code const&)> handler_type;

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		// since we don't support regular endpoints, just ignore the one
		// provided and use m_dest.

		// the connect is split up in the following steps:
		// 1. resolve name of proxy server
		// 2. connect to SAM bridge
		// 4 send command message (CONNECT/ACCEPT)

		// to avoid unnecessary copying of the handler,
		// store it in a shaed_ptr
		boost::shared_ptr<handler_type> h(new handler_type(handler));

		tcp::resolver::query q(m_hostname, to_string(m_port).elems);
		m_resolver.async_resolve(q, boost::bind(
			&i2p_stream::do_connect, this, _1, _2, h));
	}

	std::string name_lookup() const { return m_name_lookup; }
	void set_name_lookup(char const* name) { m_name_lookup = name; }

	void send_name_lookup(boost::shared_ptr<handler_type> h);

private:

	bool handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h);
	void do_connect(error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h);
	void connected(error_code const& e, boost::shared_ptr<handler_type> h);
	void start_read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void send_connect(boost::shared_ptr<handler_type> h);
	void send_accept(boost::shared_ptr<handler_type> h);
	void send_session_create(boost::shared_ptr<handler_type> h);

	// send and receive buffer
	std::vector<char> m_buffer;
	char const* m_id;
	int m_command; // 0 = connect, 1 = accept
	std::string m_dest;
	std::string m_name_lookup;

	enum state_t
	{
		read_hello_response,
		read_connect_response,
		read_accept_response,
		read_session_create_response,
		read_name_lookup_response
	};

	int m_state;
};

class i2p_connection
{
public:
	i2p_connection(io_service& ios);
	~i2p_connection();

	proxy_settings const& proxy() const { return m_sam_router; }

	bool is_open() const
	{
		return m_sam_socket
			&& m_sam_socket->is_open()
			&& m_state != sam_connecting;
	}
	void open(proxy_settings const& s, i2p_stream::handler_type const& h);
	void close(error_code&);

	char const* session_id() const { return m_session_id.c_str(); }
	std::string const& local_endpoint() const { return m_i2p_local_endpoint; }

	typedef boost::function<void(error_code const&, char const*)> name_lookup_handler;
	void async_name_lookup(char const* name, name_lookup_handler handler);

private:

	void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h);
	void do_name_lookup(std::string const& name
		, name_lookup_handler const& h);
	void on_name_lookup(error_code const& ec
		, name_lookup_handler handler);

	void set_local_endpoint(error_code const& ec, char const* dest);

	// to talk to i2p SAM bridge
	boost::shared_ptr<i2p_stream> m_sam_socket;
	proxy_settings m_sam_router;

	// our i2p endpoint key
	std::string m_i2p_local_endpoint;
	std::string m_session_id;

	std::list<std::pair<std::string, name_lookup_handler> > m_name_lookup;

	enum state_t
	{
		sam_connecting,
		sam_name_lookup,
		sam_idle
	};

	state_t m_state;

	io_service& m_io_service;
};

}
#endif // TORRENT_USE_I2P

#endif

<commit_msg>some more missing includes<commit_after>/*

Copyright (c) 2009, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_I2P_STREAM_HPP_INCLUDED
#define TORRENT_I2P_STREAM_HPP_INCLUDED

#include "libtorrent/config.hpp"

#if TORRENT_USE_I2P

#include <list>
#include <string>
#include <vector>
#include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/proxy_base.hpp"
#include "libtorrent/session_settings.hpp"

namespace libtorrent {

	namespace i2p_error {

		enum i2p_error_code
		{
			no_error = 0,
			parse_failed,
			cant_reach_peer,
			i2p_error,
			invalid_key,
			invalid_id,
			timeout,
			key_not_found,
			num_errors
		};
	}

struct TORRENT_EXPORT i2p_error_category : boost::system::error_category
{
	virtual const char* name() const;
	virtual std::string message(int ev) const;
	virtual boost::system::error_condition default_error_condition(int ev) const
	{ return boost::system::error_condition(ev, *this); }
};

extern i2p_error_category i2p_category;

class i2p_stream : public proxy_base
{
public:

	explicit i2p_stream(io_service& io_service)
		: proxy_base(io_service)
		, m_id(0)
		, m_command(cmd_create_session)
		, m_state(0)
	{}

	enum command_t
	{
		cmd_none,
		cmd_create_session,
		cmd_connect,
		cmd_accept,
		cmd_name_lookup,
		cmd_incoming
	};

	void set_command(command_t c) { m_command = c; }

	void set_session_id(char const* id) { m_id = id; }

	void set_destination(std::string const& d) { m_dest = d; }
	std::string const& destination() { return m_dest; }

	typedef boost::function<void(error_code const&)> handler_type;

	template <class Handler>
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		// since we don't support regular endpoints, just ignore the one
		// provided and use m_dest.

		// the connect is split up in the following steps:
		// 1. resolve name of proxy server
		// 2. connect to SAM bridge
		// 4 send command message (CONNECT/ACCEPT)

		// to avoid unnecessary copying of the handler,
		// store it in a shaed_ptr
		boost::shared_ptr<handler_type> h(new handler_type(handler));

		tcp::resolver::query q(m_hostname, to_string(m_port).elems);
		m_resolver.async_resolve(q, boost::bind(
			&i2p_stream::do_connect, this, _1, _2, h));
	}

	std::string name_lookup() const { return m_name_lookup; }
	void set_name_lookup(char const* name) { m_name_lookup = name; }

	void send_name_lookup(boost::shared_ptr<handler_type> h);

private:

	bool handle_error(error_code const& e, boost::shared_ptr<handler_type> const& h);
	void do_connect(error_code const& e, tcp::resolver::iterator i
		, boost::shared_ptr<handler_type> h);
	void connected(error_code const& e, boost::shared_ptr<handler_type> h);
	void start_read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void read_line(error_code const& e, boost::shared_ptr<handler_type> h);
	void send_connect(boost::shared_ptr<handler_type> h);
	void send_accept(boost::shared_ptr<handler_type> h);
	void send_session_create(boost::shared_ptr<handler_type> h);

	// send and receive buffer
	std::vector<char> m_buffer;
	char const* m_id;
	int m_command; // 0 = connect, 1 = accept
	std::string m_dest;
	std::string m_name_lookup;

	enum state_t
	{
		read_hello_response,
		read_connect_response,
		read_accept_response,
		read_session_create_response,
		read_name_lookup_response
	};

	int m_state;
};

class i2p_connection
{
public:
	i2p_connection(io_service& ios);
	~i2p_connection();

	proxy_settings const& proxy() const { return m_sam_router; }

	bool is_open() const
	{
		return m_sam_socket
			&& m_sam_socket->is_open()
			&& m_state != sam_connecting;
	}
	void open(proxy_settings const& s, i2p_stream::handler_type const& h);
	void close(error_code&);

	char const* session_id() const { return m_session_id.c_str(); }
	std::string const& local_endpoint() const { return m_i2p_local_endpoint; }

	typedef boost::function<void(error_code const&, char const*)> name_lookup_handler;
	void async_name_lookup(char const* name, name_lookup_handler handler);

private:

	void on_sam_connect(error_code const& ec, i2p_stream::handler_type const& h);
	void do_name_lookup(std::string const& name
		, name_lookup_handler const& h);
	void on_name_lookup(error_code const& ec
		, name_lookup_handler handler);

	void set_local_endpoint(error_code const& ec, char const* dest);

	// to talk to i2p SAM bridge
	boost::shared_ptr<i2p_stream> m_sam_socket;
	proxy_settings m_sam_router;

	// our i2p endpoint key
	std::string m_i2p_local_endpoint;
	std::string m_session_id;

	std::list<std::pair<std::string, name_lookup_handler> > m_name_lookup;

	enum state_t
	{
		sam_connecting,
		sam_name_lookup,
		sam_idle
	};

	state_t m_state;

	io_service& m_io_service;
};

}
#endif // TORRENT_USE_I2P

#endif

<|endoftext|>


<commit_before>#include "test.hpp"
#include "../resmgr.hpp"
#include "../resmgr_named.hpp"
#include "../lubee/random/string.hpp"

namespace spi {
	namespace test {
		template <class T>
		struct ResourceMgr : Random {
			ResMgr<T>	_mgr;
			using value_t = typename T::value_t;
			using res_t = typename decltype(_mgr)::shared_t;

			auto& getMgr() {
				return _mgr;
			}
		};
		using Types = ::testing::Types<TestObj<int>, TestObj<double>>;
		TYPED_TEST_CASE(ResourceMgr, Types);

		TYPED_TEST(ResourceMgr, Serialization) {
			USING(value_t);
			// ランダムな数、要素を追加
			auto& mgr = this->getMgr();
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				mgr.emplace(rv());
			}
			lubee::CheckSerialization(mgr);
		}

		struct Action {
			enum e {
				Acquire,
				Release,
				_Num
			};
		};
		TYPED_TEST(ResourceMgr, General) {
			USING(res_t);
			USING(value_t);
			InitializeCounter<TypeParam>();

			auto& mgr = this->getMgr();
			std::vector<std::pair<res_t, value_t>>	res;
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				switch(mtf({0,Action::_Num-1})) {
					// ランダムにリソースを確保
					case Action::Acquire:
					{
						const auto val = rv();
						res.emplace_back(mgr.emplace(val), val);
						break;
					}
					// ランダムにどれかリソースを解放
					case Action::Release:
						if(!res.empty()) {
							const int idx = mtf({0, int(res.size()-1)});
							res.erase(res.begin()+idx);
						}
						break;
				}
			}
			// 各リソースの内部値が合致しているか
			for(auto& r : res) {
				ASSERT_EQ(r.second, r.first->getValue());
			}
			// コンストラクタ/デストラクタが呼ばれた回数を比較
			// (ctor - dtor == リソースの残り数)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(res.size()));
			// こちらで管理しているリソースハンドルとリソースマネージャのそれは一致する
			ASSERT_EQ(res.size(), mgr.size());
			for(auto m : mgr) {
				const auto itr = std::find_if(res.begin(), res.end(),
						[&m](auto& r){ return r.first==m; });
				ASSERT_NE(itr, res.end());
			}
			res.clear();
			// (ctor - dtor == 0)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(0));
			// 全てリソースを開放したのでマネージャのリソース数もゼロになる
			ASSERT_EQ(0, mgr.size());
		}

		template <class T>
		struct ResourceMgrName : Random {
			class RM : public ResMgrName<T> {
				private:
					using base_t = ResMgrName<T>;
				public:
					// キー名は全て大文字にする
					void _modifyResourceName(typename base_t::key_t& key) const override {
						for(auto& c : key)
							c = std::toupper(c);
					}
			};
			using rawvalue_t = T;
			using rmgr_t = RM;
			rmgr_t	_mgr;
			using value_t = typename rawvalue_t::value_t;
			using res_t = typename rmgr_t::shared_t;
			using key_t = typename rmgr_t::key_t;

			auto& getMgr() {
				return _mgr;
			}
		};
		using NTypes = ::testing::Types<TestObj<int>>;
		TYPED_TEST_CASE(ResourceMgrName, NTypes);

		TYPED_TEST(ResourceMgrName, Serialization) {
			USING(value_t);
			// ランダムな数、要素を追加
			auto& mgr = this->getMgr();
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				mgr.emplace(lubee::random::GenAlphabetString(mtf, 16), rv());
			}
			lubee::CheckSerialization(mgr);
		}
		struct ActionN {
			enum e {
				Acquire,
				Release,
				AcquireExist,
				FindByName,
				FindByHandle,
				_Num
			};
		};
		TYPED_TEST(ResourceMgrName, General) {
			USING(key_t);
			USING(res_t);
			USING(value_t);
			USING(rawvalue_t);
			InitializeCounter<TypeParam>();

			struct Res {
				key_t		key;
				res_t		res;
				value_t		val;
			};
			using RMap = std::unordered_map<key_t, Res>;
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			auto& mgr = this->getMgr();

			RMap res;
			const auto pickRandom = [&res, &mtf](){
				const int idx = mtf({0, int(res.size()-1)});
				auto itr = res.begin();
				std::advance(itr, idx);
				return itr;
			};
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				switch(mtf({0, ActionN::_Num})) {
					case ActionN::Acquire:
					{
						// 新たにリソースを確保
						const auto val = rv();
						const auto key = lubee::random::GenAlphabetString(mtf, 16);
						auto tk(key);
						mgr._modifyResourceName(tk);
						std::pair<res_t,bool> r;
						if(mtf({0,1})) {
							if(mtf({0,1}))
								r = mgr.emplace(key, val);
							else
								r = mgr.template emplaceWithType<rawvalue_t>(key, val);
						} else {
							bool flag = false;
							r = mgr.acquireWithMake(key,
									[&flag, val](){
										flag = true;
										return new rawvalue_t(val);
									}
								);
							ASSERT_TRUE(flag);
						}
						ASSERT_TRUE(r.second);
						res.emplace(tk, Res{key, r.first, val});
						break;
					}
					case ActionN::Release:
						// リソースを解放
						if(!res.empty()) {
							res.erase(pickRandom());
						}
						break;
					case ActionN::AcquireExist:
						if(!res.empty()) {
							// 既に存在するリソースを取得
							// 同じポインタが返ってくればOK
							const auto itr = pickRandom();
							const auto r = mgr.emplace(itr->first, rv());
							ASSERT_FALSE(r.second);
							ASSERT_EQ(itr->second.res.get(), r.first.get());
						}
						break;
					case ActionN::FindByName:
						if(!res.empty()) {
							// 既に存在するリソースを名前から検索
							const auto itr = pickRandom();
							ASSERT_TRUE(mgr.get(itr->first));
						}
						break;
					case ActionN::FindByHandle:
						if(!res.empty()) {
							const auto itr = pickRandom();
							// 既に存在するリソースのポインタから名前を検索
							const auto key0 = mgr.getKey(itr->second.res);
							const auto key1 = mgr.getKey(itr->second.res.get());
							ASSERT_TRUE(key0);
							ASSERT_TRUE(key1);
							ASSERT_EQ(*key0, *key1);
							const auto res0 = mgr.get(*key0);
							ASSERT_EQ(itr->second.res, res0);
						}
						break;
				}
			}
			// 各リソースの内部値が合致しているか
			for(auto& r : res) {
				ASSERT_EQ(r.second.val, r.second.res->getValue());
			}
			// コンストラクタ/デストラクタが呼ばれた回数を比較
			// (ctor - dtor == リソースの残り数)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(res.size()));
			// こちらで管理しているリソースハンドルとリソースマネージャのそれは一致する
			ASSERT_EQ(res.size(), mgr.size());
			for(auto m : mgr) {
				auto* ptr = m.get();
				const auto itr = std::find_if(res.begin(), res.end(),
						[ptr](auto& r){ return r.second.res.get() == ptr; });
				ASSERT_NE(itr, res.end());
			}
			res.clear();
			// (ctor - dtor == 0)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(0));
			// 全てリソースを開放したのでマネージャのリソース数もゼロになる
			ASSERT_EQ(0, mgr.size());
		}
	}
}
<commit_msg>acquireWithMake()に与える引数を修正(コンパイルエラー対策)<commit_after>#include "test.hpp"
#include "../resmgr.hpp"
#include "../resmgr_named.hpp"
#include "../lubee/random/string.hpp"

namespace spi {
	namespace test {
		template <class T>
		struct ResourceMgr : Random {
			ResMgr<T>	_mgr;
			using value_t = typename T::value_t;
			using res_t = typename decltype(_mgr)::shared_t;

			auto& getMgr() {
				return _mgr;
			}
		};
		using Types = ::testing::Types<TestObj<int>, TestObj<double>>;
		TYPED_TEST_CASE(ResourceMgr, Types);

		TYPED_TEST(ResourceMgr, Serialization) {
			USING(value_t);
			// ランダムな数、要素を追加
			auto& mgr = this->getMgr();
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				mgr.emplace(rv());
			}
			lubee::CheckSerialization(mgr);
		}

		struct Action {
			enum e {
				Acquire,
				Release,
				_Num
			};
		};
		TYPED_TEST(ResourceMgr, General) {
			USING(res_t);
			USING(value_t);
			InitializeCounter<TypeParam>();

			auto& mgr = this->getMgr();
			std::vector<std::pair<res_t, value_t>>	res;
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				switch(mtf({0,Action::_Num-1})) {
					// ランダムにリソースを確保
					case Action::Acquire:
					{
						const auto val = rv();
						res.emplace_back(mgr.emplace(val), val);
						break;
					}
					// ランダムにどれかリソースを解放
					case Action::Release:
						if(!res.empty()) {
							const int idx = mtf({0, int(res.size()-1)});
							res.erase(res.begin()+idx);
						}
						break;
				}
			}
			// 各リソースの内部値が合致しているか
			for(auto& r : res) {
				ASSERT_EQ(r.second, r.first->getValue());
			}
			// コンストラクタ/デストラクタが呼ばれた回数を比較
			// (ctor - dtor == リソースの残り数)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(res.size()));
			// こちらで管理しているリソースハンドルとリソースマネージャのそれは一致する
			ASSERT_EQ(res.size(), mgr.size());
			for(auto m : mgr) {
				const auto itr = std::find_if(res.begin(), res.end(),
						[&m](auto& r){ return r.first==m; });
				ASSERT_NE(itr, res.end());
			}
			res.clear();
			// (ctor - dtor == 0)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(0));
			// 全てリソースを開放したのでマネージャのリソース数もゼロになる
			ASSERT_EQ(0, mgr.size());
		}

		template <class T>
		struct ResourceMgrName : Random {
			class RM : public ResMgrName<T> {
				private:
					using base_t = ResMgrName<T>;
				public:
					// キー名は全て大文字にする
					void _modifyResourceName(typename base_t::key_t& key) const override {
						for(auto& c : key)
							c = std::toupper(c);
					}
			};
			using rawvalue_t = T;
			using rmgr_t = RM;
			rmgr_t	_mgr;
			using value_t = typename rawvalue_t::value_t;
			using res_t = typename rmgr_t::shared_t;
			using key_t = typename rmgr_t::key_t;

			auto& getMgr() {
				return _mgr;
			}
		};
		using NTypes = ::testing::Types<TestObj<int>>;
		TYPED_TEST_CASE(ResourceMgrName, NTypes);

		TYPED_TEST(ResourceMgrName, Serialization) {
			USING(value_t);
			// ランダムな数、要素を追加
			auto& mgr = this->getMgr();
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				mgr.emplace(lubee::random::GenAlphabetString(mtf, 16), rv());
			}
			lubee::CheckSerialization(mgr);
		}
		struct ActionN {
			enum e {
				Acquire,
				Release,
				AcquireExist,
				FindByName,
				FindByHandle,
				_Num
			};
		};
		TYPED_TEST(ResourceMgrName, General) {
			USING(key_t);
			USING(res_t);
			USING(value_t);
			USING(rawvalue_t);
			InitializeCounter<TypeParam>();

			struct Res {
				key_t		key;
				res_t		res;
				value_t		val;
			};
			using RMap = std::unordered_map<key_t, Res>;
			const auto mtf = this->mt().template getUniformF<int>();
			const auto rv = this->mt().template getUniformF<value_t>();
			auto& mgr = this->getMgr();

			RMap res;
			const auto pickRandom = [&res, &mtf](){
				const int idx = mtf({0, int(res.size()-1)});
				auto itr = res.begin();
				std::advance(itr, idx);
				return itr;
			};
			const int n = mtf({0,100});
			for(int i=0 ; i<n ; i++) {
				switch(mtf({0, ActionN::_Num})) {
					case ActionN::Acquire:
					{
						// 新たにリソースを確保
						const auto val = rv();
						const auto key = lubee::random::GenAlphabetString(mtf, 16);
						auto tk(key);
						mgr._modifyResourceName(tk);
						std::pair<res_t,bool> r;
						if(mtf({0,1})) {
							if(mtf({0,1}))
								r = mgr.emplace(key, val);
							else
								r = mgr.template emplaceWithType<rawvalue_t>(key, val);
						} else {
							bool flag = false;
							r = mgr.acquireWithMake(key,
									[&flag, val](auto&&){
										flag = true;
										return new rawvalue_t(val);
									}
								);
							ASSERT_TRUE(flag);
						}
						ASSERT_TRUE(r.second);
						res.emplace(tk, Res{key, r.first, val});
						break;
					}
					case ActionN::Release:
						// リソースを解放
						if(!res.empty()) {
							res.erase(pickRandom());
						}
						break;
					case ActionN::AcquireExist:
						if(!res.empty()) {
							// 既に存在するリソースを取得
							// 同じポインタが返ってくればOK
							const auto itr = pickRandom();
							const auto r = mgr.emplace(itr->first, rv());
							ASSERT_FALSE(r.second);
							ASSERT_EQ(itr->second.res.get(), r.first.get());
						}
						break;
					case ActionN::FindByName:
						if(!res.empty()) {
							// 既に存在するリソースを名前から検索
							const auto itr = pickRandom();
							ASSERT_TRUE(mgr.get(itr->first));
						}
						break;
					case ActionN::FindByHandle:
						if(!res.empty()) {
							const auto itr = pickRandom();
							// 既に存在するリソースのポインタから名前を検索
							const auto key0 = mgr.getKey(itr->second.res);
							const auto key1 = mgr.getKey(itr->second.res.get());
							ASSERT_TRUE(key0);
							ASSERT_TRUE(key1);
							ASSERT_EQ(*key0, *key1);
							const auto res0 = mgr.get(*key0);
							ASSERT_EQ(itr->second.res, res0);
						}
						break;
				}
			}
			// 各リソースの内部値が合致しているか
			for(auto& r : res) {
				ASSERT_EQ(r.second.val, r.second.res->getValue());
			}
			// コンストラクタ/デストラクタが呼ばれた回数を比較
			// (ctor - dtor == リソースの残り数)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(res.size()));
			// こちらで管理しているリソースハンドルとリソースマネージャのそれは一致する
			ASSERT_EQ(res.size(), mgr.size());
			for(auto m : mgr) {
				auto* ptr = m.get();
				const auto itr = std::find_if(res.begin(), res.end(),
						[ptr](auto& r){ return r.second.res.get() == ptr; });
				ASSERT_NE(itr, res.end());
			}
			res.clear();
			// (ctor - dtor == 0)
			ASSERT_NO_FATAL_FAILURE(CheckCounter<TypeParam>(0));
			// 全てリソースを開放したのでマネージャのリソース数もゼロになる
			ASSERT_EQ(0, mgr.size());
		}
	}
}
<|endoftext|>