<commit_before>#include <TF3.h>
#include <TTree.h>
#include <TStopwatch.h>

#include "X.h"
#include "Units.h"
using namespace GeFiCa;

X::X(int nx, const char *name, const char *title) : TNamed(name,title), V0(0),
   V1(2e3*volt), n1(nx), n(nx), MaxIterations(9999), Nsor(0), Csor(1.95),
   Precision(1e-7*volt), fE2(0), fE3(0), fC2(0), fC3(0),
   fdC2p(0), fdC2m(0), fdC3p(0), fdC3m(0)
{
   if (n<10) { Warning("X","n<10, set it to 11"); n=11; n1=11; }

   fV=new double[n];
   fE1=new double[n];
   fE2=new double[n];
   fE3=new double[n];
   fC1=new double[n];
   fC2=new double[n];
   fC3=new double[n];

   fdC1p=new double[n];
   fdC1m=new double[n];
   fdC2m=new double[n];
   fdC2p=new double[n];
   fdC3p=new double[n];
   fdC3m=new double[n];

   fIsFixed=new bool[n];
   fIsDepleted=new bool[n];
   fImpurity=new double[n];

   for (int i=0;i<n;i++) {
      fV[i]=0;
      fE1[i]=0; fE2[i]=0; fE3[i]=0;
      fC1[i]=0; fC2[i]=0; fC3[i]=0;
      fdC1m[i]=0; fdC1p[i]=0;
      fdC2m[i]=0; fdC2p[i]=0;
      fdC3m[i]=0; fdC3p[i]=0;
      fIsFixed[i]=false;
      fIsDepleted[i]=true;
      fImpurity[i]=0;
   }

   fTree=NULL; fImpDist=NULL;
}
//_____________________________________________________________________________
//
X::~X()
{
   if (fV) delete[] fV;
   if (fE1) delete[] fE1;
   if (fC1) delete[] fC1;
   if (fdC1p) delete[] fdC1p;
   if (fdC1m) delete[] fdC1m;
   if (fIsFixed) delete[] fIsFixed;
   if (fImpurity) delete[] fImpurity;
   if (fIsDepleted) delete[] fIsDepleted;
}
//_____________________________________________________________________________
//
bool X::Analytic()
{
   Info("Analytic", "There is no analytic solution for this setup");
   return false;
}
//_____________________________________________________________________________
//
X& X::operator+=(GeFiCa::X *other)
{
   if (n!=other->n) {
      Warning("+=",
            "Only same type of detector can be added together! Do nothing.");
      return *this;
   }
   for (int i=0; i<n; i++) {
      fV[i]=fV[i]+other->fV[i];
      fImpurity[i]+=other->fImpurity[i];
   }
   V0+=other->V0; V1+=other->V1;
   return *this;
}
//_____________________________________________________________________________
//
X& X::operator*=(double p)
{
   for (int i=0; i<n; i++) fV[i]=fV[i]*p;
   V0*=p; V1*=p;
   return *this;
}
//_____________________________________________________________________________
//
int X::GetIdxOfMaxV()
{
   double max=fV[0];
   int maxn=0;
   for(int i=1;i<n;i++) {
      if(fV[i]>max) {
         maxn=i;
         max=fV[i];
      }
   }
   return maxn;
}
//_____________________________________________________________________________
//
int X::GetIdxOfMinV()
{
   double min=fV[0];
   int minn=0;
   for(int i=1;i<n;i++) {
      if(fV[i]<min) {
         minn=i;
         min=fV[i];
      }
   }
   return minn;
}
//_____________________________________________________________________________
//
bool X::IsDepleted()
{
   for(int i=0;i<n;i++) {
      DoSOR2(i); // calculate one more time in case of
      //adding two fields together, one is depleted, the other is not
      if (!fIsDepleted[i]) return false;
   }
   return true;
}
//_____________________________________________________________________________
//
void X::SetStepLength(double stepLength)
{
   for (int i=n;i-->0;) {
      fIsFixed[i]=false;
      fC1[i]=i*stepLength;
      fdC1p[i]=stepLength;
      fdC1m[i]=stepLength;
   }
}
//_____________________________________________________________________________
//
int* X::FindSurroundingMatrix(int idx)
{
   int *tmp=new int[3];
   tmp[0]=idx;
   if(idx-1<0)tmp[1]=1;
   else tmp[1]=idx-1;
   if(idx+1>=n)tmp[2]=n-2;
   else tmp[2]=idx+1;
   return tmp;
}
//_____________________________________________________________________________
//
bool X::CalculatePotential(EMethod method)
{
   if (fdC1p[0]==0) Initialize(); // setup and initialize grid if it's not done
   if (fImpDist && fImpurity[0]==0) // set impurity values if it's not done yet
      for (int i=n;i-->0;) fImpurity[i]=fImpDist->Eval(fC1[i], fC2[i], fC3[i]);
   if (method==kAnalytic) return Analytic();

   Info("CalculatePotential","Start SOR...");
   TStopwatch watch; watch.Start();
   double cp=1; // current presision
   while (Nsor<MaxIterations) {
      if (Nsor%100==0) Printf("%4d steps, precision: %.1e (target: %.0e)",
               Nsor, cp, Precision);
      double XUpSum=0;
      double XDownSum=0;
      for (int i=n-1;i>=0;i--) {
         double old=fV[i];
         DoSOR2(i);
         if(old>0)XDownSum+=old;
         else XDownSum-=old;
         double diff=fV[i]-old;
         if(diff>0)XUpSum+=(diff);
         else XUpSum-=(diff);
      }
      cp = XUpSum/XDownSum;
      Nsor++;
      if (cp<Precision) break;
   }
   for (int i=0; i<n; i++) if (!CalculateField(i)) return false;
   Printf("%4d steps, precision: %.1e (target: %.0e)", Nsor, cp, Precision);
   Info("CalculatePotential", "CPU time: %.1f s", watch.CpuTime());
   return true;
}
//_____________________________________________________________________________
//
void X::DoSOR2(int idx)
{
   // 2nd-order Runge-Kutta Successive Over-Relaxation
   if (fIsFixed[idx])return ;
   double rho=-fImpurity[idx]*Qe;
   double h2=fdC1m[idx];
   double h3=fdC1p[idx];
   double p2=fV[idx-1];
   double p3=fV[idx+1];

   double tmp=-rho/epsilon*h2*h3/2
      + (h3*fV[idx-1]+h2*fV[idx+1])/(h2+h3);

   //find minmium and maxnium of all five grid, the new one should not go overthem.
   //find min
   double min=p2;
   double max=p2;
   if(min>p3)min=p3;
   //find max
   if(max<p3)max=p3;
   //if tmp is greater or smaller than max and min, set tmp to it.

   //fV[idx]=Csor*(tmp-fV[idx])+fV[idx];
   double oldP=fV[idx];
   tmp=Csor*(tmp-oldP)+oldP;

   if(tmp<min) {
      fV[idx]=min;
      fIsDepleted[idx]=false;
   } else if(tmp>max) {
      fV[idx]=max;
      fIsDepleted[idx]=false;
   } else
      fIsDepleted[idx]=true;

   if(fIsDepleted[idx]||V0==V1) fV[idx]=tmp;
}
//_____________________________________________________________________________
//
int X::FindIdx(double tarx,int begin,int end)
{
   //search using binary search
   if (begin>=end)return end;
   int mid=(begin+end)/2;
   if(fC1[mid]>=tarx)return FindIdx(tarx,begin,mid);
   else return FindIdx(tarx,mid+1,end);
}

//_____________________________________________________________________________
//
double X::GetData(double tarx, EOutput output)
{
   int idx=FindIdx(tarx,0,n-1);
   if (idx==n) {
      switch (output) {
         case 0:return fImpurity[idx];
         case 2:return fE1[idx];
         case 1:return fV[idx];
         default: return -1;
      }
   }
   double ab=(-tarx+fC1[idx])/fdC1p[idx];
   double aa=1-ab;
   switch(output) {
      case 2:return fE1[idx]*ab+fE1[idx-1]*aa;
      case 1:return fV[idx]*ab+fC1[idx-1]*aa;
      case 0:return fImpurity[idx]*ab+fImpurity[idx-1]*aa;
      default: return -1;
   }
   return -1;
}
//_____________________________________________________________________________
//
bool X::CalculateField(int idx)
{
   if (fdC1p[idx]==0 || fdC1m[idx]==0) return false;

   if (idx%n1==0) // C1 lower boundary
      fE1[idx]=(fV[idx]-fV[idx+1])/fdC1p[idx];
   else if (idx%n1==n1-1) // C1 upper boundary
      fE1[idx]=(fV[idx]-fV[idx-1])/fdC1m[idx];
   else // bulk
      fE1[idx]=(fV[idx-1]-fV[idx+1])/(fdC1m[idx]+fdC1p[idx]);

   return true;
}
//_____________________________________________________________________________
//
double X::GetCapacitance()
{
   Info("GetCapacitance","Start...");
   // set impurity to zero
   double *tmpImpurity=fImpurity;
   for (int i=0;i<n;i++) {
      if (fImpurity[i]!=0) {
         //impurity not clear,return
         //return -1;
         fImpurity=new double[n];
         for (int j=0;j<n;j++) {
            fImpurity[j]=0;
            if (!fIsFixed[j] && !fIsDepleted[j]) fIsFixed[j]=true;
         }
         break;
      }
   }
   // calculate potential without impurity
   CalculatePotential(GeFiCa::kSOR2);
   // set impurity back
   if(fImpurity!=tmpImpurity) delete []fImpurity;
   fImpurity=tmpImpurity;

   // calculate C based on CV^2/2 = epsilon int E^2 dx^3 / 2
   double dV=V0-V1; if(dV<0)dV=-dV;
   double SumofElectricField=0;
   for(int i=0;i<n;i++) {
      SumofElectricField+=fE1[i]*fE1[i]*fdC1p[i]*cm*cm;
      if (!fIsDepleted[i]) fIsFixed[i]=false;
   }
   Info("GetCapacitance","Done.");
   return SumofElectricField*epsilon/dV/dV;
}
//_____________________________________________________________________________
//
TTree* X::GetTree(bool createNew)
{
   if (fTree!=NULL) {
      if (createNew) delete fTree;
      else return fTree;
   }

   bool b,d; double e1,c1,v,dc1p,dc1m,i;
   // define tree
   fTree=new TTree("t","field data");
   fTree->Branch("v",&v,"v/D");
   fTree->Branch("e1",&e1,"e1/D");
   fTree->Branch("c1",&c1,"c1/D");
   fTree->Branch("dc1p",&dc1p,"dc1p/D"); // step length to next point
   fTree->Branch("dc1m",&dc1m,"dc1m/D"); // step length to previous point
   fTree->Branch("b",&b,"b/O"); // boundary flag
   fTree->Branch("d",&d,"d/O"); // depletion flag
   fTree->Branch("i",&i,"i/D"); // impurity
   // fill tree
   if (fdC1p[0]==0) Initialize(); // setup & initialize grid
   if (fImpDist && fImpurity[0]==0) // set impurity values if it's not done yet
      for (int i=n;i-->0;) fImpurity[i]=fImpDist->Eval(fC1[i], fC2[i], fC3[i]);
   for (int j=0; j<n; j++) {
      v = fV[j];
      e1= fE1[j];
      c1= fC1[j];
      i = fImpurity[j];
      b = fIsFixed[j];
      d = fIsDepleted[j];
      dc1p=fdC1p[j];
      dc1m=fdC1m[j];

      fTree->Fill();
   }
   // return tree
   fTree->ResetBranchAddresses(); // disconnect from local variables
   return fTree;
}
<commit_msg>set gStyle in X constructor<commit_after>#include <TF3.h>
#include <TTree.h>
#include <TStyle.h>
#include <TStopwatch.h>

#include "X.h"
#include "Units.h"
using namespace GeFiCa;

X::X(int nx, const char *name, const char *title) : TNamed(name,title), V0(0),
   V1(2e3*volt), n1(nx), n(nx), MaxIterations(5000), Nsor(0), Csor(1.95),
   Precision(1e-7*volt)
{
   if (n<10) { Warning("X","n<10, set it to 11"); n=11; n1=11; }

   fV=new double[n];
   fE1=new double[n]; fE2=new double[n]; fE3=new double[n];
   fC1=new double[n]; fC2=new double[n]; fC3=new double[n];

   fdC1p=new double[n]; fdC1m=new double[n];
   fdC2p=new double[n]; fdC2m=new double[n];
   fdC3p=new double[n]; fdC3m=new double[n];

   fIsFixed=new bool[n];
   fIsDepleted=new bool[n];
   fImpurity=new double[n];

   for (int i=0;i<n;i++) {
      fV[i]=0;
      fE1[i]=0; fE2[i]=0; fE3[i]=0;
      fC1[i]=0; fC2[i]=0; fC3[i]=0;

      fdC1m[i]=0; fdC1p[i]=0;
      fdC2m[i]=0; fdC2p[i]=0;
      fdC3m[i]=0; fdC3p[i]=0;

      fIsFixed[i]=false;
      fIsDepleted[i]=true;
      fImpurity[i]=0;
   }

   fTree=NULL; fImpDist=NULL;

   gROOT->SetStyle("Plain"); // pick up a good default style to modify
   gStyle->SetLegendBorderSize(0);
   gStyle->SetLegendFont(132);
   gStyle->SetLabelFont(132,"XYZ");
   gStyle->SetTitleFont(132,"XYZ");
   gStyle->SetLabelSize(0.05,"XYZ");
   gStyle->SetTitleSize(0.05,"XYZ");
   gStyle->SetTitleOffset(-0.4,"Z");
   gStyle->SetPadTopMargin(0.02);
}
//_____________________________________________________________________________
//
X::~X()
{
   if (fV) delete[] fV;
   if (fE1) delete[] fE1;
   if (fC1) delete[] fC1;
   if (fdC1p) delete[] fdC1p;
   if (fdC1m) delete[] fdC1m;
   if (fIsFixed) delete[] fIsFixed;
   if (fImpurity) delete[] fImpurity;
   if (fIsDepleted) delete[] fIsDepleted;
}
//_____________________________________________________________________________
//
bool X::Analytic()
{
   Info("Analytic", "There is no analytic solution for this setup");
   return false;
}
//_____________________________________________________________________________
//
X& X::operator+=(GeFiCa::X *other)
{
   if (n!=other->n) {
      Warning("+=",
            "Only same type of detector can be added together! Do nothing.");
      return *this;
   }
   for (int i=0; i<n; i++) {
      fV[i]=fV[i]+other->fV[i];
      fImpurity[i]+=other->fImpurity[i];
   }
   V0+=other->V0; V1+=other->V1;
   return *this;
}
//_____________________________________________________________________________
//
X& X::operator*=(double p)
{
   for (int i=0; i<n; i++) fV[i]=fV[i]*p;
   V0*=p; V1*=p;
   return *this;
}
//_____________________________________________________________________________
//
int X::GetIdxOfMaxV()
{
   double max=fV[0];
   int maxn=0;
   for(int i=1;i<n;i++) {
      if(fV[i]>max) {
         maxn=i;
         max=fV[i];
      }
   }
   return maxn;
}
//_____________________________________________________________________________
//
int X::GetIdxOfMinV()
{
   double min=fV[0];
   int minn=0;
   for(int i=1;i<n;i++) {
      if(fV[i]<min) {
         minn=i;
         min=fV[i];
      }
   }
   return minn;
}
//_____________________________________________________________________________
//
bool X::IsDepleted()
{
   for(int i=0;i<n;i++) {
      DoSOR2(i); // calculate one more time in case of
      //adding two fields together, one is depleted, the other is not
      if (!fIsDepleted[i]) return false;
   }
   return true;
}
//_____________________________________________________________________________
//
void X::SetStepLength(double stepLength)
{
   for (int i=n;i-->0;) {
      fIsFixed[i]=false;
      fC1[i]=i*stepLength;
      fdC1p[i]=stepLength;
      fdC1m[i]=stepLength;
   }
}
//_____________________________________________________________________________
//
int* X::FindSurroundingMatrix(int idx)
{
   int *tmp=new int[3];
   tmp[0]=idx;
   if(idx-1<0)tmp[1]=1;
   else tmp[1]=idx-1;
   if(idx+1>=n)tmp[2]=n-2;
   else tmp[2]=idx+1;
   return tmp;
}
//_____________________________________________________________________________
//
bool X::CalculatePotential(EMethod method)
{
   if (fdC1p[0]==0) Initialize(); // setup and initialize grid if it's not done
   if (fImpDist && fImpurity[0]==0) // set impurity values if it's not done yet
      for (int i=n;i-->0;) fImpurity[i]=fImpDist->Eval(fC1[i], fC2[i], fC3[i]);
   if (method==kAnalytic) return Analytic();

   Info("CalculatePotential","Start SOR...");
   TStopwatch watch; watch.Start();
   double cp=1; // current presision
   while (Nsor<MaxIterations) {
      if (Nsor%100==0) Printf("%4d steps, precision: %.1e (target: %.0e)",
               Nsor, cp, Precision);
      double XUpSum=0;
      double XDownSum=0;
      for (int i=n-1;i>=0;i--) {
         double old=fV[i];
         DoSOR2(i);
         if(old>0)XDownSum+=old;
         else XDownSum-=old;
         double diff=fV[i]-old;
         if(diff>0)XUpSum+=(diff);
         else XUpSum-=(diff);
      }
      cp = XUpSum/XDownSum;
      Nsor++;
      if (cp<Precision) break;
   }
   for (int i=0; i<n; i++) if (!CalculateField(i)) return false;
   Printf("%4d steps, precision: %.1e (target: %.0e)", Nsor, cp, Precision);
   Info("CalculatePotential", "CPU time: %.1f s", watch.CpuTime());
   return true;
}
//_____________________________________________________________________________
//
void X::DoSOR2(int idx)
{
   // 2nd-order Runge-Kutta Successive Over-Relaxation
   if (fIsFixed[idx])return ;
   double rho=-fImpurity[idx]*Qe;
   double h2=fdC1m[idx];
   double h3=fdC1p[idx];
   double p2=fV[idx-1];
   double p3=fV[idx+1];

   double tmp=-rho/epsilon*h2*h3/2
      + (h3*fV[idx-1]+h2*fV[idx+1])/(h2+h3);

   //find minmium and maxnium of all five grid, the new one should not go overthem.
   //find min
   double min=p2;
   double max=p2;
   if(min>p3)min=p3;
   //find max
   if(max<p3)max=p3;
   //if tmp is greater or smaller than max and min, set tmp to it.

   //fV[idx]=Csor*(tmp-fV[idx])+fV[idx];
   double oldP=fV[idx];
   tmp=Csor*(tmp-oldP)+oldP;

   if(tmp<min) {
      fV[idx]=min;
      fIsDepleted[idx]=false;
   } else if(tmp>max) {
      fV[idx]=max;
      fIsDepleted[idx]=false;
   } else
      fIsDepleted[idx]=true;

   if(fIsDepleted[idx]||V0==V1) fV[idx]=tmp;
}
//_____________________________________________________________________________
//
int X::FindIdx(double tarx,int begin,int end)
{
   //search using binary search
   if (begin>=end)return end;
   int mid=(begin+end)/2;
   if(fC1[mid]>=tarx)return FindIdx(tarx,begin,mid);
   else return FindIdx(tarx,mid+1,end);
}

//_____________________________________________________________________________
//
double X::GetData(double tarx, EOutput output)
{
   int idx=FindIdx(tarx,0,n-1);
   if (idx==n) {
      switch (output) {
         case 0:return fImpurity[idx];
         case 2:return fE1[idx];
         case 1:return fV[idx];
         default: return -1;
      }
   }
   double ab=(-tarx+fC1[idx])/fdC1p[idx];
   double aa=1-ab;
   switch(output) {
      case 2:return fE1[idx]*ab+fE1[idx-1]*aa;
      case 1:return fV[idx]*ab+fC1[idx-1]*aa;
      case 0:return fImpurity[idx]*ab+fImpurity[idx-1]*aa;
      default: return -1;
   }
   return -1;
}
//_____________________________________________________________________________
//
bool X::CalculateField(int idx)
{
   if (fdC1p[idx]==0 || fdC1m[idx]==0) return false;

   if (idx%n1==0) // C1 lower boundary
      fE1[idx]=(fV[idx]-fV[idx+1])/fdC1p[idx];
   else if (idx%n1==n1-1) // C1 upper boundary
      fE1[idx]=(fV[idx]-fV[idx-1])/fdC1m[idx];
   else // bulk
      fE1[idx]=(fV[idx-1]-fV[idx+1])/(fdC1m[idx]+fdC1p[idx]);

   return true;
}
//_____________________________________________________________________________
//
double X::GetCapacitance()
{
   Info("GetCapacitance","Start...");
   // set impurity to zero
   double *tmpImpurity=fImpurity;
   for (int i=0;i<n;i++) {
      if (fImpurity[i]!=0) {
         //impurity not clear,return
         //return -1;
         fImpurity=new double[n];
         for (int j=0;j<n;j++) {
            fImpurity[j]=0;
            if (!fIsFixed[j] && !fIsDepleted[j]) fIsFixed[j]=true;
         }
         break;
      }
   }
   // calculate potential without impurity
   CalculatePotential(GeFiCa::kSOR2);
   // set impurity back
   if(fImpurity!=tmpImpurity) delete []fImpurity;
   fImpurity=tmpImpurity;

   // calculate C based on CV^2/2 = epsilon int E^2 dx^3 / 2
   double dV=V0-V1; if(dV<0)dV=-dV;
   double SumofElectricField=0;
   for(int i=0;i<n;i++) {
      SumofElectricField+=fE1[i]*fE1[i]*fdC1p[i]*cm*cm;
      if (!fIsDepleted[i]) fIsFixed[i]=false;
   }
   Info("GetCapacitance","Done.");
   return SumofElectricField*epsilon/dV/dV;
}
//_____________________________________________________________________________
//
TTree* X::GetTree(bool createNew)
{
   if (fTree!=NULL) {
      if (createNew) delete fTree;
      else return fTree;
   }

   bool b,d; double e1,c1,v,dc1p,dc1m,i;
   // define tree
   fTree=new TTree("t","field data");
   fTree->Branch("v",&v,"v/D");
   fTree->Branch("e1",&e1,"e1/D");
   fTree->Branch("c1",&c1,"c1/D");
   fTree->Branch("dc1p",&dc1p,"dc1p/D"); // step length to next point
   fTree->Branch("dc1m",&dc1m,"dc1m/D"); // step length to previous point
   fTree->Branch("b",&b,"b/O"); // boundary flag
   fTree->Branch("d",&d,"d/O"); // depletion flag
   fTree->Branch("i",&i,"i/D"); // impurity
   // fill tree
   if (fdC1p[0]==0) Initialize(); // setup & initialize grid
   if (fImpDist && fImpurity[0]==0) // set impurity values if it's not done yet
      for (int i=n;i-->0;) fImpurity[i]=fImpDist->Eval(fC1[i], fC2[i], fC3[i]);
   for (int j=0; j<n; j++) {
      v = fV[j];
      e1= fE1[j];
      c1= fC1[j];
      i = fImpurity[j];
      b = fIsFixed[j];
      d = fIsDepleted[j];
      dc1p=fdC1p[j];
      dc1m=fdC1m[j];

      fTree->Fill();
   }
   // return tree
   fTree->ResetBranchAddresses(); // disconnect from local variables
   return fTree;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// include ---------------------------------------------------------------

#include "srchxtra.hxx"
#include <tools/rcid.h>
#include <vcl/msgbox.hxx>
#include <svl/cjkoptions.hxx>
#include <svl/whiter.hxx>
#include <sfx2/objsh.hxx>
#include <cuires.hrc>
#include "srchxtra.hrc"
#include <svx/svxitems.hrc> // RID_ATTR_BEGIN
#include <svx/dialmgr.hxx>  // item resources
#include <editeng/flstitem.hxx>
#include "chardlg.hxx"
#include "paragrph.hxx"
#include <dialmgr.hxx>
#include "backgrnd.hxx"
#include <svx/dialogs.hrc> // RID_SVXPAGE_...
#include <tools/resary.hxx>
#include <rtl/strbuf.hxx>

// class SvxSearchFormatDialog -------------------------------------------

SvxSearchFormatDialog::SvxSearchFormatDialog( Window* pParent, const SfxItemSet& rSet ) :

    SfxTabDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHFORMAT ), &rSet ),

    pFontList( NULL )

{
    FreeResource();

    AddTabPage( RID_SVXPAGE_CHAR_NAME, SvxCharNamePage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_EFFECTS, SvxCharEffectsPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_POSITION, SvxCharPositionPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_TWOLINES, SvxCharTwoLinesPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_STD_PARAGRAPH, SvxStdParagraphTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_ALIGN_PARAGRAPH, SvxParaAlignTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_EXT_PARAGRAPH, SvxExtParagraphTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_PARA_ASIAN, SvxAsianTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_BACKGROUND, SvxBackgroundTabPage::Create, 0 );

    // remove asian tabpages if necessary
    SvtCJKOptions aCJKOptions;
    if ( !aCJKOptions.IsDoubleLinesEnabled() )
        RemoveTabPage( RID_SVXPAGE_CHAR_TWOLINES );
    if ( !aCJKOptions.IsAsianTypographyEnabled() )
        RemoveTabPage( RID_SVXPAGE_PARA_ASIAN );
}

// -----------------------------------------------------------------------

SvxSearchFormatDialog::~SvxSearchFormatDialog()
{
    delete pFontList;
}

// -----------------------------------------------------------------------

void SvxSearchFormatDialog::PageCreated( sal_uInt16 nId, SfxTabPage& rPage )
{
    switch ( nId )
    {
        case RID_SVXPAGE_CHAR_NAME:
        {
            const FontList* pAppFontList = 0;
            SfxObjectShell* pSh = SfxObjectShell::Current();

            if ( pSh )
            {
                const SvxFontListItem* pFLItem = (const SvxFontListItem*)
                    pSh->GetItem( SID_ATTR_CHAR_FONTLIST );
                if ( pFLItem )
                    pAppFontList = pFLItem->GetFontList();
            }

            const FontList* pList = pAppFontList;

            if ( !pList )
            {
                if ( !pFontList )
                    pFontList = new FontList( this );
                pList = pFontList;
            }

            if ( pList )
                ( (SvxCharNamePage&)rPage ).
                    SetFontList( SvxFontListItem( pList, SID_ATTR_CHAR_FONTLIST ) );
            ( (SvxCharNamePage&)rPage ).EnableSearchMode();
            break;
        }

        case RID_SVXPAGE_STD_PARAGRAPH:
            ( (SvxStdParagraphTabPage&)rPage ).EnableAutoFirstLine();
            break;

        case RID_SVXPAGE_ALIGN_PARAGRAPH:
            ( (SvxParaAlignTabPage&)rPage ).EnableJustifyExt();
            break;
        case RID_SVXPAGE_BACKGROUND :
            ( (SvxBackgroundTabPage&)rPage ).ShowParaControl(sal_True);
            break;
    }
}

// class SvxSearchFormatDialog -------------------------------------------

SvxSearchAttributeDialog::SvxSearchAttributeDialog( Window* pParent,
                                                    SearchAttrItemList& rLst,
                                                    const sal_uInt16* pWhRanges ) :

    ModalDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHATTR )  ),

    aAttrFL ( this, CUI_RES( FL_ATTR ) ),
    aAttrLB ( this, CUI_RES( LB_ATTR ) ),
    aOKBtn  ( this, CUI_RES( BTN_ATTR_OK ) ),
    aEscBtn ( this, CUI_RES( BTN_ATTR_CANCEL ) ),
    aHelpBtn( this, CUI_RES( BTN_ATTR_HELP ) ),

    rList( rLst )

{
    FreeResource();

    aAttrLB.SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_SORT );
    aAttrLB.GetModel()->SetSortMode( SortAscending );

    aOKBtn.SetClickHdl( LINK( this, SvxSearchAttributeDialog, OKHdl ) );

    SfxObjectShell* pSh = SfxObjectShell::Current();
    DBG_ASSERT( pSh, "No DocShell" );

    ResStringArray aAttrNames( SVX_RES( RID_ATTR_NAMES ) );
    SfxItemPool& rPool = pSh->GetPool();
    SfxItemSet aSet( rPool, pWhRanges );
    SfxWhichIter aIter( aSet );
    sal_uInt16 nWhich = aIter.FirstWhich();

    while ( nWhich )
    {
        sal_uInt16 nSlot = rPool.GetSlotId( nWhich );
        if ( nSlot >= SID_SVX_START )
        {
            sal_Bool bChecked = sal_False, bFound = sal_False;
            for ( sal_uInt16 i = 0; !bFound && i < rList.Count(); ++i )
            {
                if ( nSlot == rList[i].nSlot )
                {
                    bFound = sal_True;
                    if ( IsInvalidItem( rList[i].pItem ) )
                        bChecked = sal_True;
                }
            }

            // item resources are in svx
            sal_uInt32 nId  = aAttrNames.FindIndex( nSlot );
            SvLBoxEntry* pEntry = NULL;
            if ( RESARRAY_INDEX_NOTFOUND != nId )
                pEntry = aAttrLB.SvTreeListBox::InsertEntry( aAttrNames.GetString(nId) );
            else
            {
                rtl::OStringBuffer sError(
                    RTL_CONSTASCII_STRINGPARAM("no resource for slot id\nslot = "));
                sError.append(nSlot);
                DBG_ERRORFILE(sError.getStr());
            }

            if ( pEntry )
            {
                aAttrLB.SetCheckButtonState( pEntry, bChecked ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED );
                pEntry->SetUserData( (void*)(sal_uLong)nSlot );
            }
        }
        nWhich = aIter.NextWhich();
    }

    aAttrLB.SetHighlightRange();
    aAttrLB.SelectEntryPos( 0 );
}

// -----------------------------------------------------------------------

IMPL_LINK( SvxSearchAttributeDialog, OKHdl, Button *, EMPTYARG )
{
    SearchAttrItem aInvalidItem;
    aInvalidItem.pItem = (SfxPoolItem*)-1;

    for ( sal_uInt16 i = 0; i < aAttrLB.GetEntryCount(); ++i )
    {
        sal_uInt16 nSlot = (sal_uInt16)(sal_uLong)aAttrLB.GetEntryData(i);
        sal_Bool bChecked = aAttrLB.IsChecked(i);

        sal_uInt16 j;
        for ( j = rList.Count(); j; )
        {
            SearchAttrItem& rItem = rList[ --j ];
            if( rItem.nSlot == nSlot )
            {
                if( bChecked )
                {
                    if( !IsInvalidItem( rItem.pItem ) )
                        delete rItem.pItem;
                    rItem.pItem = (SfxPoolItem*)-1;
                }
                else if( IsInvalidItem( rItem.pItem ) )
                    rItem.pItem = 0;
                j = 1;
                break;
            }
        }

        if ( !j && bChecked )
        {
            aInvalidItem.nSlot = nSlot;
            rList.Insert( aInvalidItem );
        }
    }

    // remove invalid items (pItem == NULL)
    for ( sal_uInt16 n = rList.Count(); n; )
        if ( !rList[ --n ].pItem )
            rList.Remove( n );

    EndDialog( RET_OK );
    return 0;
}

// class SvxSearchSimilarityDialog ---------------------------------------

SvxSearchSimilarityDialog::SvxSearchSimilarityDialog
(
    Window* pParent,
    sal_Bool bRelax,
    sal_uInt16 nOther,
    sal_uInt16 nShorter,
    sal_uInt16 nLonger
) :
    ModalDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHSIMILARITY ) ),

    aFixedLine  ( this, CUI_RES( FL_SIMILARITY ) ),
    aOtherTxt   ( this, CUI_RES( FT_OTHER ) ),
    aOtherFld   ( this, CUI_RES( NF_OTHER   ) ),
    aLongerTxt  ( this, CUI_RES( FT_LONGER ) ),
    aLongerFld  ( this, CUI_RES( NF_LONGER ) ),
    aShorterTxt ( this, CUI_RES( FT_SHORTER ) ),
    aShorterFld ( this, CUI_RES( NF_SHORTER ) ),
    aRelaxBox   ( this, CUI_RES( CB_RELAX ) ),

    aOKBtn      ( this, CUI_RES( BTN_ATTR_OK ) ),
    aEscBtn     ( this, CUI_RES( BTN_ATTR_CANCEL ) ),
    aHelpBtn    ( this, CUI_RES( BTN_ATTR_HELP ) )

{
    FreeResource();

    aOtherFld.SetValue( nOther );
    aShorterFld.SetValue( nShorter );
    aLongerFld.SetValue( nLonger );
    aRelaxBox.Check( bRelax );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>fix ambiguity<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// include ---------------------------------------------------------------

#include "srchxtra.hxx"
#include <tools/rcid.h>
#include <vcl/msgbox.hxx>
#include <svl/cjkoptions.hxx>
#include <svl/whiter.hxx>
#include <sfx2/objsh.hxx>
#include <cuires.hrc>
#include "srchxtra.hrc"
#include <svx/svxitems.hrc> // RID_ATTR_BEGIN
#include <svx/dialmgr.hxx>  // item resources
#include <editeng/flstitem.hxx>
#include "chardlg.hxx"
#include "paragrph.hxx"
#include <dialmgr.hxx>
#include "backgrnd.hxx"
#include <svx/dialogs.hrc> // RID_SVXPAGE_...
#include <tools/resary.hxx>
#include <rtl/strbuf.hxx>

// class SvxSearchFormatDialog -------------------------------------------

SvxSearchFormatDialog::SvxSearchFormatDialog( Window* pParent, const SfxItemSet& rSet ) :

    SfxTabDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHFORMAT ), &rSet ),

    pFontList( NULL )

{
    FreeResource();

    AddTabPage( RID_SVXPAGE_CHAR_NAME, SvxCharNamePage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_EFFECTS, SvxCharEffectsPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_POSITION, SvxCharPositionPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_CHAR_TWOLINES, SvxCharTwoLinesPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_STD_PARAGRAPH, SvxStdParagraphTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_ALIGN_PARAGRAPH, SvxParaAlignTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_EXT_PARAGRAPH, SvxExtParagraphTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_PARA_ASIAN, SvxAsianTabPage::Create, 0 );
    AddTabPage( RID_SVXPAGE_BACKGROUND, SvxBackgroundTabPage::Create, 0 );

    // remove asian tabpages if necessary
    SvtCJKOptions aCJKOptions;
    if ( !aCJKOptions.IsDoubleLinesEnabled() )
        RemoveTabPage( RID_SVXPAGE_CHAR_TWOLINES );
    if ( !aCJKOptions.IsAsianTypographyEnabled() )
        RemoveTabPage( RID_SVXPAGE_PARA_ASIAN );
}

// -----------------------------------------------------------------------

SvxSearchFormatDialog::~SvxSearchFormatDialog()
{
    delete pFontList;
}

// -----------------------------------------------------------------------

void SvxSearchFormatDialog::PageCreated( sal_uInt16 nId, SfxTabPage& rPage )
{
    switch ( nId )
    {
        case RID_SVXPAGE_CHAR_NAME:
        {
            const FontList* pAppFontList = 0;
            SfxObjectShell* pSh = SfxObjectShell::Current();

            if ( pSh )
            {
                const SvxFontListItem* pFLItem = (const SvxFontListItem*)
                    pSh->GetItem( SID_ATTR_CHAR_FONTLIST );
                if ( pFLItem )
                    pAppFontList = pFLItem->GetFontList();
            }

            const FontList* pList = pAppFontList;

            if ( !pList )
            {
                if ( !pFontList )
                    pFontList = new FontList( this );
                pList = pFontList;
            }

            if ( pList )
                ( (SvxCharNamePage&)rPage ).
                    SetFontList( SvxFontListItem( pList, SID_ATTR_CHAR_FONTLIST ) );
            ( (SvxCharNamePage&)rPage ).EnableSearchMode();
            break;
        }

        case RID_SVXPAGE_STD_PARAGRAPH:
            ( (SvxStdParagraphTabPage&)rPage ).EnableAutoFirstLine();
            break;

        case RID_SVXPAGE_ALIGN_PARAGRAPH:
            ( (SvxParaAlignTabPage&)rPage ).EnableJustifyExt();
            break;
        case RID_SVXPAGE_BACKGROUND :
            ( (SvxBackgroundTabPage&)rPage ).ShowParaControl(sal_True);
            break;
    }
}

// class SvxSearchFormatDialog -------------------------------------------

SvxSearchAttributeDialog::SvxSearchAttributeDialog( Window* pParent,
                                                    SearchAttrItemList& rLst,
                                                    const sal_uInt16* pWhRanges ) :

    ModalDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHATTR )  ),

    aAttrFL ( this, CUI_RES( FL_ATTR ) ),
    aAttrLB ( this, CUI_RES( LB_ATTR ) ),
    aOKBtn  ( this, CUI_RES( BTN_ATTR_OK ) ),
    aEscBtn ( this, CUI_RES( BTN_ATTR_CANCEL ) ),
    aHelpBtn( this, CUI_RES( BTN_ATTR_HELP ) ),

    rList( rLst )

{
    FreeResource();

    aAttrLB.SetStyle( GetStyle() | WB_CLIPCHILDREN | WB_HSCROLL | WB_SORT );
    aAttrLB.GetModel()->SetSortMode( SortAscending );

    aOKBtn.SetClickHdl( LINK( this, SvxSearchAttributeDialog, OKHdl ) );

    SfxObjectShell* pSh = SfxObjectShell::Current();
    DBG_ASSERT( pSh, "No DocShell" );

    ResStringArray aAttrNames( SVX_RES( RID_ATTR_NAMES ) );
    SfxItemPool& rPool = pSh->GetPool();
    SfxItemSet aSet( rPool, pWhRanges );
    SfxWhichIter aIter( aSet );
    sal_uInt16 nWhich = aIter.FirstWhich();

    while ( nWhich )
    {
        sal_uInt16 nSlot = rPool.GetSlotId( nWhich );
        if ( nSlot >= SID_SVX_START )
        {
            sal_Bool bChecked = sal_False, bFound = sal_False;
            for ( sal_uInt16 i = 0; !bFound && i < rList.Count(); ++i )
            {
                if ( nSlot == rList[i].nSlot )
                {
                    bFound = sal_True;
                    if ( IsInvalidItem( rList[i].pItem ) )
                        bChecked = sal_True;
                }
            }

            // item resources are in svx
            sal_uInt32 nId  = aAttrNames.FindIndex( nSlot );
            SvLBoxEntry* pEntry = NULL;
            if ( RESARRAY_INDEX_NOTFOUND != nId )
                pEntry = aAttrLB.SvTreeListBox::InsertEntry( aAttrNames.GetString(nId) );
            else
            {
                rtl::OStringBuffer sError(
                    RTL_CONSTASCII_STRINGPARAM("no resource for slot id\nslot = "));
                sError.append(static_cast<sal_Int32>(nSlot));
                DBG_ERRORFILE(sError.getStr());
            }

            if ( pEntry )
            {
                aAttrLB.SetCheckButtonState( pEntry, bChecked ? SV_BUTTON_CHECKED : SV_BUTTON_UNCHECKED );
                pEntry->SetUserData( (void*)(sal_uLong)nSlot );
            }
        }
        nWhich = aIter.NextWhich();
    }

    aAttrLB.SetHighlightRange();
    aAttrLB.SelectEntryPos( 0 );
}

// -----------------------------------------------------------------------

IMPL_LINK( SvxSearchAttributeDialog, OKHdl, Button *, EMPTYARG )
{
    SearchAttrItem aInvalidItem;
    aInvalidItem.pItem = (SfxPoolItem*)-1;

    for ( sal_uInt16 i = 0; i < aAttrLB.GetEntryCount(); ++i )
    {
        sal_uInt16 nSlot = (sal_uInt16)(sal_uLong)aAttrLB.GetEntryData(i);
        sal_Bool bChecked = aAttrLB.IsChecked(i);

        sal_uInt16 j;
        for ( j = rList.Count(); j; )
        {
            SearchAttrItem& rItem = rList[ --j ];
            if( rItem.nSlot == nSlot )
            {
                if( bChecked )
                {
                    if( !IsInvalidItem( rItem.pItem ) )
                        delete rItem.pItem;
                    rItem.pItem = (SfxPoolItem*)-1;
                }
                else if( IsInvalidItem( rItem.pItem ) )
                    rItem.pItem = 0;
                j = 1;
                break;
            }
        }

        if ( !j && bChecked )
        {
            aInvalidItem.nSlot = nSlot;
            rList.Insert( aInvalidItem );
        }
    }

    // remove invalid items (pItem == NULL)
    for ( sal_uInt16 n = rList.Count(); n; )
        if ( !rList[ --n ].pItem )
            rList.Remove( n );

    EndDialog( RET_OK );
    return 0;
}

// class SvxSearchSimilarityDialog ---------------------------------------

SvxSearchSimilarityDialog::SvxSearchSimilarityDialog
(
    Window* pParent,
    sal_Bool bRelax,
    sal_uInt16 nOther,
    sal_uInt16 nShorter,
    sal_uInt16 nLonger
) :
    ModalDialog( pParent, CUI_RES( RID_SVXDLG_SEARCHSIMILARITY ) ),

    aFixedLine  ( this, CUI_RES( FL_SIMILARITY ) ),
    aOtherTxt   ( this, CUI_RES( FT_OTHER ) ),
    aOtherFld   ( this, CUI_RES( NF_OTHER   ) ),
    aLongerTxt  ( this, CUI_RES( FT_LONGER ) ),
    aLongerFld  ( this, CUI_RES( NF_LONGER ) ),
    aShorterTxt ( this, CUI_RES( FT_SHORTER ) ),
    aShorterFld ( this, CUI_RES( NF_SHORTER ) ),
    aRelaxBox   ( this, CUI_RES( CB_RELAX ) ),

    aOKBtn      ( this, CUI_RES( BTN_ATTR_OK ) ),
    aEscBtn     ( this, CUI_RES( BTN_ATTR_CANCEL ) ),
    aHelpBtn    ( this, CUI_RES( BTN_ATTR_HELP ) )

{
    FreeResource();

    aOtherFld.SetValue( nOther );
    aShorterFld.SetValue( nShorter );
    aLongerFld.SetValue( nLonger );
    aRelaxBox.Check( bRelax );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

// eth_arpback.cc  - basic ethernet packetmover, only responds to ARP

// Various networking docs:
// http://www.graphcomp.com/info/rfc/
// rfc0826: arp
// rfc0903: rarp

#include "bochs.h"
#include "crc32.h"
#define LOG_THIS bx_ne2k.

static const Bit8u external_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00};
static const Bit8u external_ip[]={ 192, 168, 0, 2, 0x00 };
static const Bit8u broadcast_mac[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};

#define MAX_FRAME_SIZE 2048

//
//  Define the class. This is private to this module
//
class bx_arpback_pktmover_c : public eth_pktmover_c {
public:
  bx_arpback_pktmover_c(const char *netif, const char *macaddr,
		     eth_rx_handler_t rxh,
		     void *rxarg);
  void sendpkt(void *buf, unsigned io_len);
private:
  int rx_timer_index;
  static void rx_timer_handler(void *);
  void rx_timer(void);
  FILE *txlog, *txlog_txt;
  Bit8u arpbuf[MAX_FRAME_SIZE];
  Bit32u buflen;
  Boolean bufvalid;
  CRC_Generator mycrc;
};

//
//  Define the static class that registers the derived pktmover class,
// and allocates one on request.
//
class bx_arpback_locator_c : public eth_locator_c {
public:
  bx_arpback_locator_c(void) : eth_locator_c("arpback") {}
protected:
  eth_pktmover_c *allocate(const char *netif, const char *macaddr,
			   eth_rx_handler_t rxh,
			   void *rxarg) {
    return (new bx_arpback_pktmover_c(netif, macaddr, rxh, rxarg));
  }
} bx_arpback_match;

//
// Define the methods for the bx_arpback_pktmover derived class
//

// the constructor
bx_arpback_pktmover_c::bx_arpback_pktmover_c(const char *netif,
				       const char *macaddr,
				       eth_rx_handler_t rxh,
				       void *rxarg)
{
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
				1, 1); // continuous, active
  this->rxh   = rxh;
  this->rxarg = rxarg;
  bufvalid=0;
#if BX_ETH_NULL_LOGGING
  // Start the rx poll
  // eventually Bryce wants txlog to dump in pcap format so that
  // tcpdump -r FILE can read it and interpret packets.
  txlog = fopen ("ne2k-tx.log", "wb");
  if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
  txlog_txt = fopen ("ne2k-txdump.txt", "wb");
  if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
  fprintf (txlog_txt, "arpback packetmover readable log file\n");
  fprintf (txlog_txt, "net IF = %s\n", netif);
  fprintf (txlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf (txlog_txt, "\n--\n");
  fflush (txlog_txt);
#endif
}

void
bx_arpback_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
  if(io_len<MAX_FRAME_SIZE) {
    if((!memcmp(buf, external_mac, 6)) || (!memcmp(buf, broadcast_mac, 6)) ) {
      Bit32u tempcrc;
      memcpy(arpbuf,buf,io_len); //move to temporary buffer
      memcpy(arpbuf, arpbuf+6, 6); //set destination to sender
      memcpy(arpbuf+6, external_mac, 6); //set sender to us
      memcpy(arpbuf+32, arpbuf+22, 10); //move destination to sender
      memcpy(arpbuf+22, external_mac, 6); //set sender to us
      memcpy(arpbuf+28, external_ip, 4); //set sender to us
      arpbuf[21]=2; //make this a reply and not a request
      tempcrc=mycrc.get_CRC(arpbuf,io_len);
      memcpy(arpbuf+io_len, &tempcrc, 4);
      buflen=io_len+4;
      bufvalid=1;
    }
  }
#if BX_ETH_NULL_LOGGING
  BX_DEBUG (("sendpkt length %u", io_len));
  // dump raw bytes to a file, eventually dump in pcap format so that
  // tcpdump -r FILE can interpret them for us.
  int n = fwrite (buf, io_len, 1, txlog);
  if (n != 1) BX_ERROR (("fwrite to txlog failed", io_len));
  // dump packet in hex into an ascii log file
  fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
  Bit8u *charbuf = (Bit8u *)buf;
  for (n=0; n<io_len; n++) {
    if (((n % 16) == 0) && n>0)
      fprintf (txlog_txt, "\n");
    fprintf (txlog_txt, "%02x ", charbuf[n]);
  }
  fprintf (txlog_txt, "\n--\n");
  // flush log so that we see the packets as they arrive w/o buffering
  fflush (txlog);
  fflush (txlog_txt);
#endif
}

void bx_arpback_pktmover_c::rx_timer_handler (void * this_ptr)
{
#if BX_ETH_NULL_LOGGING
  BX_DEBUG (("rx_timer_handler"));
#endif
  bx_arpback_pktmover_c *class_ptr = ((bx_arpback_pktmover_c *)this_ptr);

  class_ptr->rx_timer();
}

void bx_arpback_pktmover_c::rx_timer (void)
{
  int nbytes = 0;
  struct bpf_hdr *bhdr;

  if(bufvalid) {
    bufvalid=0;
    void * buf=arpbuf;
    unsigned io_len=buflen;
    Bit32u n;
    fprintf (txlog_txt, "NE2K receiving a packet, length %u\n", io_len);
    Bit8u *charbuf = (Bit8u *)buf;
    for (n=0; n<io_len; n++) {
      if (((n % 16) == 0) && n>0)
	fprintf (txlog_txt, "\n");
      fprintf (txlog_txt, "%02x ", charbuf[n]);
    }
    fprintf (txlog_txt, "\n--\n");
    fflush (txlog_txt);

    (*rxh)(rxarg, buf, io_len);
  }
}

<commit_msg>Only respond to ARP packets.<commit_after>//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

// eth_arpback.cc  - basic ethernet packetmover, only responds to ARP

// Various networking docs:
// http://www.graphcomp.com/info/rfc/
// rfc0826: arp
// rfc0903: rarp

#include "bochs.h"
#include "crc32.h"
#define LOG_THIS bx_ne2k.

static const Bit8u external_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00};
static const Bit8u external_ip[]={ 192, 168, 0, 2, 0x00 };
static const Bit8u broadcast_mac[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
static const Bit8u ethtype_arp[]={0x08, 0x06, 0x00};

#define MAX_FRAME_SIZE 2048

//
//  Define the class. This is private to this module
//
class bx_arpback_pktmover_c : public eth_pktmover_c {
public:
  bx_arpback_pktmover_c(const char *netif, const char *macaddr,
		     eth_rx_handler_t rxh,
		     void *rxarg);
  void sendpkt(void *buf, unsigned io_len);
private:
  int rx_timer_index;
  static void rx_timer_handler(void *);
  void rx_timer(void);
  FILE *txlog, *txlog_txt;
  Bit8u arpbuf[MAX_FRAME_SIZE];
  Bit32u buflen;
  Boolean bufvalid;
  CRC_Generator mycrc;
};

//
//  Define the static class that registers the derived pktmover class,
// and allocates one on request.
//
class bx_arpback_locator_c : public eth_locator_c {
public:
  bx_arpback_locator_c(void) : eth_locator_c("arpback") {}
protected:
  eth_pktmover_c *allocate(const char *netif, const char *macaddr,
			   eth_rx_handler_t rxh,
			   void *rxarg) {
    return (new bx_arpback_pktmover_c(netif, macaddr, rxh, rxarg));
  }
} bx_arpback_match;

//
// Define the methods for the bx_arpback_pktmover derived class
//

// the constructor
bx_arpback_pktmover_c::bx_arpback_pktmover_c(const char *netif,
				       const char *macaddr,
				       eth_rx_handler_t rxh,
				       void *rxarg)
{
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
				1, 1); // continuous, active
  this->rxh   = rxh;
  this->rxarg = rxarg;
  bufvalid=0;
#if BX_ETH_NULL_LOGGING
  // Start the rx poll
  // eventually Bryce wants txlog to dump in pcap format so that
  // tcpdump -r FILE can read it and interpret packets.
  txlog = fopen ("ne2k-tx.log", "wb");
  if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
  txlog_txt = fopen ("ne2k-txdump.txt", "wb");
  if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
  fprintf (txlog_txt, "arpback packetmover readable log file\n");
  fprintf (txlog_txt, "net IF = %s\n", netif);
  fprintf (txlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf (txlog_txt, "\n--\n");
  fflush (txlog_txt);
#endif
}

void
bx_arpback_pktmover_c::sendpkt(void *buf, unsigned io_len)
{
  if(io_len<MAX_FRAME_SIZE) {
    if(( (!memcmp(buf, external_mac, 6)) || (!memcmp(buf, broadcast_mac, 6)) )
       && (!memcmp(((Bit8u *)buf)+12, ethtype_arp, 2)) ) {
      Bit32u tempcrc;
      memcpy(arpbuf,buf,io_len); //move to temporary buffer
      memcpy(arpbuf, arpbuf+6, 6); //set destination to sender
      memcpy(arpbuf+6, external_mac, 6); //set sender to us
      memcpy(arpbuf+32, arpbuf+22, 10); //move destination to sender
      memcpy(arpbuf+22, external_mac, 6); //set sender to us
      memcpy(arpbuf+28, external_ip, 4); //set sender to us
      arpbuf[21]=2; //make this a reply and not a request
      tempcrc=mycrc.get_CRC(arpbuf,io_len);
      memcpy(arpbuf+io_len, &tempcrc, 4);
      buflen=io_len/*+4*/;
      bufvalid=1;
    }
  }
#if BX_ETH_NULL_LOGGING
  BX_DEBUG (("sendpkt length %u", io_len));
  // dump raw bytes to a file, eventually dump in pcap format so that
  // tcpdump -r FILE can interpret them for us.
  int n = fwrite (buf, io_len, 1, txlog);
  if (n != 1) BX_ERROR (("fwrite to txlog failed", io_len));
  // dump packet in hex into an ascii log file
  fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
  Bit8u *charbuf = (Bit8u *)buf;
  for (n=0; n<io_len; n++) {
    if (((n % 16) == 0) && n>0)
      fprintf (txlog_txt, "\n");
    fprintf (txlog_txt, "%02x ", charbuf[n]);
  }
  fprintf (txlog_txt, "\n--\n");
  // flush log so that we see the packets as they arrive w/o buffering
  fflush (txlog);
  fflush (txlog_txt);
#endif
}

void bx_arpback_pktmover_c::rx_timer_handler (void * this_ptr)
{
#if BX_ETH_NULL_LOGGING
  BX_DEBUG (("rx_timer_handler"));
#endif
  bx_arpback_pktmover_c *class_ptr = ((bx_arpback_pktmover_c *)this_ptr);

  class_ptr->rx_timer();
}

void bx_arpback_pktmover_c::rx_timer (void)
{
  int nbytes = 0;
  struct bpf_hdr *bhdr;

  if(bufvalid) {
    bufvalid=0;
    void * buf=arpbuf;
    unsigned io_len=buflen;
    Bit32u n;
    fprintf (txlog_txt, "NE2K receiving a packet, length %u\n", io_len);
    Bit8u *charbuf = (Bit8u *)buf;
    for (n=0; n<io_len; n++) {
      if (((n % 16) == 0) && n>0)
	fprintf (txlog_txt, "\n");
      fprintf (txlog_txt, "%02x ", charbuf[n]);
    }
    fprintf (txlog_txt, "\n--\n");
    fflush (txlog_txt);

    (*rxh)(rxarg, buf, io_len);
  }
}

<|endoftext|>


<commit_before>#include "Config.hpp"
#include "EventWatcher.hpp"
#include "KeyOverlaidModifier.hpp"
#include "VirtualKey.hpp"

namespace org_pqrs_KeyRemap4MacBook {
  namespace RemapFunc {
    TimerWrapper KeyOverlaidModifier::firerepeat_timer_;
    KeyOverlaidModifier* KeyOverlaidModifier::target_ = NULL;

    void
    KeyOverlaidModifier::static_initialize(IOWorkLoop& workloop)
    {
      firerepeat_timer_.initialize(&workloop, NULL, KeyOverlaidModifier::firerepeat_timer_callback);
    }

    void
    KeyOverlaidModifier::static_terminate(void)
    {
      firerepeat_timer_.terminate();
    }

    KeyOverlaidModifier::KeyOverlaidModifier(void) :
      index_(0), isAnyEventHappen_(false), savedflags_(0), isRepeatEnabled_(false)
    {
      ic_.begin();
    }

    KeyOverlaidModifier::~KeyOverlaidModifier(void)
    {
      if (target_ == this) {
        firerepeat_timer_.cancelTimeout();
        target_ = NULL;
      }
    }

    void
    KeyOverlaidModifier::add(unsigned int datatype, unsigned int newval)
    {
      switch (datatype) {
        case BRIDGE_DATATYPE_KEYCODE:
        {
          switch (index_) {
            case 0:
              keytokey_.add(KeyCode(newval));
              keytokey_fire_.add(KeyCode::VK_PSEUDO_KEY);
              break;

            case 1:
              toKey_.key = newval;
              keytokey_.add(KeyCode(newval));
              break;

            default:
              keytokey_fire_.add(KeyCode(newval));
              break;
          }
          ++index_;

          break;
        }

        case BRIDGE_DATATYPE_FLAGS:
        {
          switch (index_) {
            case 0:
              IOLOG_ERROR("Invalid KeyOverlaidModifier::add\n");
              break;

            case 1:
              keytokey_.add(Flags(newval));
              break;

            case 2:
              toKey_.flags = newval;
              keytokey_.add(Flags(newval));
              break;

            default:
              keytokey_fire_.add(Flags(newval));
              break;
          }
          break;
        }

        case BRIDGE_DATATYPE_OPTION:
        {
          if (Option::KEYOVERLAIDMODIFIER_REPEAT == newval) {
            isRepeatEnabled_ = true;
          } else {
            IOLOG_ERROR("KeyOverlaidModifier::add unknown option:%d\n", newval);
          }
          break;
        }

        default:
          IOLOG_ERROR("KeyOverlaidModifier::add invalid datatype:%d\n", datatype);
          break;
      }
    }

    bool
    KeyOverlaidModifier::remap(RemapParams& remapParams)
    {
      bool savedIsAnyEventHappen = isAnyEventHappen_;

      bool result = keytokey_.remap(remapParams);
      if (! result) return false;

      // ------------------------------------------------------------
      IOLockWrapper::ScopedLock lk(firerepeat_timer_.getlock());

      if (remapParams.params.ex_iskeydown) {
        EventWatcher::set(isAnyEventHappen_);
        ic_.begin();

        // ----------------------------------------
        // We store the flags when KeyDown.
        // Because it lets you make a natural input when the following sequence.
        //
        // ex. "Space to Shift (when type only, send Space)"
        // (1) KeyDown Command_L
        // (2) KeyDown Space        save flags (Command_L)
        // (3) KeyUp   Command_L
        // (4) KeyUp   Space        fire Command_L+Space

        FlagStatus::temporary_decrease(toKey_.flags | toKey_.key.getModifierFlag() | Handle_VK_LAZY::getModifierFlag(toKey_.key));
        savedflags_ = FlagStatus::makeFlags();
        FlagStatus::temporary_increase(toKey_.flags | toKey_.key.getModifierFlag() | Handle_VK_LAZY::getModifierFlag(toKey_.key));

        // ----------------------------------------
        if (isRepeatEnabled_) {
          target_ = this;
          isfirenormal_ = false;
          isfirerepeat_ = false;
          firerepeat_timer_.setTimeoutMS(Config::get_keyoverlaidmodifier_initial_wait());
        }

      } else {
        firerepeat_timer_.cancelTimeout();

        if (isfirerepeat_) {
          FlagStatus::ScopedTemporaryFlagsChanger stfc(savedflags_);
          keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::UP);

        } else {
          isfirenormal_ = true;

          if (savedIsAnyEventHappen == false) {
            int timeout = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_parameter_keyoverlaidmodifier_timeout);
            if (timeout <= 0 || ic_.checkThreshold(timeout) == false) {
              FlagStatus::ScopedTemporaryFlagsChanger stfc(savedflags_);

              keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::DOWN);
              keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::UP);
            }
          }
          EventWatcher::unset(isAnyEventHappen_);
        }
      }

      return true;
    }

    void
    KeyOverlaidModifier::firerepeat_timer_callback(OSObject* owner, IOTimerEventSource* sender)
    {
      IOLockWrapper::ScopedLock lk(firerepeat_timer_.getlock());

      if (! target_) return;

      if (target_->isAnyEventHappen_) return;

      if (! target_->isfirenormal_) {
        target_->isfirerepeat_ = true;

        FlagStatus::ScopedTemporaryFlagsChanger stfc(target_->savedflags_);
        (target_->keytokey_fire_).call_remap_with_VK_PSEUDO_KEY(EventType::DOWN);
      }
    }
  }
}
<commit_msg>remove unnecessary ScopedLock<commit_after>#include "Config.hpp"
#include "EventWatcher.hpp"
#include "KeyOverlaidModifier.hpp"
#include "VirtualKey.hpp"

namespace org_pqrs_KeyRemap4MacBook {
  namespace RemapFunc {
    TimerWrapper KeyOverlaidModifier::firerepeat_timer_;
    KeyOverlaidModifier* KeyOverlaidModifier::target_ = NULL;

    void
    KeyOverlaidModifier::static_initialize(IOWorkLoop& workloop)
    {
      firerepeat_timer_.initialize(&workloop, NULL, KeyOverlaidModifier::firerepeat_timer_callback);
    }

    void
    KeyOverlaidModifier::static_terminate(void)
    {
      firerepeat_timer_.terminate();
    }

    KeyOverlaidModifier::KeyOverlaidModifier(void) :
      index_(0), isAnyEventHappen_(false), savedflags_(0), isRepeatEnabled_(false)
    {
      ic_.begin();
    }

    KeyOverlaidModifier::~KeyOverlaidModifier(void)
    {
      if (target_ == this) {
        firerepeat_timer_.cancelTimeout();
        target_ = NULL;
      }
    }

    void
    KeyOverlaidModifier::add(unsigned int datatype, unsigned int newval)
    {
      switch (datatype) {
        case BRIDGE_DATATYPE_KEYCODE:
        {
          switch (index_) {
            case 0:
              keytokey_.add(KeyCode(newval));
              keytokey_fire_.add(KeyCode::VK_PSEUDO_KEY);
              break;

            case 1:
              toKey_.key = newval;
              keytokey_.add(KeyCode(newval));
              break;

            default:
              keytokey_fire_.add(KeyCode(newval));
              break;
          }
          ++index_;

          break;
        }

        case BRIDGE_DATATYPE_FLAGS:
        {
          switch (index_) {
            case 0:
              IOLOG_ERROR("Invalid KeyOverlaidModifier::add\n");
              break;

            case 1:
              keytokey_.add(Flags(newval));
              break;

            case 2:
              toKey_.flags = newval;
              keytokey_.add(Flags(newval));
              break;

            default:
              keytokey_fire_.add(Flags(newval));
              break;
          }
          break;
        }

        case BRIDGE_DATATYPE_OPTION:
        {
          if (Option::KEYOVERLAIDMODIFIER_REPEAT == newval) {
            isRepeatEnabled_ = true;
          } else {
            IOLOG_ERROR("KeyOverlaidModifier::add unknown option:%d\n", newval);
          }
          break;
        }

        default:
          IOLOG_ERROR("KeyOverlaidModifier::add invalid datatype:%d\n", datatype);
          break;
      }
    }

    bool
    KeyOverlaidModifier::remap(RemapParams& remapParams)
    {
      bool savedIsAnyEventHappen = isAnyEventHappen_;

      bool result = keytokey_.remap(remapParams);
      if (! result) return false;

      // ------------------------------------------------------------
      if (remapParams.params.ex_iskeydown) {
        EventWatcher::set(isAnyEventHappen_);
        ic_.begin();

        // ----------------------------------------
        // We store the flags when KeyDown.
        // Because it lets you make a natural input when the following sequence.
        //
        // ex. "Space to Shift (when type only, send Space)"
        // (1) KeyDown Command_L
        // (2) KeyDown Space        save flags (Command_L)
        // (3) KeyUp   Command_L
        // (4) KeyUp   Space        fire Command_L+Space

        FlagStatus::temporary_decrease(toKey_.flags | toKey_.key.getModifierFlag() | Handle_VK_LAZY::getModifierFlag(toKey_.key));
        savedflags_ = FlagStatus::makeFlags();
        FlagStatus::temporary_increase(toKey_.flags | toKey_.key.getModifierFlag() | Handle_VK_LAZY::getModifierFlag(toKey_.key));

        // ----------------------------------------
        if (isRepeatEnabled_) {
          target_ = this;
          isfirenormal_ = false;
          isfirerepeat_ = false;
          firerepeat_timer_.setTimeoutMS(Config::get_keyoverlaidmodifier_initial_wait());
        }

      } else {
        firerepeat_timer_.cancelTimeout();

        if (isfirerepeat_) {
          FlagStatus::ScopedTemporaryFlagsChanger stfc(savedflags_);
          keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::UP);

        } else {
          isfirenormal_ = true;

          if (savedIsAnyEventHappen == false) {
            int timeout = Config::get_essential_config(BRIDGE_ESSENTIAL_CONFIG_INDEX_parameter_keyoverlaidmodifier_timeout);
            if (timeout <= 0 || ic_.checkThreshold(timeout) == false) {
              FlagStatus::ScopedTemporaryFlagsChanger stfc(savedflags_);

              keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::DOWN);
              keytokey_fire_.call_remap_with_VK_PSEUDO_KEY(EventType::UP);
            }
          }
          EventWatcher::unset(isAnyEventHappen_);
        }
      }

      return true;
    }

    void
    KeyOverlaidModifier::firerepeat_timer_callback(OSObject* owner, IOTimerEventSource* sender)
    {
      if (! target_) return;

      if (target_->isAnyEventHappen_) return;

      if (! target_->isfirenormal_) {
        target_->isfirerepeat_ = true;

        FlagStatus::ScopedTemporaryFlagsChanger stfc(target_->savedflags_);
        (target_->keytokey_fire_).call_remap_with_VK_PSEUDO_KEY(EventType::DOWN);
      }
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "riegeli/bytes/string_writer.h"

#include <stddef.h>

#include <string>
#include <utility>

#include "absl/base/optimization.h"
#include "absl/strings/string_view.h"
#include "riegeli/base/base.h"
#include "riegeli/base/chain.h"
#include "riegeli/base/memory.h"
#include "riegeli/bytes/writer.h"

namespace riegeli {

void StringWriterBase::Done() {
  if (ABSL_PREDICT_TRUE(healthy())) {
    std::string* const dest = dest_string();
    RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
        << "StringWriter destination changed unexpectedly";
    SyncBuffer(dest);
  }
  Writer::Done();
}

bool StringWriterBase::PushSlow(size_t min_length, size_t recommended_length) {
  RIEGELI_ASSERT_GT(min_length, available())
      << "Failed precondition of Writer::PushSlow(): "
         "length too small, use Push() instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  SyncBuffer(dest);
  if (min_length > dest->capacity() - dest->size()) {
    if (ABSL_PREDICT_FALSE(min_length > dest->max_size() - dest->size())) {
      return FailOverflow();
    }
    dest->reserve(
        UnsignedMin(UnsignedMax(SaturatingAdd(dest->size(), recommended_length),
                                // Double the size, and round up to one below a
                                // possible allocated size (for NUL terminator).
                                EstimatedAllocatedSize(SaturatingAdd(
                                    dest->size(), dest->size(), size_t{1})) -
                                    1,
                                dest->size() + min_length),
                    dest->max_size()));
  }
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(absl::string_view src) {
  RIEGELI_ASSERT_GT(src.size(), available())
      << "Failed precondition of Writer::WriteSlow(string_view): "
         "length too small, use Write(string_view) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  dest->append(src.data(), src.size());
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(const Chain& src) {
  RIEGELI_ASSERT_GT(src.size(), UnsignedMin(available(), kMaxBytesToCopy))
      << "Failed precondition of Writer::WriteSlow(Chain): "
         "length too small, use Write(Chain) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  src.AppendTo(dest);
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(Chain&& src) {
  RIEGELI_ASSERT_GT(src.size(), UnsignedMin(available(), kMaxBytesToCopy))
      << "Failed precondition of Writer::WriteSlow(Chain&&): "
         "length too small, use Write(Chain) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  std::move(src).AppendTo(dest);
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::Flush(FlushType flush_type) {
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  SyncBuffer(dest);
  return true;
}

bool StringWriterBase::Truncate(Position new_size) {
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(new_size > written_to_buffer())) return false;
  cursor_ = start_ + new_size;
  return true;
}

inline void StringWriterBase::SyncBuffer(std::string* dest) {
  dest->erase(written_to_buffer());
  start_ = &(*dest)[0];
  cursor_ = start_ + dest->size();
  limit_ = cursor_;
}

inline void StringWriterBase::MakeBuffer(std::string* dest) {
  const size_t cursor_pos = dest->size();
  dest->resize(dest->capacity());
  start_ = &(*dest)[0];
  cursor_ = start_ + cursor_pos;
  limit_ = start_ + dest->size();
}

}  // namespace riegeli
<commit_msg>Tune string sizing in StringWriter.<commit_after>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "riegeli/bytes/string_writer.h"

#include <stddef.h>

#include <string>
#include <utility>

#include "absl/base/optimization.h"
#include "absl/strings/string_view.h"
#include "riegeli/base/base.h"
#include "riegeli/base/chain.h"
#include "riegeli/base/memory.h"
#include "riegeli/bytes/writer.h"

namespace riegeli {

void StringWriterBase::Done() {
  if (ABSL_PREDICT_TRUE(healthy())) {
    std::string* const dest = dest_string();
    RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
        << "StringWriter destination changed unexpectedly";
    SyncBuffer(dest);
  }
  Writer::Done();
}

bool StringWriterBase::PushSlow(size_t min_length, size_t recommended_length) {
  RIEGELI_ASSERT_GT(min_length, available())
      << "Failed precondition of Writer::PushSlow(): "
         "length too small, use Push() instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  SyncBuffer(dest);
  if (min_length > dest->capacity() - dest->size()) {
    if (ABSL_PREDICT_FALSE(min_length > dest->max_size() - dest->size())) {
      return FailOverflow();
    }
    dest->reserve(UnsignedMin(
        UnsignedMax(SaturatingAdd(dest->size(),
                                  UnsignedMax(min_length, recommended_length)),
                    // Double the capacity, and round up to one below a possible
                    // allocated size (for NUL terminator).
                    EstimatedAllocatedSize(SaturatingAdd(
                        dest->capacity(), dest->capacity(), size_t{1})) -
                        1),
        dest->max_size()));
  }
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(absl::string_view src) {
  RIEGELI_ASSERT_GT(src.size(), available())
      << "Failed precondition of Writer::WriteSlow(string_view): "
         "length too small, use Write(string_view) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  dest->append(src.data(), src.size());
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(const Chain& src) {
  RIEGELI_ASSERT_GT(src.size(), UnsignedMin(available(), kMaxBytesToCopy))
      << "Failed precondition of Writer::WriteSlow(Chain): "
         "length too small, use Write(Chain) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  src.AppendTo(dest);
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::WriteSlow(Chain&& src) {
  RIEGELI_ASSERT_GT(src.size(), UnsignedMin(available(), kMaxBytesToCopy))
      << "Failed precondition of Writer::WriteSlow(Chain&&): "
         "length too small, use Write(Chain) instead";
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(src.size() > dest->max_size() - written_to_buffer())) {
    return FailOverflow();
  }
  SyncBuffer(dest);
  std::move(src).AppendTo(dest);
  MakeBuffer(dest);
  return true;
}

bool StringWriterBase::Flush(FlushType flush_type) {
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  SyncBuffer(dest);
  return true;
}

bool StringWriterBase::Truncate(Position new_size) {
  if (ABSL_PREDICT_FALSE(!healthy())) return false;
  std::string* const dest = dest_string();
  RIEGELI_ASSERT_EQ(buffer_size(), dest->size())
      << "StringWriter destination changed unexpectedly";
  if (ABSL_PREDICT_FALSE(new_size > written_to_buffer())) return false;
  cursor_ = start_ + new_size;
  return true;
}

inline void StringWriterBase::SyncBuffer(std::string* dest) {
  dest->erase(written_to_buffer());
  start_ = &(*dest)[0];
  cursor_ = start_ + dest->size();
  limit_ = cursor_;
}

inline void StringWriterBase::MakeBuffer(std::string* dest) {
  const size_t cursor_pos = dest->size();
  dest->resize(dest->capacity());
  start_ = &(*dest)[0];
  cursor_ = start_ + cursor_pos;
  limit_ = start_ + dest->size();
}

}  // namespace riegeli
<|endoftext|>