<commit_before>// @(#) $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTLogging.cxx
    @author Matthias Richter, Timm Steinbeck
    @date
    @brief  Implementation of HLT logging primitives.
*/

#if __GNUC__>= 3
using namespace std;
#endif

#include "AliHLTStdIncludes.h"
#include "AliHLTLogging.h"
#include "AliHLTComponentHandler.h"
#include "TString.h"
#include "Varargs.h"
#include <string>
#include <sstream>
#include <iostream>

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTLogging);

AliHLTLogging::AliHLTLogging()
  :
  fLocalLogFilter(fgLocalLogDefault),
  fpDefaultKeyword(NULL),
  fpCurrentKeyword(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTLogging::AliHLTLogging(const AliHLTLogging&)
  :
  fLocalLogFilter(kHLTLogAll),
  fpDefaultKeyword(NULL),
  fpCurrentKeyword(NULL)
{
  // see header file for class documentation
  HLTFatal("copy constructor untested");
}

AliHLTLogging& AliHLTLogging::operator=(const AliHLTLogging&)
{
  // see header file for class documentation
  HLTFatal("assignment operator untested");
  return *this;
}

ostringstream AliHLTLogging::fgLogstr;
AliHLTComponentLogSeverity AliHLTLogging::fgGlobalLogFilter=kHLTLogAll;
AliHLTComponentLogSeverity AliHLTLogging::fgLocalLogDefault=kHLTLogAll;
AliHLTfctLogging AliHLTLogging::fgLoggingFunc=NULL;
AliHLTLogging::AliHLTDynamicMessage AliHLTLogging::fgAliLoggingFunc=NULL;
int AliHLTLogging::fgUseAliLog=1;

TString AliHLTLogging::fgBlackList="";
TString AliHLTLogging::fgWhiteList="";

AliHLTLogging::~AliHLTLogging()
{
  // see header file for class documentation
}

// the array will be grown dynamically, this is just an initial size
TArrayC AliHLTLogging::fgAliHLTLoggingTarget(200);
// the maximum size of the array
const int AliHLTLogging::fgkALIHLTLOGGINGMAXBUFFERSIZE=10000;

int AliHLTLogging::Init(AliHLTfctLogging pFun)
{
  // see header file for class documentation
  if (fgLoggingFunc!=NULL && fgLoggingFunc!=pFun) {
    (*fgLoggingFunc)(NULL/*fParam*/, kHLTLogWarning, "AliHLTLogging::Init", "no key", "overriding previously initialized logging function");
  }
  fgLoggingFunc=pFun;

  return 0;
}

int AliHLTLogging::InitAliLogTrap(AliHLTComponentHandler* pHandler)
{
  // see header file for class documentation
  // init the AliRoot logging trap
  // AliLog messages are redirected to PubSub,
  int iResult=0;
  if (pHandler) {
    // set temporary loglevel of component handler
    AliHLTComponentLogSeverity loglevel=pHandler->GetLocalLoggingLevel();
    pHandler->SetLocalLoggingLevel(kHLTLogError);

    // load library containing AliRoot dependencies and initialization handler
    pHandler->LoadLibrary(ALILOG_WRAPPER_LIBRARY, 0/* do not activate agents */);

    // restore loglevel
    pHandler->SetLocalLoggingLevel(loglevel);

    // find the symbol
    InitAliDynamicMessageCallback pFunc=(InitAliDynamicMessageCallback)pHandler->FindSymbol(ALILOG_WRAPPER_LIBRARY, "InitAliDynamicMessageCallback");
    if (pFunc) {
      iResult=(*pFunc)();
    } else {
      Message(NULL, kHLTLogError, "AliHLTLogging::InitAliLogTrap", "init logging",
	      "can not initialize AliLog callback");
      iResult=-ENOSYS;
    }
  } else {
    iResult=-EINVAL;
  }

  return iResult;
}

int AliHLTLogging::InitAliLogFunc(AliHLTComponentHandler* pHandler)
{
  // see header file for class documentation
  int iResult=0;
  if (pHandler) {
    // set temporary loglevel of component handler
    AliHLTComponentLogSeverity loglevel=pHandler->GetLocalLoggingLevel();
    pHandler->SetLocalLoggingLevel(kHLTLogError);

    // load library containing AliRoot dependencies and initialization handler
    pHandler->LoadLibrary(ALILOG_WRAPPER_LIBRARY, 0/* do not activate agents */);

    // restore loglevel
    pHandler->SetLocalLoggingLevel(loglevel);

    // find the symbol
    fgAliLoggingFunc=(AliHLTLogging::AliHLTDynamicMessage)pHandler->FindSymbol(ALILOG_WRAPPER_LIBRARY, "AliDynamicMessage");
    if (fgAliLoggingFunc==NULL) {
      Message(NULL, kHLTLogError, "AliHLTLogging::InitAliLogFunc", "init logging",
	      "symbol lookp failure: can not find AliDynamicMessage, switching to HLT logging system");
      iResult=-ENOSYS;
    }
  } else {
    iResult=-EINVAL;
  }

  return iResult;
}

int AliHLTLogging::Message(void *param, AliHLTComponentLogSeverity severity,
			   const char* origin, const char* keyword,
			   const char* message)
{
  // see header file for class documentation
  int iResult=0;
  if (param==NULL) {
    // this is currently just to get rid of the warning "unused parameter"
  }

  const char* strSeverity="";
  switch (severity) {
  case kHLTLogBenchmark:
    strSeverity="benchmark";
    break;
  case kHLTLogDebug:
    strSeverity="debug";
    break;
  case kHLTLogInfo:
    strSeverity="info";
    break;
  case kHLTLogWarning:
    strSeverity="warning";
    break;
  case kHLTLogError:
    strSeverity="error";
    break;
  case kHLTLogFatal:
    strSeverity="fatal";
    break;
  case kHLTLogImportant:
    strSeverity="notify";
    break;
  default:
    break;
  }
  TString out="HLT Log ";
  out+=strSeverity;
  if (origin && origin[0]!=0) {out+=": <"; out+=origin; out+="> ";}
  out+=" "; out+=message;
  if (keyword!=NULL && strcmp(keyword, HLT_DEFAULT_LOG_KEYWORD)!=0) {
    out+=" ("; out+=keyword; out +=")";
  }
  cout << out.Data() << endl;
  return iResult;
}

#if 0
int AliHLTLogging::AliMessage(AliHLTComponentLogSeverity severity,
			      const char* originClass, const char* originFunc,
			      const char* file, int line, const char* message)
{
  // see header file for class documentation

  switch (severity) {
  case kHLTLogBenchmark:
    AliLog::Message(AliLog::kInfo, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogDebug:
    AliLog::Message(AliLog::kDebug, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogInfo:
    AliLog::Message(AliLog::kInfo, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogWarning:
    AliLog::Message(AliLog::kWarning, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogError:
    AliLog::Message(AliLog::kError, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogFatal:
    AliLog::Message(AliLog::kWarning, message, "HLT", originClass, originFunc, file, line);
    break;
  default:
    break;
  }
  return 0;
}
#endif

const char* AliHLTLogging::BuildLogString(const char *format, va_list ap, bool bAppend)
{
  // see header file for class documentation

  int iResult=0;
#ifdef R__VA_COPY
  va_list bap;
  R__VA_COPY(bap, ap);
#endif //R__VA_COPY

  // take the first argument from the list as format string if no
  // format was given
  const char* fmt = format;
  if (fmt==NULL) fmt=va_arg(ap, const char*);

  unsigned int iOffset=0;
  if (bAppend) {
    iOffset=strlen(fgAliHLTLoggingTarget.GetArray());
  } else {
    fgAliHLTLoggingTarget[0]=0;
  }
  while (fmt!=NULL) {
    iResult=vsnprintf(fgAliHLTLoggingTarget.GetArray()+iOffset, fgAliHLTLoggingTarget.GetSize()-iOffset, fmt, ap);
    if (iResult==-1)
      // for compatibility with older version of vsnprintf
      iResult=fgAliHLTLoggingTarget.GetSize()*2;
    else
      iResult+=iOffset;

    if (iResult<fgAliHLTLoggingTarget.GetSize())
      // everything in the limit
      break;

    // terminate if buffer is already at the limit
    if (fgAliHLTLoggingTarget.GetSize()>=fgkALIHLTLOGGINGMAXBUFFERSIZE)
    {
      fgAliHLTLoggingTarget[fgAliHLTLoggingTarget.GetSize()-1]=0;
      break;
    }

    // check limitation and grow the buffer
    if (iResult>fgkALIHLTLOGGINGMAXBUFFERSIZE) iResult=fgkALIHLTLOGGINGMAXBUFFERSIZE;
    fgAliHLTLoggingTarget.Set(iResult+1);

    // copy the original list and skip the first argument if this was the format string
#ifdef R__VA_COPY
    va_end(ap);
    R__VA_COPY(ap, bap);
#else
    fgAliHLTLoggingTarget[fgAliHLTLoggingTarget.GetSize()-1]=0;
    break;
#endif //R__VA_COPY
    if (format==NULL) va_arg(ap, const char*);
  }
#ifdef R__VA_COPY
  va_end(bap);
#endif //R__VA_COPY

  return fgAliHLTLoggingTarget.GetArray();
}

const char* AliHLTLogging::SetLogString(const void* p, const char* pfmt, const char *format, ...)
{
  // see header file for class documentation
  TString formatstr=format;
  TString pstr;
#ifdef __DEBUG
  pstr.Form(pfmt, p);
#endif
  formatstr.ReplaceAll("_pfmt_", pstr);
  va_list args;
  va_start(args, format);

  const char* message=BuildLogString(formatstr.Data(), args);
  va_end(args);

  return message;
}

int AliHLTLogging::Logging(AliHLTComponentLogSeverity severity,
			   const char* origin, const char* keyword,
			   const char* format, ... )
{
  // see header file for class documentation
  int iResult=CheckFilter(severity);
  if (iResult>0) {
    va_list args;
    va_start(args, format);
    if (fgLoggingFunc) {
      iResult = (*fgLoggingFunc)(NULL/*fParam*/, severity, origin, keyword, AliHLTLogging::BuildLogString(format, args ));
    } else {
      if (fgUseAliLog!=0 && fgAliLoggingFunc!=NULL)
	iResult=(*fgAliLoggingFunc)(severity, NULL, origin, NULL, 0, AliHLTLogging::BuildLogString(format, args ));
      else
        iResult=Message(NULL/*fParam*/, severity, origin, keyword, AliHLTLogging::BuildLogString(format, args ));
    }
    va_end(args);
  }
  return iResult;
}

int AliHLTLogging::LoggingVarargs(AliHLTComponentLogSeverity severity,
				  const char* originClass, const char* originFunc,
				  const char* file, int line,  ... ) const
{
  // see header file for class documentation
  int iResult=0;

  va_list args;
  va_start(args, line);

  iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args ));
  va_end(args);

  return iResult;
}

int AliHLTLogging::SendMessage(AliHLTComponentLogSeverity severity,
			       const char* originClass, const char* originFunc,
			       const char* file, int line,
			       const char* message) const
{
  // see header file for class documentation
  int iResult=0;
  const char* separator="";
  TString origin;
  if (originClass) {
    origin+=originClass;
    separator="::";
  }
  if (originFunc) {
    origin+=separator;
    origin+=originFunc;
  }

  if (fgLoggingFunc) {
    iResult=(*fgLoggingFunc)(NULL/*fParam*/, severity, origin.Data(), GetKeyword(), message);
  } else {
    if (fgUseAliLog!=0 && fgAliLoggingFunc!=NULL)
      iResult=(*fgAliLoggingFunc)(severity, originClass, originFunc, file, line, message);
    else
      iResult=Message(NULL/*fParam*/, severity, origin.Data(), GetKeyword(), message);
  }
  return iResult;
}

int AliHLTLogging::CheckFilter(AliHLTComponentLogSeverity severity) const
{
  // see header file for class documentation

  int iResult=severity==kHLTLogNone || ((severity&fgGlobalLogFilter)>0 && (severity&fLocalLogFilter)>0);
  return iResult;
}

void AliHLTLogging::SetGlobalLoggingLevel(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation

  fgGlobalLogFilter=level;
}

AliHLTComponentLogSeverity AliHLTLogging::GetGlobalLoggingLevel()
{
  // see header file for class documentation

  return fgGlobalLogFilter;
}

void AliHLTLogging::SetLocalLoggingLevel(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation

  fLocalLogFilter=level;
}

AliHLTComponentLogSeverity AliHLTLogging::GetLocalLoggingLevel()
{
  // see header file for class documentation

  return fLocalLogFilter;
}

void AliHLTLogging::SetLocalLoggingDefault(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation
  fgLocalLogDefault=level;
}

int AliHLTLogging::CheckGroup(const char* /*originClass*/) const
{
  // see header file for class documentation

  return 1;
}

int AliHLTLogging::SetBlackList(const char* classnames)
{
  // see header file for class documentation

  if (classnames)
    fgBlackList=classnames;
  return 0;
}

int AliHLTLogging::SetWhiteList(const char* classnames)
{
  // see header file for class documentation

  if (classnames)
    fgWhiteList=classnames;
  return 0;
}
<commit_msg>compilation warning fixed<commit_after>// @(#) $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTLogging.cxx
    @author Matthias Richter, Timm Steinbeck
    @date
    @brief  Implementation of HLT logging primitives.
*/

#if __GNUC__>= 3
using namespace std;
#endif

#include "AliHLTStdIncludes.h"
#include "AliHLTLogging.h"
#include "AliHLTComponentHandler.h"
#include "TString.h"
#include "Varargs.h"
#include <string>
#include <sstream>
#include <iostream>

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTLogging);

AliHLTLogging::AliHLTLogging()
  :
  fLocalLogFilter(fgLocalLogDefault),
  fpDefaultKeyword(NULL),
  fpCurrentKeyword(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTLogging::AliHLTLogging(const AliHLTLogging&)
  :
  fLocalLogFilter(kHLTLogAll),
  fpDefaultKeyword(NULL),
  fpCurrentKeyword(NULL)
{
  // see header file for class documentation
  HLTFatal("copy constructor untested");
}

AliHLTLogging& AliHLTLogging::operator=(const AliHLTLogging&)
{
  // see header file for class documentation
  HLTFatal("assignment operator untested");
  return *this;
}

ostringstream AliHLTLogging::fgLogstr;
AliHLTComponentLogSeverity AliHLTLogging::fgGlobalLogFilter=kHLTLogAll;
AliHLTComponentLogSeverity AliHLTLogging::fgLocalLogDefault=kHLTLogAll;
AliHLTfctLogging AliHLTLogging::fgLoggingFunc=NULL;
AliHLTLogging::AliHLTDynamicMessage AliHLTLogging::fgAliLoggingFunc=NULL;
int AliHLTLogging::fgUseAliLog=1;

TString AliHLTLogging::fgBlackList="";
TString AliHLTLogging::fgWhiteList="";

AliHLTLogging::~AliHLTLogging()
{
  // see header file for class documentation
}

// the array will be grown dynamically, this is just an initial size
TArrayC AliHLTLogging::fgAliHLTLoggingTarget(200);
// the maximum size of the array
const int AliHLTLogging::fgkALIHLTLOGGINGMAXBUFFERSIZE=10000;

int AliHLTLogging::Init(AliHLTfctLogging pFun)
{
  // see header file for class documentation
  if (fgLoggingFunc!=NULL && fgLoggingFunc!=pFun) {
    (*fgLoggingFunc)(NULL/*fParam*/, kHLTLogWarning, "AliHLTLogging::Init", "no key", "overriding previously initialized logging function");
  }
  fgLoggingFunc=pFun;

  return 0;
}

int AliHLTLogging::InitAliLogTrap(AliHLTComponentHandler* pHandler)
{
  // see header file for class documentation
  // init the AliRoot logging trap
  // AliLog messages are redirected to PubSub,
  int iResult=0;
  if (pHandler) {
    // set temporary loglevel of component handler
    AliHLTComponentLogSeverity loglevel=pHandler->GetLocalLoggingLevel();
    pHandler->SetLocalLoggingLevel(kHLTLogError);

    // load library containing AliRoot dependencies and initialization handler
    pHandler->LoadLibrary(ALILOG_WRAPPER_LIBRARY, 0/* do not activate agents */);

    // restore loglevel
    pHandler->SetLocalLoggingLevel(loglevel);

    // find the symbol
    InitAliDynamicMessageCallback pFunc=(InitAliDynamicMessageCallback)pHandler->FindSymbol(ALILOG_WRAPPER_LIBRARY, "InitAliDynamicMessageCallback");
    if (pFunc) {
      iResult=(*pFunc)();
    } else {
      Message(NULL, kHLTLogError, "AliHLTLogging::InitAliLogTrap", "init logging",
	      "can not initialize AliLog callback");
      iResult=-ENOSYS;
    }
  } else {
    iResult=-EINVAL;
  }

  return iResult;
}

int AliHLTLogging::InitAliLogFunc(AliHLTComponentHandler* pHandler)
{
  // see header file for class documentation
  int iResult=0;
  if (pHandler) {
    // set temporary loglevel of component handler
    AliHLTComponentLogSeverity loglevel=pHandler->GetLocalLoggingLevel();
    pHandler->SetLocalLoggingLevel(kHLTLogError);

    // load library containing AliRoot dependencies and initialization handler
    pHandler->LoadLibrary(ALILOG_WRAPPER_LIBRARY, 0/* do not activate agents */);

    // restore loglevel
    pHandler->SetLocalLoggingLevel(loglevel);

    // find the symbol
    fgAliLoggingFunc=(AliHLTLogging::AliHLTDynamicMessage)pHandler->FindSymbol(ALILOG_WRAPPER_LIBRARY, "AliDynamicMessage");
    if (fgAliLoggingFunc==NULL) {
      Message(NULL, kHLTLogError, "AliHLTLogging::InitAliLogFunc", "init logging",
	      "symbol lookp failure: can not find AliDynamicMessage, switching to HLT logging system");
      iResult=-ENOSYS;
    }
  } else {
    iResult=-EINVAL;
  }

  return iResult;
}

int AliHLTLogging::Message(void *param, AliHLTComponentLogSeverity severity,
			   const char* origin, const char* keyword,
			   const char* message)
{
  // see header file for class documentation
  int iResult=0;
  if (param==NULL) {
    // this is currently just to get rid of the warning "unused parameter"
  }

  const char* strSeverity="";
  switch (severity) {
  case kHLTLogBenchmark:
    strSeverity="benchmark";
    break;
  case kHLTLogDebug:
    strSeverity="debug";
    break;
  case kHLTLogInfo:
    strSeverity="info";
    break;
  case kHLTLogWarning:
    strSeverity="warning";
    break;
  case kHLTLogError:
    strSeverity="error";
    break;
  case kHLTLogFatal:
    strSeverity="fatal";
    break;
  case kHLTLogImportant:
    strSeverity="notify";
    break;
  default:
    break;
  }
  TString out="HLT Log ";
  out+=strSeverity;
  if (origin && origin[0]!=0) {out+=": <"; out+=origin; out+="> ";}
  out+=" "; out+=message;
  if (keyword!=NULL && strcmp(keyword, HLT_DEFAULT_LOG_KEYWORD)!=0) {
    out+=" ("; out+=keyword; out +=")";
  }
  cout << out.Data() << endl;
  return iResult;
}

#if 0
int AliHLTLogging::AliMessage(AliHLTComponentLogSeverity severity,
			      const char* originClass, const char* originFunc,
			      const char* file, int line, const char* message)
{
  // see header file for class documentation

  switch (severity) {
  case kHLTLogBenchmark:
    AliLog::Message(AliLog::kInfo, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogDebug:
    AliLog::Message(AliLog::kDebug, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogInfo:
    AliLog::Message(AliLog::kInfo, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogWarning:
    AliLog::Message(AliLog::kWarning, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogError:
    AliLog::Message(AliLog::kError, message, "HLT", originClass, originFunc, file, line);
    break;
  case kHLTLogFatal:
    AliLog::Message(AliLog::kWarning, message, "HLT", originClass, originFunc, file, line);
    break;
  default:
    break;
  }
  return 0;
}
#endif

const char* AliHLTLogging::BuildLogString(const char *format, va_list ap, bool bAppend)
{
  // see header file for class documentation

  int iResult=0;
#ifdef R__VA_COPY
  va_list bap;
  R__VA_COPY(bap, ap);
#endif //R__VA_COPY

  // take the first argument from the list as format string if no
  // format was given
  const char* fmt = format;
  if (fmt==NULL) fmt=va_arg(ap, const char*);

  unsigned int iOffset=0;
  if (bAppend) {
    iOffset=strlen(fgAliHLTLoggingTarget.GetArray());
  } else {
    fgAliHLTLoggingTarget[0]=0;
  }
  while (fmt!=NULL) {
    iResult=vsnprintf(fgAliHLTLoggingTarget.GetArray()+iOffset, fgAliHLTLoggingTarget.GetSize()-iOffset, fmt, ap);
    if (iResult==-1)
      // for compatibility with older version of vsnprintf
      iResult=fgAliHLTLoggingTarget.GetSize()*2;
    else
      iResult+=iOffset;

    if (iResult<fgAliHLTLoggingTarget.GetSize())
      // everything in the limit
      break;

    // terminate if buffer is already at the limit
    if (fgAliHLTLoggingTarget.GetSize()>=fgkALIHLTLOGGINGMAXBUFFERSIZE)
    {
      fgAliHLTLoggingTarget[fgAliHLTLoggingTarget.GetSize()-1]=0;
      break;
    }

    // check limitation and grow the buffer
    if (iResult>fgkALIHLTLOGGINGMAXBUFFERSIZE) iResult=fgkALIHLTLOGGINGMAXBUFFERSIZE;
    fgAliHLTLoggingTarget.Set(iResult+1);

    // copy the original list and skip the first argument if this was the format string
#ifdef R__VA_COPY
    va_end(ap);
    R__VA_COPY(ap, bap);
#else
    fgAliHLTLoggingTarget[fgAliHLTLoggingTarget.GetSize()-1]=0;
    break;
#endif //R__VA_COPY
    if (format==NULL) va_arg(ap, const char*);
  }
#ifdef R__VA_COPY
  va_end(bap);
#endif //R__VA_COPY

  return fgAliHLTLoggingTarget.GetArray();
}

const char* AliHLTLogging::SetLogString(const void* p, const char* pfmt, const char *format, ...)
{
  // see header file for class documentation
  if (!p || !pfmt) return NULL;
  TString formatstr=format;
  TString pstr;
#ifdef __DEBUG
  pstr.Form(pfmt, p);
#endif
  formatstr.ReplaceAll("_pfmt_", pstr);
  va_list args;
  va_start(args, format);

  const char* message=BuildLogString(formatstr.Data(), args);
  va_end(args);

  return message;
}

int AliHLTLogging::Logging(AliHLTComponentLogSeverity severity,
			   const char* origin, const char* keyword,
			   const char* format, ... )
{
  // see header file for class documentation
  int iResult=CheckFilter(severity);
  if (iResult>0) {
    va_list args;
    va_start(args, format);
    if (fgLoggingFunc) {
      iResult = (*fgLoggingFunc)(NULL/*fParam*/, severity, origin, keyword, AliHLTLogging::BuildLogString(format, args ));
    } else {
      if (fgUseAliLog!=0 && fgAliLoggingFunc!=NULL)
	iResult=(*fgAliLoggingFunc)(severity, NULL, origin, NULL, 0, AliHLTLogging::BuildLogString(format, args ));
      else
        iResult=Message(NULL/*fParam*/, severity, origin, keyword, AliHLTLogging::BuildLogString(format, args ));
    }
    va_end(args);
  }
  return iResult;
}

int AliHLTLogging::LoggingVarargs(AliHLTComponentLogSeverity severity,
				  const char* originClass, const char* originFunc,
				  const char* file, int line,  ... ) const
{
  // see header file for class documentation
  int iResult=0;

  va_list args;
  va_start(args, line);

  iResult=SendMessage(severity, originClass, originFunc, file, line, AliHLTLogging::BuildLogString(NULL, args ));
  va_end(args);

  return iResult;
}

int AliHLTLogging::SendMessage(AliHLTComponentLogSeverity severity,
			       const char* originClass, const char* originFunc,
			       const char* file, int line,
			       const char* message) const
{
  // see header file for class documentation
  int iResult=0;
  const char* separator="";
  TString origin;
  if (originClass) {
    origin+=originClass;
    separator="::";
  }
  if (originFunc) {
    origin+=separator;
    origin+=originFunc;
  }

  if (fgLoggingFunc) {
    iResult=(*fgLoggingFunc)(NULL/*fParam*/, severity, origin.Data(), GetKeyword(), message);
  } else {
    if (fgUseAliLog!=0 && fgAliLoggingFunc!=NULL)
      iResult=(*fgAliLoggingFunc)(severity, originClass, originFunc, file, line, message);
    else
      iResult=Message(NULL/*fParam*/, severity, origin.Data(), GetKeyword(), message);
  }
  return iResult;
}

int AliHLTLogging::CheckFilter(AliHLTComponentLogSeverity severity) const
{
  // see header file for class documentation

  int iResult=severity==kHLTLogNone || ((severity&fgGlobalLogFilter)>0 && (severity&fLocalLogFilter)>0);
  return iResult;
}

void AliHLTLogging::SetGlobalLoggingLevel(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation

  fgGlobalLogFilter=level;
}

AliHLTComponentLogSeverity AliHLTLogging::GetGlobalLoggingLevel()
{
  // see header file for class documentation

  return fgGlobalLogFilter;
}

void AliHLTLogging::SetLocalLoggingLevel(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation

  fLocalLogFilter=level;
}

AliHLTComponentLogSeverity AliHLTLogging::GetLocalLoggingLevel()
{
  // see header file for class documentation

  return fLocalLogFilter;
}

void AliHLTLogging::SetLocalLoggingDefault(AliHLTComponentLogSeverity level)
{
  // see header file for class documentation
  fgLocalLogDefault=level;
}

int AliHLTLogging::CheckGroup(const char* /*originClass*/) const
{
  // see header file for class documentation

  return 1;
}

int AliHLTLogging::SetBlackList(const char* classnames)
{
  // see header file for class documentation

  if (classnames)
    fgBlackList=classnames;
  return 0;
}

int AliHLTLogging::SetWhiteList(const char* classnames)
{
  // see header file for class documentation

  if (classnames)
    fgWhiteList=classnames;
  return 0;
}
<|endoftext|>


<commit_before>#include <stingray/toolkit/string_stream.h>
#include <stingray/toolkit/exception.h>
#include <stdio.h>

namespace stingray
{
	template<>
	template<>
	void basic_string_ostream<char>::Insert(bool value)
	{
		if (value)
			write("true", 4);
		else
			write("false", 5);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(unsigned value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%u", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(u8 value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%hu", (unsigned short)value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(int value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%d", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(unsigned short value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%hu", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(short value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%hd", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(unsigned long value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%lu", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(long value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%ld", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(unsigned long long value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%llu", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(long long value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%lld", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(long double value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%Lg", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(double value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%g", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(float value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%g", (double)value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	template<>
	template<>
	void basic_string_ostream<char>::Insert(const void * value)
	{
		char buf[32];
		int r = snprintf(buf, sizeof(buf), "%p", value);
		if (r == -1)
			TOOLKIT_THROW("snprintf failed");
		write(buf, r);
	}

	extern template void string_ostream::Insert(bool);
	extern template void string_ostream::Insert(unsigned char);
	extern template void string_ostream::Insert(short);
	extern template void string_ostream::Insert(unsigned short);
	extern template void string_ostream::Insert(long);
	extern template void string_ostream::Insert(unsigned long);
	extern template void string_ostream::Insert(long long);
	extern template void string_ostream::Insert(unsigned long long);
	extern template void string_ostream::Insert(float);
	extern template void string_ostream::Insert(double);
	extern template void string_ostream::Insert(long double);
	extern template void string_ostream::Insert(const void *);

}
<commit_msg>replace copy-pasted code with macro<commit_after>#include <stingray/toolkit/string_stream.h>
#include <stingray/toolkit/exception.h>
#include <stdio.h>

namespace stingray
{
	template<>
	template<>
	void basic_string_ostream<char>::Insert(bool value)
	{
		if (value)
			write("true", 4);
		else
			write("false", 5);
	}
	extern template void string_ostream::Insert(bool);

#define DECLARE_INSERT(VALUE_TYPE, VALUE_FORMAT, VALUE_FORMAT_TYPE) \
	template<> \
	template<> \
	void basic_string_ostream<char>::Insert(VALUE_TYPE value) \
	{ \
		char buf[32]; \
		int r = snprintf(buf, sizeof(buf), VALUE_FORMAT, static_cast<VALUE_FORMAT_TYPE>(value)); \
		if (r == -1) \
			TOOLKIT_THROW("snprintf failed"); \
		write(buf, r); \
	} \
	extern template void string_ostream::Insert(VALUE_TYPE)

	DECLARE_INSERT(unsigned,			"%u",	unsigned);
	DECLARE_INSERT(u8,					"%hu",	unsigned short);
	DECLARE_INSERT(int,					"%d",	int);
	DECLARE_INSERT(unsigned short,		"%hu",	unsigned short);
	DECLARE_INSERT(short,				"%hd",	short);
	DECLARE_INSERT(unsigned long,		"%lu",	unsigned long);
	DECLARE_INSERT(long,				"%ld",	long);
	DECLARE_INSERT(unsigned long long,	"%llu",	unsigned long long);
	DECLARE_INSERT(long long,			"%lld",	long long);
	DECLARE_INSERT(long double,			"%Lg",	long double);
	DECLARE_INSERT(double,				"%g",	double);
	DECLARE_INSERT(float,				"%g",	double);
	DECLARE_INSERT(const void *,		"%p",	const void *);

}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include "caf/config.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
#include "caf/uri.hpp"

CAF_PUSH_UNUSED_LABEL_WARNING

#include "caf/detail/parser/fsm.hpp"

namespace caf {
namespace detail {
namespace parser {

//   foo://example.com:8042/over/there?name=ferret#nose
//   \_/   \______________/\_________/ \_________/ \__/
//    |           |            |            |        |
// scheme     authority       path        query   fragment
//    |   _____________________|__
//   / \ /                        \.
//   urn:example:animal:ferret:nose

// Unlike our other parsers, the URI parsers only check for validity and
// generate ranges for the subcomponents. URIs can't have linebreaks, so we can
// safely keep track of the position by looking at the column.

template <class State>
void read_uri_percent_encoded(State& ps, std::string& str) {
  uint8_t char_code = 0;
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      str += static_cast<char>(char_code);
  });
  start();
  state(init) {
    transition(read_nibble, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  state(read_nibble) {
    transition(done, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  term_state(done) {
    // nop
  }
  fin();
}

inline bool uri_unprotected_char(char c) {
  return in_whitelist(alphanumeric_chars, c) || in_whitelist("-._~", c);
}

#define read_next_char(next_state, dest)                                       \
  transition(next_state, uri_unprotected_char, dest += ch)                     \
  fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%')

template <class State, class Consumer>
void read_uri_query(State& ps, Consumer&& consumer) {
  // Local variables.
  uri::query_map result;
  std::string key;
  std::string value;
  // Utility functions.
  auto take_str = [&](std::string& str) {
    using std::swap;
    std::string res;
    swap(str, res);
    return res;
  };
  auto push = [&] {
    result.emplace(take_str(key), take_str(value));
  };
  // Call consumer on exit.
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      consumer.query(std::move(result));
  });
  // FSM declaration.
  start();
  // Query may be empty.
  term_state(init) {
    read_next_char(read_key, key)
  }
  state(read_key) {
    read_next_char(read_key, key)
    transition(read_value, '=')
  }
  term_state(read_value, push()) {
    read_next_char(read_value, value)
    transition(init, '&', push())
  }
  fin();
}

template <class State, class Consumer>
void read_uri(State& ps, Consumer&& consumer) {
  // Local variables.
  std::string str;
  uint16_t port = 0;
  // Replaces `str` with a default constructed string to make sure we're never
  // operating on a moved-from string object.
  auto take_str = [&] {
    using std::swap;
    std::string res;
    swap(str, res);
    return res;
  };
  // Allowed character sets.
  auto path_char = [](char c) {
    return uri_unprotected_char(c) || c == '/';
  };
  // Utility setters for avoiding code duplication.
  auto set_path = [&] {
    consumer.path(take_str());
  };
  auto set_host = [&] {
    consumer.host(take_str());
  };
  auto set_userinfo = [&] {
    consumer.userinfo(take_str());
  };
  // Consumer for reading IPv6 addresses.
  struct {
    Consumer& f;
    void value(ipv6_address addr) {
      f.host(addr);
    }
  } ip_consumer{consumer};
  // FSM declaration.
  start();
  state(init) {
    epsilon(read_scheme)
  }
  state(read_scheme) {
    read_next_char(read_scheme, str)
    transition(have_scheme, ':', consumer.scheme(take_str()))
  }
  state(have_scheme) {
    transition(disambiguate_path, '/')
    read_next_char(read_path, str)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
  }
  // This state is terminal, because "file:/" is a valid URI.
  term_state(disambiguate_path, consumer.path("/")) {
    transition(start_authority, '/')
    epsilon(read_path, any_char, str += '/')
  }
  state(start_authority) {
    read_next_char(read_authority, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  state(await_end_of_ipv6) {
    transition(end_of_ipv6_host, ']')
  }
  term_state(end_of_ipv6_host) {
    transition(start_port, ':')
    epsilon(end_of_authority)
  }
  term_state(end_of_host) {
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  term_state(read_authority, set_host()) {
    read_next_char(read_authority, str)
    transition(start_host, '@', set_userinfo())
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_host) {
    read_next_char(read_host, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  term_state(read_host, set_host()) {
    read_next_char(read_host, str)
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_port) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch))
  }
  term_state(read_port, consumer.port(port)) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch),
               pec::integer_overflow)
    epsilon(end_of_authority, "/?#", consumer.port(port))
  }
  term_state(end_of_authority) {
    transition(read_path, '/')
    transition(start_query, '?')
    transition(read_fragment, '#')
  }
  term_state(read_path, set_path()) {
    transition(read_path, path_char, str += ch)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
    transition(start_query, '?', set_path())
    transition(read_fragment, '#', set_path())
  }
  term_state(start_query) {
    fsm_epsilon(read_uri_query(ps, consumer), end_of_query)
  }
  unstable_state(end_of_query) {
    transition(read_fragment, '#')
    epsilon(done)
  }
  term_state(read_fragment, consumer.fragment(take_str())) {
    read_next_char(read_fragment, str)
  }
  term_state(done) {
    // nop
  }
  fin();
}

} // namespace parser
} // namespace detail
} // namespace caf

#include "caf/detail/parser/fsm_undef.hpp"

CAF_POP_WARNINGS
<commit_msg>Fix formatting<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include "caf/config.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
#include "caf/uri.hpp"

CAF_PUSH_UNUSED_LABEL_WARNING

#include "caf/detail/parser/fsm.hpp"

namespace caf {
namespace detail {
namespace parser {

//   foo://example.com:8042/over/there?name=ferret#nose
//   \_/   \______________/\_________/ \_________/ \__/
//    |           |            |            |        |
// scheme     authority       path        query   fragment
//    |   _____________________|__
//   / \ /                        \.
//   urn:example:animal:ferret:nose

// Unlike our other parsers, the URI parsers only check for validity and
// generate ranges for the subcomponents. URIs can't have linebreaks, so we can
// safely keep track of the position by looking at the column.

template <class State>
void read_uri_percent_encoded(State& ps, std::string& str) {
  uint8_t char_code = 0;
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      str += static_cast<char>(char_code);
  });
  // clang-format off
  start();
  state(init) {
    transition(read_nibble, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  state(read_nibble) {
    transition(done, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  term_state(done) {
    // nop
  }
  fin();
  // clang-format on
}

inline bool uri_unprotected_char(char c) {
  return in_whitelist(alphanumeric_chars, c) || in_whitelist("-._~", c);
}

// clang-format off
#define read_next_char(next_state, dest)                                       \
  transition(next_state, uri_unprotected_char, dest += ch)                     \
  fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%')
// clang-format on

template <class State, class Consumer>
void read_uri_query(State& ps, Consumer&& consumer) {
  // Local variables.
  uri::query_map result;
  std::string key;
  std::string value;
  // Utility functions.
  auto take_str = [&](std::string& str) {
    using std::swap;
    std::string res;
    swap(str, res);
    return res;
  };
  auto push = [&] { result.emplace(take_str(key), take_str(value)); };
  // Call consumer on exit.
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      consumer.query(std::move(result));
  });
  // clang-format off
  start();
  // Query may be empty.
  term_state(init) {
    read_next_char(read_key, key)
  }
  state(read_key) {
    read_next_char(read_key, key)
    transition(read_value, '=')
  }
  term_state(read_value, push()) {
    read_next_char(read_value, value)
    transition(init, '&', push())
  }
  fin();
  // clang-format on
}

template <class State, class Consumer>
void read_uri(State& ps, Consumer&& consumer) {
  // Local variables.
  std::string str;
  uint16_t port = 0;
  // Replaces `str` with a default constructed string to make sure we're never
  // operating on a moved-from string object.
  auto take_str = [&] {
    using std::swap;
    std::string res;
    swap(str, res);
    return res;
  };
  // Allowed character sets.
  auto path_char = [](char c) { return uri_unprotected_char(c) || c == '/'; };
  // Utility setters for avoiding code duplication.
  auto set_path = [&] { consumer.path(take_str()); };
  auto set_host = [&] { consumer.host(take_str()); };
  auto set_userinfo = [&] { consumer.userinfo(take_str()); };
  // Consumer for reading IPv6 addresses.
  struct {
    Consumer& f;
    void value(ipv6_address addr) {
      f.host(addr);
    }
  } ip_consumer{consumer};
  // clang-format off
  start();
  state(init) {
    epsilon(read_scheme)
  }
  state(read_scheme) {
    read_next_char(read_scheme, str)
    transition(have_scheme, ':', consumer.scheme(take_str()))
  }
  state(have_scheme) {
    transition(disambiguate_path, '/')
    read_next_char(read_path, str)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
  }
  // This state is terminal, because "file:/" is a valid URI.
  term_state(disambiguate_path, consumer.path("/")) {
    transition(start_authority, '/')
    epsilon(read_path, any_char, str += '/')
  }
  state(start_authority) {
    read_next_char(read_authority, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  state(await_end_of_ipv6) {
    transition(end_of_ipv6_host, ']')
  }
  term_state(end_of_ipv6_host) {
    transition(start_port, ':')
    epsilon(end_of_authority)
  }
  term_state(end_of_host) {
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  term_state(read_authority, set_host()) {
    read_next_char(read_authority, str)
    transition(start_host, '@', set_userinfo())
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_host) {
    read_next_char(read_host, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  term_state(read_host, set_host()) {
    read_next_char(read_host, str)
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_port) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch))
  }
  term_state(read_port, consumer.port(port)) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch),
               pec::integer_overflow)
    epsilon(end_of_authority, "/?#", consumer.port(port))
  }
  term_state(end_of_authority) {
    transition(read_path, '/')
    transition(start_query, '?')
    transition(read_fragment, '#')
  }
  term_state(read_path, set_path()) {
    transition(read_path, path_char, str += ch)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
    transition(start_query, '?', set_path())
    transition(read_fragment, '#', set_path())
  }
  term_state(start_query) {
    fsm_epsilon(read_uri_query(ps, consumer), end_of_query)
  }
  unstable_state(end_of_query) {
    transition(read_fragment, '#')
    epsilon(done)
  }
  term_state(read_fragment, consumer.fragment(take_str())) {
    read_next_char(read_fragment, str)
  }
  term_state(done) {
    // nop
  }
  fin();
  // clang-format on
}

} // namespace parser
} // namespace detail
} // namespace caf

#include "caf/detail/parser/fsm_undef.hpp"

CAF_POP_WARNINGS
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "Light.h"
#include "GraphicsWorld.h"
#include "AttributeMetadata.h"
#include "Placeable.h"
#include "UrhoRenderer.h"
#include "Scene/Scene.h"
#include "Math/MathUtilities.h"
#include "LoggingFunctions.h"

#include <Engine/Scene/Node.h>
#include <Engine/Scene/Scene.h>
#include <Engine/Graphics/Graphics.h>
#include <Engine/Graphics/Light.h>

namespace Tundra
{

Light::Light(Urho3D::Context* context, Scene* scene) :
    IComponent(context, scene),
    INIT_ATTRIBUTE_VALUE(type, "Type", PointLight),
    INIT_ATTRIBUTE_VALUE(diffColor, "Diffuse color", Color::White),
    INIT_ATTRIBUTE_VALUE(specColor, "Specular color", Color::Black),
    INIT_ATTRIBUTE_VALUE(castShadows, "Cast shadows", false),
    INIT_ATTRIBUTE_VALUE(range, "Range", 25),
    INIT_ATTRIBUTE_VALUE(brightness, "Brightness", 1.0f),
    INIT_ATTRIBUTE_VALUE(constAtten, "Constant atten", 0.0f), /**< @todo "Constant attennuation" */
    INIT_ATTRIBUTE_VALUE(linearAtten, "Linear atten", 0.01f), /**< @todo "Linear attennuation" */
    INIT_ATTRIBUTE_VALUE(quadraAtten, "Quadratic atten", 0.01f), /**< @todo "Quadratic attennuation" */
    INIT_ATTRIBUTE_VALUE(innerAngle, "Light inner angle", 30.0f),
    INIT_ATTRIBUTE_VALUE(outerAngle, "Light outer angle", 40.0f)
{
    static AttributeMetadata typeAttrData;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        typeAttrData.enums[PointLight] = "Point";
        typeAttrData.enums[Spotlight] = "Spot";
        typeAttrData.enums[DirectionalLight] = "Directional";
        metadataInitialized = true;
    }
    type.SetMetadata(&typeAttrData);

    ParentEntitySet.Connect(this, &Light::UpdateSignals);
}

Light::~Light()
{
    if (world_.Expired())
    {
        if (light_)
            LogError("Light: World has expired, skipping uninitialization!");
        return;
    }

    DetachLight();

    if (light_)
        light_.Reset();
}

void Light::UpdateSignals()
{
    // If scene is not view-enabled, no further action
    if (!ViewEnabled())
        return;
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    parent->ComponentAdded.Connect(this, &Light::OnComponentStructureChanged);
    parent->ComponentRemoved.Connect(this, &Light::OnComponentStructureChanged);

    if (parent->ParentScene())
        world_ = parent->ParentScene()->Subsystem<GraphicsWorld>();

    // Make sure we attach to the Placeable if exists.
    AttachLight();
}

void Light::OnComponentStructureChanged(IComponent*, AttributeChange::Type)
{
    // No-op if attached to the same placeable already
    if (placeable_ == parentEntity->Component<Placeable>())
        return;

    AttachLight(); // Try to attach if placeable is present, otherwise detach
}

void Light::AttributesChanged()
{
    if (type.ValueChanged())
    {
        int tundraType = type.Get();
        Urho3D::LightType urhoType = Urho3D::LIGHT_DIRECTIONAL;
        if (tundraType == PointLight)
            urhoType = Urho3D::LIGHT_POINT;
        else if (tundraType == Spotlight)
            urhoType = Urho3D::LIGHT_SPOT;
        light_->SetLightType(urhoType);
    }
    if (diffColor.ValueChanged())
        light_->SetColor(diffColor.Get());
    // Specular color value ignored, only use intensity
    if (specColor.ValueChanged())
        light_->SetSpecularIntensity(specColor.Get().ToFloat4().AverageOfElements());
    //if (castShadows.ValueChanged())
    //    light_->SetShadowFadeDistance(0);
    if (range.ValueChanged())
        light_->SetRange(range.Get());
    if (brightness.ValueChanged())
        light_->SetBrightness(brightness.Get());
}

void Light::AttachLight()
{
    if (world_.Expired())
        return;

    // Detach first, in case the original placeable no longer exists
    DetachLight();

    Entity *entity = ParentEntity();
    if (!entity)
        return;

    placeable_ = entity->Component<Placeable>();
    if (!placeable_)
        return;

    Urho3D::Node* placeableNode = placeable_->UrhoSceneNode();
    if (!placeableNode)
    {
        LogError("Can not attach light: placeable does not have an Urho3D scene node");
        return;
    }

    light_ = placeableNode->CreateComponent<Urho3D::Light>();

    int tundraType = type.Get();
    Urho3D::LightType urhoType = Urho3D::LIGHT_DIRECTIONAL;
    if (tundraType == PointLight)
        urhoType = Urho3D::LIGHT_POINT;
    else if (tundraType == Spotlight)
        urhoType = Urho3D::LIGHT_SPOT;
    light_->SetLightType(urhoType);
    light_->SetColor(diffColor.Get());
    light_->SetSpecularIntensity(specColor.Get().ToFloat4().AverageOfElements());
    light_->SetRange(range.Get());
    light_->SetBrightness(brightness.Get());
}

void Light::DetachLight()
{
    if (!light_ || world_.Expired())
        return;

    if (placeable_)
    {
        Urho3D::Node* placeableNode = placeable_->UrhoSceneNode();
        if (!placeableNode)
        {
            LogError("Can not detach light: placeable does not have an Urho3D scene node");
            return;
        }
        placeableNode->RemoveComponent(light_);
        light_.Reset();
        placeable_.Reset();
    }
}

}
<commit_msg>Light: apply castShadow-attribute to Urho3D light.<commit_after>// For conditions of distribution and use, see copyright notice in LICENSE

#include "StableHeaders.h"
#include "Light.h"
#include "GraphicsWorld.h"
#include "AttributeMetadata.h"
#include "Placeable.h"
#include "UrhoRenderer.h"
#include "Scene/Scene.h"
#include "Math/MathUtilities.h"
#include "LoggingFunctions.h"

#include <Engine/Scene/Node.h>
#include <Engine/Scene/Scene.h>
#include <Engine/Graphics/Graphics.h>
#include <Engine/Graphics/Light.h>

namespace Tundra
{

Light::Light(Urho3D::Context* context, Scene* scene) :
    IComponent(context, scene),
    INIT_ATTRIBUTE_VALUE(type, "Type", PointLight),
    INIT_ATTRIBUTE_VALUE(diffColor, "Diffuse color", Color::White),
    INIT_ATTRIBUTE_VALUE(specColor, "Specular color", Color::Black),
    INIT_ATTRIBUTE_VALUE(castShadows, "Cast shadows", false),
    INIT_ATTRIBUTE_VALUE(range, "Range", 25),
    INIT_ATTRIBUTE_VALUE(brightness, "Brightness", 1.0f),
    INIT_ATTRIBUTE_VALUE(constAtten, "Constant atten", 0.0f), /**< @todo "Constant attennuation" */
    INIT_ATTRIBUTE_VALUE(linearAtten, "Linear atten", 0.01f), /**< @todo "Linear attennuation" */
    INIT_ATTRIBUTE_VALUE(quadraAtten, "Quadratic atten", 0.01f), /**< @todo "Quadratic attennuation" */
    INIT_ATTRIBUTE_VALUE(innerAngle, "Light inner angle", 30.0f),
    INIT_ATTRIBUTE_VALUE(outerAngle, "Light outer angle", 40.0f)
{
    static AttributeMetadata typeAttrData;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        typeAttrData.enums[PointLight] = "Point";
        typeAttrData.enums[Spotlight] = "Spot";
        typeAttrData.enums[DirectionalLight] = "Directional";
        metadataInitialized = true;
    }
    type.SetMetadata(&typeAttrData);

    ParentEntitySet.Connect(this, &Light::UpdateSignals);
}

Light::~Light()
{
    if (world_.Expired())
    {
        if (light_)
            LogError("Light: World has expired, skipping uninitialization!");
        return;
    }

    DetachLight();

    if (light_)
        light_.Reset();
}

void Light::UpdateSignals()
{
    // If scene is not view-enabled, no further action
    if (!ViewEnabled())
        return;
    Entity* parent = ParentEntity();
    if (!parent)
        return;

    parent->ComponentAdded.Connect(this, &Light::OnComponentStructureChanged);
    parent->ComponentRemoved.Connect(this, &Light::OnComponentStructureChanged);

    if (parent->ParentScene())
        world_ = parent->ParentScene()->Subsystem<GraphicsWorld>();

    // Make sure we attach to the Placeable if exists.
    AttachLight();
}

void Light::OnComponentStructureChanged(IComponent*, AttributeChange::Type)
{
    // No-op if attached to the same placeable already
    if (placeable_ == parentEntity->Component<Placeable>())
        return;

    AttachLight(); // Try to attach if placeable is present, otherwise detach
}

void Light::AttributesChanged()
{
    if (type.ValueChanged())
    {
        int tundraType = type.Get();
        Urho3D::LightType urhoType = Urho3D::LIGHT_DIRECTIONAL;
        if (tundraType == PointLight)
            urhoType = Urho3D::LIGHT_POINT;
        else if (tundraType == Spotlight)
            urhoType = Urho3D::LIGHT_SPOT;
        light_->SetLightType(urhoType);
    }
    if (diffColor.ValueChanged())
        light_->SetColor(diffColor.Get());
    // Specular color value ignored, only use intensity
    if (specColor.ValueChanged())
        light_->SetSpecularIntensity(specColor.Get().ToFloat4().AverageOfElements());
    if (castShadows.ValueChanged())
		light_->SetCastShadows(castShadows.Get());
    if (range.ValueChanged())
        light_->SetRange(range.Get());
    if (brightness.ValueChanged())
        light_->SetBrightness(brightness.Get());
}

void Light::AttachLight()
{
    if (world_.Expired())
        return;

    // Detach first, in case the original placeable no longer exists
    DetachLight();

    Entity *entity = ParentEntity();
    if (!entity)
        return;

    placeable_ = entity->Component<Placeable>();
    if (!placeable_)
        return;

    Urho3D::Node* placeableNode = placeable_->UrhoSceneNode();
    if (!placeableNode)
    {
        LogError("Can not attach light: placeable does not have an Urho3D scene node");
        return;
    }

    light_ = placeableNode->CreateComponent<Urho3D::Light>();

    int tundraType = type.Get();
    Urho3D::LightType urhoType = Urho3D::LIGHT_DIRECTIONAL;
    if (tundraType == PointLight)
        urhoType = Urho3D::LIGHT_POINT;
    else if (tundraType == Spotlight)
        urhoType = Urho3D::LIGHT_SPOT;
    light_->SetLightType(urhoType);
    light_->SetColor(diffColor.Get());
    light_->SetSpecularIntensity(specColor.Get().ToFloat4().AverageOfElements());
	light_->SetCastShadows(castShadows.Get());
    light_->SetRange(range.Get());
    light_->SetBrightness(brightness.Get());
}

void Light::DetachLight()
{
    if (!light_ || world_.Expired())
        return;

    if (placeable_)
    {
        Urho3D::Node* placeableNode = placeable_->UrhoSceneNode();
        if (!placeableNode)
        {
            LogError("Can not detach light: placeable does not have an Urho3D scene node");
            return;
        }
        placeableNode->RemoveComponent(light_);
        light_.Reset();
        placeable_.Reset();
    }
}

}
<|endoftext|>


<commit_before>/*
    MetaContactSelectorWidget

    Copyright (c) 2005 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

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

#include <qcheckbox.h>
#include <qlabel.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qvbox.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qpainter.h>
#include <qlayout.h>

#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#include <kiconloader.h>

#include <kdeversion.h>
#include <kinputdialog.h>
#include <kpushbutton.h>
#include <kactivelabel.h>
#include <kdebug.h>
#include <klistview.h>
#include <klistviewsearchline.h>

#include "kopetelistview.h"
#include "kopetelistviewsearchline.h"
#include "kopetecontactlist.h"
#include "kopetemetacontact.h"
#include "metacontactselectorwidget_base.h"
#include "metacontactselectorwidget.h"

using namespace Kopete::UI::ListView;

namespace Kopete
{
namespace UI
{

class MetaContactSelectorWidgetLVI::Private
{
public:

	Kopete::MetaContact *metaContact;
	ImageComponent *metaContactPhoto;
	ImageComponent *metaContactIcon;
	DisplayNameComponent *nameText;
	TextComponent *extraText;
	BoxComponent *contactIconBox;
	BoxComponent *spacerBox;
	int photoSize;
	int contactIconSize;
};

MetaContactSelectorWidgetLVI::MetaContactSelectorWidgetLVI(Kopete::MetaContact *mc, QListView *parent, QObject *owner, const char *name) : Kopete::UI::ListView::Item(parent, owner, name) , d( new Private() )
{
	d->metaContact = mc;
	d->photoSize = 60;

	connect( d->metaContact, SIGNAL( photoChanged() ),
		SLOT( slotPhotoChanged() ) );
	connect( d->metaContact, SIGNAL( displayNameChanged() ),
		SLOT( slotDisplayNameChanged() ) );
	buildVisualComponents();
}

Kopete::MetaContact* MetaContactSelectorWidgetLVI::metaContact()
{
	return d->metaContact;
}

void MetaContactSelectorWidgetLVI::slotDisplayNameChanged()
{
	if ( d->nameText )
	{
		d->nameText->setText( d->metaContact->displayName() );

		// delay the sort if we can
		if ( ListView::ListView *lv = dynamic_cast<ListView::ListView *>( listView() ) )
			lv->delayedSort();
		else
			listView()->sort();
	}
}

QString MetaContactSelectorWidgetLVI::text ( int /* column */ ) const
{
	return d->metaContact->displayName();
}

void MetaContactSelectorWidgetLVI::slotPhotoChanged()
{
	QPixmap photoPixmap;
	QImage photoImg = d->metaContact->photo();
	if ( !photoImg.isNull() && (photoImg.width() > 0) &&  (photoImg.height() > 0) )
	{
		int photoSize = d->photoSize;

		photoImg = photoImg.smoothScale( photoSize, photoSize, QImage::ScaleMin ) ;

		// draw a 1 pixel black border
		photoPixmap = photoImg;
		QPainter p(&photoPixmap);
		p.setPen(Qt::black);
		p.drawLine(0, 0, photoPixmap.width()-1, 0);
		p.drawLine(0, photoPixmap.height()-1, photoPixmap.width()-1, photoPixmap.height()-1);
		p.drawLine(0, 0, 0, photoPixmap.height()-1);
		p.drawLine(photoPixmap.width()-1, 0, photoPixmap.width()-1, photoPixmap.height()-1);
	}
	else
	{
		// if no photo use the smilie icon
		photoPixmap=SmallIcon(d->metaContact->statusIcon(), d->photoSize);
	}
	d->metaContactPhoto->setPixmap( photoPixmap, false);
}

void MetaContactSelectorWidgetLVI::buildVisualComponents()
{
	// empty...
	while ( component( 0 ) )
		delete component( 0 );

	d->nameText = 0L;
	d->metaContactPhoto = 0L;
	d->extraText = 0L;
	d->contactIconSize = 16;
	d->photoSize = 48;

	Component *hbox = new BoxComponent( this, BoxComponent::Horizontal );
	d->spacerBox = new BoxComponent( hbox, BoxComponent::Horizontal );

	d->contactIconSize = IconSize( KIcon::Small );
	Component *imageBox = new BoxComponent( hbox, BoxComponent::Vertical );
	new VSpacerComponent( imageBox );
	// include borders in size
	d->metaContactPhoto = new ImageComponent( imageBox, d->photoSize + 2 , d->photoSize + 2 );
	new VSpacerComponent( imageBox );
	Component *vbox = new BoxComponent( hbox, BoxComponent::Vertical );
	d->nameText = new DisplayNameComponent( vbox );
	d->extraText = new TextComponent( vbox );

	Component *box = new BoxComponent( vbox, BoxComponent::Horizontal );
	d->contactIconBox = new BoxComponent( box, BoxComponent::Horizontal );

	slotUpdateContactBox();
	slotDisplayNameChanged();
	slotPhotoChanged();
}

void MetaContactSelectorWidgetLVI::slotUpdateContactBox()
{
	QPtrList<Kopete::Contact> contacts = d->metaContact->contacts();
	for(Kopete::Contact *c = contacts.first(); c; c = contacts.next())
	{
		new ContactComponent(d->contactIconBox, c, IconSize( KIcon::Small ));
	}
}

class MetaContactSelectorWidget::Private
{
public:
	MetaContactSelectorWidget_Base *widget;
};

MetaContactSelectorWidget::MetaContactSelectorWidget( QWidget *parent, const char *name )
		: QWidget( parent, name ), d( new Private() )
{
	QBoxLayout *l = new QVBoxLayout(this);
	d->widget = new MetaContactSelectorWidget_Base(this);
	l->addWidget(d->widget);

	connect( d->widget->metaContactListView, SIGNAL( clicked(QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );
	connect( d->widget->metaContactListView, SIGNAL( selectionChanged( QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );
	connect( d->widget->metaContactListView, SIGNAL( spacePressed( QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );

	connect( Kopete::ContactList::self(), SIGNAL( metaContactAdded( MetaContact * ) ), this, SLOT( slotLoadMetaContacts() ) );

	d->widget->kListViewSearchLine->setListView(d->widget->metaContactListView);
	d->widget->metaContactListView->setFullWidth( true );
	d->widget->metaContactListView->header()->hide();
	d->widget->metaContactListView->setColumnWidthMode(0, QListView::Maximum);
	slotLoadMetaContacts();
}

MetaContactSelectorWidget::~MetaContactSelectorWidget()
{
	disconnect( Kopete::ContactList::self(), SIGNAL( metaContactAdded( MetaContact * ) ), this, SLOT( slotLoadMetaContacts() ) );
}

Kopete::MetaContact* MetaContactSelectorWidget::metaContact()
{
	MetaContactSelectorWidgetLVI *item = 0L;
	item = static_cast<MetaContactSelectorWidgetLVI *>( d->widget->metaContactListView->selectedItem() );

	if ( item )
		return item->metaContact();

	return 0L;
}

void MetaContactSelectorWidget::selectMetaContact( Kopete::MetaContact *mc )
{
	// iterate trough list view
	QListViewItemIterator it( d->widget->metaContactListView );
	while( it.current() )
	{
		MetaContactSelectorWidgetLVI *item = (MetaContactSelectorWidgetLVI *) it.current();
		if (!item)
			continue;

		if ( mc == item->metaContact() )
		{
			// select the contact item
			d->widget->metaContactListView->setSelected( item, true );
			d->widget->metaContactListView->ensureItemVisible( item );
		}
		++it;
	}
}

bool MetaContactSelectorWidget::metaContactSelected()
{
	return d->widget->metaContactListView->selectedItem() ? true : false;
}

/**  Read in contacts from addressbook, and select the contact that is for our nick. */
void MetaContactSelectorWidget::slotLoadMetaContacts()
{
	d->widget->metaContactListView->clear();

	QPtrList<Kopete::MetaContact> metaContacts = Kopete::ContactList::self()->metaContacts();
	for( Kopete::MetaContact *mc = metaContacts.first(); mc ; mc = metaContacts.next() )
	{
		if( !mc->isTemporary() && mc != metaContact() )
		{
			new MetaContactSelectorWidgetLVI(mc, d->widget->metaContactListView);
		}
	}

	d->widget->metaContactListView->sort();
}

void MetaContactSelectorWidget::setLabelMessage( const QString &msg )
{
	d->widget->lblHeader->setText(msg);
}

} // namespace UI
} // namespace Kopete

#include "metacontactselectorwidget.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Fix a couple connect() and disconnect() calls.<commit_after>/*
    MetaContactSelectorWidget

    Copyright (c) 2005 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002-2005 by the Kopete developers  <kopete-devel@kde.org>

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

#include <qcheckbox.h>
#include <qlabel.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qvbox.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qpainter.h>
#include <qlayout.h>

#include <kapplication.h>
#include <kconfig.h>
#include <klocale.h>
#include <kiconloader.h>

#include <kdeversion.h>
#include <kinputdialog.h>
#include <kpushbutton.h>
#include <kactivelabel.h>
#include <kdebug.h>
#include <klistview.h>
#include <klistviewsearchline.h>

#include "kopetelistview.h"
#include "kopetelistviewsearchline.h"
#include "kopetecontactlist.h"
#include "kopetemetacontact.h"
#include "metacontactselectorwidget_base.h"
#include "metacontactselectorwidget.h"

using namespace Kopete::UI::ListView;

namespace Kopete
{
namespace UI
{

class MetaContactSelectorWidgetLVI::Private
{
public:

	Kopete::MetaContact *metaContact;
	ImageComponent *metaContactPhoto;
	ImageComponent *metaContactIcon;
	DisplayNameComponent *nameText;
	TextComponent *extraText;
	BoxComponent *contactIconBox;
	BoxComponent *spacerBox;
	int photoSize;
	int contactIconSize;
};

MetaContactSelectorWidgetLVI::MetaContactSelectorWidgetLVI(Kopete::MetaContact *mc, QListView *parent, QObject *owner, const char *name) : Kopete::UI::ListView::Item(parent, owner, name) , d( new Private() )
{
	d->metaContact = mc;
	d->photoSize = 60;

	connect( d->metaContact, SIGNAL( photoChanged() ),
		SLOT( slotPhotoChanged() ) );
	connect( d->metaContact, SIGNAL( displayNameChanged(const QString&, const QString&) ),
		SLOT( slotDisplayNameChanged() ) );
	buildVisualComponents();
}

Kopete::MetaContact* MetaContactSelectorWidgetLVI::metaContact()
{
	return d->metaContact;
}

void MetaContactSelectorWidgetLVI::slotDisplayNameChanged()
{
	if ( d->nameText )
	{
		d->nameText->setText( d->metaContact->displayName() );

		// delay the sort if we can
		if ( ListView::ListView *lv = dynamic_cast<ListView::ListView *>( listView() ) )
			lv->delayedSort();
		else
			listView()->sort();
	}
}

QString MetaContactSelectorWidgetLVI::text ( int /* column */ ) const
{
	return d->metaContact->displayName();
}

void MetaContactSelectorWidgetLVI::slotPhotoChanged()
{
	QPixmap photoPixmap;
	QImage photoImg = d->metaContact->photo();
	if ( !photoImg.isNull() && (photoImg.width() > 0) &&  (photoImg.height() > 0) )
	{
		int photoSize = d->photoSize;

		photoImg = photoImg.smoothScale( photoSize, photoSize, QImage::ScaleMin ) ;

		// draw a 1 pixel black border
		photoPixmap = photoImg;
		QPainter p(&photoPixmap);
		p.setPen(Qt::black);
		p.drawLine(0, 0, photoPixmap.width()-1, 0);
		p.drawLine(0, photoPixmap.height()-1, photoPixmap.width()-1, photoPixmap.height()-1);
		p.drawLine(0, 0, 0, photoPixmap.height()-1);
		p.drawLine(photoPixmap.width()-1, 0, photoPixmap.width()-1, photoPixmap.height()-1);
	}
	else
	{
		// if no photo use the smilie icon
		photoPixmap=SmallIcon(d->metaContact->statusIcon(), d->photoSize);
	}
	d->metaContactPhoto->setPixmap( photoPixmap, false);
}

void MetaContactSelectorWidgetLVI::buildVisualComponents()
{
	// empty...
	while ( component( 0 ) )
		delete component( 0 );

	d->nameText = 0L;
	d->metaContactPhoto = 0L;
	d->extraText = 0L;
	d->contactIconSize = 16;
	d->photoSize = 48;

	Component *hbox = new BoxComponent( this, BoxComponent::Horizontal );
	d->spacerBox = new BoxComponent( hbox, BoxComponent::Horizontal );

	d->contactIconSize = IconSize( KIcon::Small );
	Component *imageBox = new BoxComponent( hbox, BoxComponent::Vertical );
	new VSpacerComponent( imageBox );
	// include borders in size
	d->metaContactPhoto = new ImageComponent( imageBox, d->photoSize + 2 , d->photoSize + 2 );
	new VSpacerComponent( imageBox );
	Component *vbox = new BoxComponent( hbox, BoxComponent::Vertical );
	d->nameText = new DisplayNameComponent( vbox );
	d->extraText = new TextComponent( vbox );

	Component *box = new BoxComponent( vbox, BoxComponent::Horizontal );
	d->contactIconBox = new BoxComponent( box, BoxComponent::Horizontal );

	slotUpdateContactBox();
	slotDisplayNameChanged();
	slotPhotoChanged();
}

void MetaContactSelectorWidgetLVI::slotUpdateContactBox()
{
	QPtrList<Kopete::Contact> contacts = d->metaContact->contacts();
	for(Kopete::Contact *c = contacts.first(); c; c = contacts.next())
	{
		new ContactComponent(d->contactIconBox, c, IconSize( KIcon::Small ));
	}
}

class MetaContactSelectorWidget::Private
{
public:
	MetaContactSelectorWidget_Base *widget;
};

MetaContactSelectorWidget::MetaContactSelectorWidget( QWidget *parent, const char *name )
		: QWidget( parent, name ), d( new Private() )
{
	QBoxLayout *l = new QVBoxLayout(this);
	d->widget = new MetaContactSelectorWidget_Base(this);
	l->addWidget(d->widget);

	connect( d->widget->metaContactListView, SIGNAL( clicked(QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );
	connect( d->widget->metaContactListView, SIGNAL( selectionChanged( QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );
	connect( d->widget->metaContactListView, SIGNAL( spacePressed( QListViewItem * ) ),
			SIGNAL( metaContactListClicked( QListViewItem * ) ) );

	connect( Kopete::ContactList::self(), SIGNAL( metaContactAdded( Kopete::MetaContact * ) ), this, SLOT( slotLoadMetaContacts() ) );

	d->widget->kListViewSearchLine->setListView(d->widget->metaContactListView);
	d->widget->metaContactListView->setFullWidth( true );
	d->widget->metaContactListView->header()->hide();
	d->widget->metaContactListView->setColumnWidthMode(0, QListView::Maximum);
	slotLoadMetaContacts();
}

MetaContactSelectorWidget::~MetaContactSelectorWidget()
{
	disconnect( Kopete::ContactList::self(), SIGNAL( metaContactAdded( Kopete::MetaContact * ) ), this, SLOT( slotLoadMetaContacts() ) );
}

Kopete::MetaContact* MetaContactSelectorWidget::metaContact()
{
	MetaContactSelectorWidgetLVI *item = 0L;
	item = static_cast<MetaContactSelectorWidgetLVI *>( d->widget->metaContactListView->selectedItem() );

	if ( item )
		return item->metaContact();

	return 0L;
}

void MetaContactSelectorWidget::selectMetaContact( Kopete::MetaContact *mc )
{
	// iterate trough list view
	QListViewItemIterator it( d->widget->metaContactListView );
	while( it.current() )
	{
		MetaContactSelectorWidgetLVI *item = (MetaContactSelectorWidgetLVI *) it.current();
		if (!item)
			continue;

		if ( mc == item->metaContact() )
		{
			// select the contact item
			d->widget->metaContactListView->setSelected( item, true );
			d->widget->metaContactListView->ensureItemVisible( item );
		}
		++it;
	}
}

bool MetaContactSelectorWidget::metaContactSelected()
{
	return d->widget->metaContactListView->selectedItem() ? true : false;
}

/**  Read in contacts from addressbook, and select the contact that is for our nick. */
void MetaContactSelectorWidget::slotLoadMetaContacts()
{
	d->widget->metaContactListView->clear();

	QPtrList<Kopete::MetaContact> metaContacts = Kopete::ContactList::self()->metaContacts();
	for( Kopete::MetaContact *mc = metaContacts.first(); mc ; mc = metaContacts.next() )
	{
		if( !mc->isTemporary() && mc != metaContact() )
		{
			new MetaContactSelectorWidgetLVI(mc, d->widget->metaContactListView);
		}
	}

	d->widget->metaContactListView->sort();
}

void MetaContactSelectorWidget::setLabelMessage( const QString &msg )
{
	d->widget->lblHeader->setText(msg);
}

} // namespace UI
} // namespace Kopete

#include "metacontactselectorwidget.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>#include <ATen/ATen.h>
#include <ATen/native/quantized/affine_quantizer.h>
#include <torch/library.h>

#include "../../cpu/roi_align_common.h"

namespace vision {
namespace ops {

namespace {

template <typename T>
void qroi_align_forward_kernel_impl(
    int n_rois,
    const at::Tensor& t_input,
    const float& spatial_scale,
    int channels,
    int height,
    int width,
    int pooled_height,
    int pooled_width,
    int sampling_ratio,
    bool aligned,
    const at::Tensor& t_rois,
    T* output) {
  // Don't delete these otherwise the .data_ptr() data might be undefined
  auto t_input_cont = t_input.contiguous();
  auto t_rois_cont = t_rois.contiguous();

  const T* input = t_input_cont.data_ptr<T>();
  int64_t input_zp = t_input.q_zero_point();
  float input_scale = t_input.q_scale();

  const T* rois = t_rois_cont.data_ptr<T>();
  int64_t rois_zp = t_rois.q_zero_point();
  float rois_scale = t_rois.q_scale();

  for (int n = 0; n < n_rois; n++) {
    int index_n = n * channels * pooled_width * pooled_height;

    const T* offset_rois = rois + n * 5;

    // FIXME: change this when batches of size > 1 are allowed
    const int roi_batch_ind = 0;

    // Do not using rounding; this implementation detail is critical
    float offset = aligned ? 0.5 : 0.;
    float roi_start_w =
        at::native::dequantize_val(rois_scale, rois_zp, offset_rois[1]) *
            spatial_scale -
        offset;
    float roi_start_h =
        at::native::dequantize_val(rois_scale, rois_zp, offset_rois[2]) *
            spatial_scale -
        offset;
    float roi_end_w =
        at::native::dequantize_val(rois_scale, rois_zp, offset_rois[3]) *
            spatial_scale -
        offset;
    float roi_end_h =
        at::native::dequantize_val(rois_scale, rois_zp, offset_rois[4]) *
            spatial_scale -
        offset;

    float roi_width = roi_end_w - roi_start_w;
    float roi_height = roi_end_h - roi_start_h;
    if (!aligned) {
      // Force malformed ROIs to be 1x1
      roi_width = std::max(roi_width, 1.f);
      roi_height = std::max(roi_height, 1.f);
    }

    float bin_size_h = roi_height / pooled_height;
    float bin_size_w = roi_width / pooled_width;

    // We use roi_bin_grid to sample the grid and mimic integral
    int roi_bin_grid_h = (sampling_ratio > 0)
        ? sampling_ratio
        : ceil(roi_height / pooled_height); // e.g., = 2
    int roi_bin_grid_w =
        (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width);

    // We do average (integral) pooling inside a bin
    // When the grid is empty, output zeros.
    const float count =
        std::max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4

    // we want to precalculate indices and weights shared by all chanels,
    // this is the key point of optimization
    std::vector<detail::PreCalc<float>> pre_calc(
        roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height);
    detail::pre_calc_for_bilinear_interpolate(
        height,
        width,
        pooled_height,
        pooled_width,
        roi_start_h,
        roi_start_w,
        bin_size_h,
        bin_size_w,
        roi_bin_grid_h,
        roi_bin_grid_w,
        pre_calc);

    for (int c = 0; c < channels; c++) {
      int index_n_c = index_n + c * pooled_width * pooled_height;
      const T* offset_input =
          input + (roi_batch_ind * channels + c) * height * width;
      int pre_calc_index = 0;

      for (int ph = 0; ph < pooled_height; ph++) {
        for (int pw = 0; pw < pooled_width; pw++) {
          int index = index_n_c + ph * pooled_width + pw;

          float output_val = 0.;
          float sum_w = 0.;
          for (int iy = 0; iy < roi_bin_grid_h; iy++) {
            for (int ix = 0; ix < roi_bin_grid_w; ix++) {
              detail::PreCalc<float> pc = pre_calc[pre_calc_index];

              // Optimization: we use the raw values here and we'll dequantize
              // later
              output_val += pc.w1 * offset_input[pc.pos1].val_ +
                  pc.w2 * offset_input[pc.pos2].val_ +
                  pc.w3 * offset_input[pc.pos3].val_ +
                  pc.w4 * offset_input[pc.pos4].val_;
              sum_w += pc.w1 + pc.w2 + pc.w3 + pc.w4;

              pre_calc_index += 1;
            }
          }
          // Dequantize here
          output_val = input_scale * (output_val - (float)input_zp * sum_w);

          output_val /= count; // Average pooling

          output[index] =
              at::native::quantize_val<T>(input_scale, input_zp, output_val);
        } // for pw
      } // for ph
    } // for c
  } // for n
}

at::Tensor qroi_align_forward_kernel(
    const at::Tensor& input,
    const at::Tensor& rois,
    double spatial_scale,
    int64_t pooled_height,
    int64_t pooled_width,
    int64_t sampling_ratio,
    bool aligned) {
  TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor");
  TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor");
  TORCH_CHECK(rois.size(1) == 5, "rois must have shape as Tensor[K, 5]");
  // The first column of the RoI tensor is an image index, but not all indices
  // are representable depending on the quantization. For example 1, 3, 5...
  // indices can't be represented when qscale is 2. To prevent any bug, we force
  // a batch size of 1 and we ignore the first column
  TORCH_CHECK(
      input.size(0) == 1,
      "Only one image per batch is allowed in roi_align when quantized tensors are passed.");

  at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2};

  at::CheckedFrom c = "qroi_align_forward_kernel";
  at::checkAllSameType(c, {input_t, rois_t});

  auto num_rois = rois.size(0);
  auto channels = input.size(1);
  auto height = input.size(2);
  auto width = input.size(3);

  // FIXME: This is private, API might change:
  // https://github.com/pytorch/pytorch/wiki/Introducing-Quantized-Tensor#quantized-tensor-apis
  at::Tensor output = at::_empty_affine_quantized(
      {num_rois, channels, pooled_height, pooled_width},
      input.options(),
      input.q_scale(),
      input.q_zero_point());

  if (output.numel() == 0)
    return output;

  AT_DISPATCH_QINT_TYPES(input.scalar_type(), "qroi_align_forward_kernel", [&] {
    qroi_align_forward_kernel_impl<scalar_t>(
        num_rois,
        input,
        spatial_scale,
        channels,
        height,
        width,
        pooled_height,
        pooled_width,
        sampling_ratio,
        aligned,
        rois,
        output.data_ptr<scalar_t>());
  });
  return output;
}

} // namespace

TORCH_LIBRARY_IMPL(torchvision, QuantizedCPU, m) {
  m.impl(
      TORCH_SELECTIVE_NAME("torchvision::roi_align"),
      TORCH_FN(qroi_align_forward_kernel));
}

} // namespace ops
} // namespace vision
<commit_msg>[FBcode->GH] Port quantize_val and dequantize_val into torchvision to avoid at::native and android xplat incompatibility (#4311)<commit_after>#include <ATen/ATen.h>
#include <torch/library.h>

#include "../../cpu/roi_align_common.h"

namespace vision {
namespace ops {

namespace {

// BEGIN copy-pasted code from pytorch core
// https://github.com/pytorch/pytorch/blob/master/aten/src/ATen/native/quantized/affine_quantizer_base.cpp
// We're vendoring the quantize_val() and dequantize_val() functions here. The
// reason is that these functions belong in at::native, which is incompatible
// with android xplat support.

// FIXME: Remove this section once we can use at::native for android xplat
// builds, or when quantize_val() and dequantize_val() aren't in at::native

#ifdef USE_FBGEMM
template <typename T>
T quantize_val(double scale, int64_t zero_point, float value) {
  // Internally, fbgemm::Quantize uses std::nearbyint.
  // std::nearbyint results in nearest integer value according to the current
  // rounding mode and the default rounding mode is rounds to even in half-way
  // cases in most popular processor architectures like x86 and ARM. This is
  // typically faster than an alternatives like std::round that rounds half-way
  // cases away from zero, and can be consistent with SIMD implementations for
  // example in x86 using _mm512_cvtps_epi32 or mm512_round_ps with
  // _MM_FROUND_CUR_DIRECTION option that also follow the current rounding mode.
  // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
  int32_t qvalue;
  // NOLINTNEXTLINE(bugprone-signed-char-misuse)
  qvalue = fbgemm::Quantize<typename T::underlying, false /*LEGACY*/>(
      value,
      static_cast<int32_t>(zero_point),
      static_cast<float>(scale),
      /*result_precision=*/CHAR_BIT * sizeof(typename T::underlying));
  return static_cast<T>(qvalue);
}

template <typename T>
inline float dequantize_val(double scale, int64_t zero_point, T value) {
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
  fbgemm::TensorQuantizationParams qparams;
  qparams.scale = static_cast<float>(scale);
  qparams.zero_point = static_cast<int32_t>(zero_point);
  return fbgemm::Dequantize<typename T::underlying>(value.val_, qparams);
}
#else // USE_FBGEMM

#if defined(__ANDROID__) && !defined(__NDK_MAJOR__)
template <class T>
inline float Round(const float x) {
  return ::nearbyintf(x);
}
inline double Round(const double x) {
  return ::nearbyint(x);
}
#else
template <class T>
inline T Round(const T x) {
  return std::nearbyint(x);
}
#endif

template <typename T>
T quantize_val(double scale, int64_t zero_point, float value) {
  // std::nearbyint results in nearest integer value according to the current
  // rounding mode and the default rounding mode is rounds to even in half-way
  // cases in most popular processor architectures like x86 and ARM. This is
  // typically faster than an alternatives like std::round that rounds half-way
  // cases away from zero, and can be consistent with SIMD implementations for
  // example in x86 using _mm512_cvtps_epi32 or mm512_round_ps with
  // _MM_FROUND_CUR_DIRECTION option that also follow the current rounding mode.
  int64_t qvalue;
  constexpr int64_t qmin = std::numeric_limits<typename T::underlying>::min();
  constexpr int64_t qmax = std::numeric_limits<typename T::underlying>::max();
  float inv_scale = 1.0f / static_cast<float>(scale);
  qvalue = static_cast<int64_t>(zero_point + Round(value * inv_scale));
  qvalue = std::max<int64_t>(qvalue, qmin);
  qvalue = std::min<int64_t>(qvalue, qmax);
  return static_cast<T>(qvalue);
}

template <typename T>
float dequantize_val(double scale, int64_t zero_point, T value) {
  // We need to convert the qint8 value to float to ensure the subtraction
  // subexpression returns a float
  return (static_cast<float>(value.val_) - zero_point) * scale;
}
#endif // USE_FBGEMM
// END copy-pasted code from pytorch core

template <typename T>
void qroi_align_forward_kernel_impl(
    int n_rois,
    const at::Tensor& t_input,
    const float& spatial_scale,
    int channels,
    int height,
    int width,
    int pooled_height,
    int pooled_width,
    int sampling_ratio,
    bool aligned,
    const at::Tensor& t_rois,
    T* output) {
  // Don't delete these otherwise the .data_ptr() data might be undefined
  auto t_input_cont = t_input.contiguous();
  auto t_rois_cont = t_rois.contiguous();

  const T* input = t_input_cont.data_ptr<T>();
  int64_t input_zp = t_input.q_zero_point();
  float input_scale = t_input.q_scale();

  const T* rois = t_rois_cont.data_ptr<T>();
  int64_t rois_zp = t_rois.q_zero_point();
  float rois_scale = t_rois.q_scale();

  for (int n = 0; n < n_rois; n++) {
    int index_n = n * channels * pooled_width * pooled_height;

    const T* offset_rois = rois + n * 5;

    // FIXME: change this when batches of size > 1 are allowed
    const int roi_batch_ind = 0;

    // Do not using rounding; this implementation detail is critical
    float offset = aligned ? 0.5 : 0.;
    float roi_start_w =
        dequantize_val(rois_scale, rois_zp, offset_rois[1]) *
            spatial_scale -
        offset;
    float roi_start_h =
        dequantize_val(rois_scale, rois_zp, offset_rois[2]) *
            spatial_scale -
        offset;
    float roi_end_w =
        dequantize_val(rois_scale, rois_zp, offset_rois[3]) *
            spatial_scale -
        offset;
    float roi_end_h =
        dequantize_val(rois_scale, rois_zp, offset_rois[4]) *
            spatial_scale -
        offset;

    float roi_width = roi_end_w - roi_start_w;
    float roi_height = roi_end_h - roi_start_h;
    if (!aligned) {
      // Force malformed ROIs to be 1x1
      roi_width = std::max(roi_width, 1.f);
      roi_height = std::max(roi_height, 1.f);
    }

    float bin_size_h = roi_height / pooled_height;
    float bin_size_w = roi_width / pooled_width;

    // We use roi_bin_grid to sample the grid and mimic integral
    int roi_bin_grid_h = (sampling_ratio > 0)
        ? sampling_ratio
        : ceil(roi_height / pooled_height); // e.g., = 2
    int roi_bin_grid_w =
        (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width);

    // We do average (integral) pooling inside a bin
    // When the grid is empty, output zeros.
    const float count =
        std::max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4

    // we want to precalculate indices and weights shared by all chanels,
    // this is the key point of optimization
    std::vector<detail::PreCalc<float>> pre_calc(
        roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height);
    detail::pre_calc_for_bilinear_interpolate(
        height,
        width,
        pooled_height,
        pooled_width,
        roi_start_h,
        roi_start_w,
        bin_size_h,
        bin_size_w,
        roi_bin_grid_h,
        roi_bin_grid_w,
        pre_calc);

    for (int c = 0; c < channels; c++) {
      int index_n_c = index_n + c * pooled_width * pooled_height;
      const T* offset_input =
          input + (roi_batch_ind * channels + c) * height * width;
      int pre_calc_index = 0;

      for (int ph = 0; ph < pooled_height; ph++) {
        for (int pw = 0; pw < pooled_width; pw++) {
          int index = index_n_c + ph * pooled_width + pw;

          float output_val = 0.;
          float sum_w = 0.;
          for (int iy = 0; iy < roi_bin_grid_h; iy++) {
            for (int ix = 0; ix < roi_bin_grid_w; ix++) {
              detail::PreCalc<float> pc = pre_calc[pre_calc_index];

              // Optimization: we use the raw values here and we'll dequantize
              // later
              output_val += pc.w1 * offset_input[pc.pos1].val_ +
                  pc.w2 * offset_input[pc.pos2].val_ +
                  pc.w3 * offset_input[pc.pos3].val_ +
                  pc.w4 * offset_input[pc.pos4].val_;
              sum_w += pc.w1 + pc.w2 + pc.w3 + pc.w4;

              pre_calc_index += 1;
            }
          }
          // Dequantize here
          output_val = input_scale * (output_val - (float)input_zp * sum_w);

          output_val /= count; // Average pooling

          output[index] = quantize_val<T>(input_scale, input_zp, output_val);
        } // for pw
      } // for ph
    } // for c
  } // for n
}

at::Tensor qroi_align_forward_kernel(
    const at::Tensor& input,
    const at::Tensor& rois,
    double spatial_scale,
    int64_t pooled_height,
    int64_t pooled_width,
    int64_t sampling_ratio,
    bool aligned) {
  TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor");
  TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor");
  TORCH_CHECK(rois.size(1) == 5, "rois must have shape as Tensor[K, 5]");
  // The first column of the RoI tensor is an image index, but not all indices
  // are representable depending on the quantization. For example 1, 3, 5...
  // indices can't be represented when qscale is 2. To prevent any bug, we force
  // a batch size of 1 and we ignore the first column
  TORCH_CHECK(
      input.size(0) == 1,
      "Only one image per batch is allowed in roi_align when quantized tensors are passed.");

  at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2};

  at::CheckedFrom c = "qroi_align_forward_kernel";
  at::checkAllSameType(c, {input_t, rois_t});

  auto num_rois = rois.size(0);
  auto channels = input.size(1);
  auto height = input.size(2);
  auto width = input.size(3);

  // FIXME: This is private, API might change:
  // https://github.com/pytorch/pytorch/wiki/Introducing-Quantized-Tensor#quantized-tensor-apis
  at::Tensor output = at::_empty_affine_quantized(
      {num_rois, channels, pooled_height, pooled_width},
      input.options(),
      input.q_scale(),
      input.q_zero_point());

  if (output.numel() == 0)
    return output;

  AT_DISPATCH_QINT_TYPES(input.scalar_type(), "qroi_align_forward_kernel", [&] {
    qroi_align_forward_kernel_impl<scalar_t>(
        num_rois,
        input,
        spatial_scale,
        channels,
        height,
        width,
        pooled_height,
        pooled_width,
        sampling_ratio,
        aligned,
        rois,
        output.data_ptr<scalar_t>());
  });
  return output;
}

} // namespace

TORCH_LIBRARY_IMPL(torchvision, QuantizedCPU, m) {
  m.impl(
      TORCH_SELECTIVE_NAME("torchvision::roi_align"),
      TORCH_FN(qroi_align_forward_kernel));
}

} // namespace ops
} // namespace vision
<|endoftext|>


<commit_before>include "mc_type.cp"

proc MCD : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backends)
  # NOTE (possibly shared) dictionaries are application-level primitives we supply.
  # FIXME specify what parameters to give? e.g., whether to randomise, and initial allocation.
  global cache : dictionary <string * string> := empty_dictionary

  # Any time we get something from a backend, cache it and forward it to the
  # client.
  backends => update_cache(cache) => client

  # Any time we get something from a client, see if we have a response in our
  # cache, and forward the request to a backend if it isn't.
  client => test_cache_or_pass_on(client, backends)

fun update_cache : (cache : ref dictionary <string * string>, response : type mcd_reply) -> (type mcd_reply)
  # NOTE relying on pass-by-reference of cache
  cache[response.key] := response
  response

fun test_cache_or_pass_on : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backend; request : type mcd_request) -> ()
  if cache[request.key] = None:
    # Work out which backend memcached to forward this request to, and send.
    request => backends[hash(request.key) mod len(backends)]
  else:
    cache[request.key] => client
<commit_msg>fixed parameter name;<commit_after>include "mc_type.cp"

proc MCD : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backends)
  # NOTE (possibly shared) dictionaries are application-level primitives we supply.
  # FIXME specify what parameters to give? e.g., whether to randomise, and initial allocation.
  global cache : dictionary <string * string> := empty_dictionary

  # Any time we get something from a backend, cache it and forward it to the
  # client.
  backends => update_cache(cache) => client

  # Any time we get something from a client, see if we have a response in our
  # cache, and forward the request to a backend if it isn't.
  client => test_cache_or_pass_on(client, backends)

fun update_cache : (cache : ref dictionary <string * string>, response : type mcd_reply) -> (type mcd_reply)
  # NOTE relying on pass-by-reference of cache
  cache[response.key] := response
  response

fun test_cache_or_pass_on : (type mcd_request/type mcd_reply client, [type mcd_request/type mcd_reply] backends; request : type mcd_request) -> ()
  if cache[request.key] = None:
    # Work out which backend memcached to forward this request to, and send.
    request => backends[hash(request.key) mod len(backends)]
  else:
    cache[request.key] => client
<|endoftext|>


<commit_before>#include "TgaImageLoader.hpp"
#include "RawTextureData.hpp"
#include "../File.hpp"
#include "../Exception.hpp"
#include <cstdint>

BEGIN_INANITY_GRAPHICS

ptr<RawTextureData> TgaImageLoader::Load(ptr<File> file)
{
#pragma pack(push, 1)
	struct Header
	{
		uint8_t idLength;
		uint8_t colorMapType;
		uint8_t imageType;
		uint8_t colorMapSpec[5];
		uint16_t xOrigin;
		uint16_t yOrigin;
		uint16_t width;
		uint16_t height;
		uint8_t bitsPerPixel;
		uint8_t imageDesc;
	};
#pragma pack(pop)

	BEGIN_TRY();

	const uint8_t* fileData = (const uint8_t*)file->GetData();
	size_t fileSize = file->GetSize();

	// read header
	if(fileSize < sizeof(Header))
		THROW("Can't read header");
	const Header* header = (const Header*)fileData;

	// check that there is no color map
	if(header->colorMapType != 0)
		THROW("Unsupported color map type");

	// for now we support only uncompressed images
	if(header->imageType != 2)
		THROW("Unsupported image type");

	// check bits per pixel
	if(header->bitsPerPixel != 24)
		THROW("Unsupported bits per pixel value");

	// check size of pixel data
	int width = (int)header->width;
	int height = (int)header->height;
	int pitch = width * (header->bitsPerPixel / 8);
	const uint8_t* pixelData = (const uint8_t*)(header + 1);
	if(fileSize - sizeof(Header) < (size_t)(width * pitch))
		THROW("Wrong size of file");

	// create image data
	ptr<RawTextureData> textureData = NEW(RawTextureData(
		nullptr,
		PixelFormats::uintRGBA32,
		width,
		height,
		0, // depth
		1, // mips
		0 // count
		));

	// read and copy data
	int resultPitch = textureData->GetMipLinePitch(0);
	uint8_t* resultData = (uint8_t*)textureData->GetMipData(0, 0);
	for(int i = 0; i < height; ++i)
		for(int j = 0; j < width; ++j)
		{
			for(int k = 0; k < 3; ++k)
				resultData[i * resultPitch + j * 4 + k] = pixelData[(height - i - 1) * pitch + j * 3 + 2 - k];
			resultData[i * resultPitch + j * 4 + 3] = 255; // alpha
		}

	return textureData;

	END_TRY("Can't load TGA image");
}

END_INANITY_GRAPHICS
<commit_msg>32-bit image support for TGA images<commit_after>#include "TgaImageLoader.hpp"
#include "RawTextureData.hpp"
#include "../File.hpp"
#include "../Exception.hpp"
#include <cstdint>

BEGIN_INANITY_GRAPHICS

ptr<RawTextureData> TgaImageLoader::Load(ptr<File> file)
{
#pragma pack(push, 1)
	struct Header
	{
		uint8_t idLength;
		uint8_t colorMapType;
		uint8_t imageType;
		uint8_t colorMapSpec[5];
		uint16_t xOrigin;
		uint16_t yOrigin;
		uint16_t width;
		uint16_t height;
		uint8_t bitsPerPixel;
		uint8_t imageDesc;
	};
#pragma pack(pop)

	BEGIN_TRY();

	const uint8_t* fileData = (const uint8_t*)file->GetData();
	size_t fileSize = file->GetSize();

	// read header
	if(fileSize < sizeof(Header))
		THROW("Can't read header");
	const Header* header = (const Header*)fileData;

	// check that there is no color map
	if(header->colorMapType != 0)
		THROW("Unsupported color map type");

	// for now we support only uncompressed images
	if(header->imageType != 2)
		THROW("Unsupported image type");

	// check size of pixel data
	int width = (int)header->width;
	int height = (int)header->height;
	int pitch = width * (header->bitsPerPixel / 8);
	const uint8_t* pixelData = (const uint8_t*)(header + 1);
	if(fileSize - sizeof(Header) < (size_t)(width * pitch))
		THROW("Wrong size of file");

	// create image data
	ptr<RawTextureData> textureData = NEW(RawTextureData(
		nullptr,
		PixelFormats::uintRGBA32,
		width,
		height,
		0, // depth
		1, // mips
		0 // count
		));

	// read and copy data
	int resultPitch = textureData->GetMipLinePitch(0);
	uint8_t* resultData = (uint8_t*)textureData->GetMipData(0, 0);

	switch(header->bitsPerPixel)
	{
	case 24:
		for(int i = 0; i < height; ++i)
			for(int j = 0; j < width; ++j)
			{
				for(int k = 0; k < 3; ++k)
					resultData[i * resultPitch + j * 4 + k] = pixelData[(height - i - 1) * pitch + j * 3 + 2 - k];
				resultData[i * resultPitch + j * 4 + 3] = 255; // alpha
			}
		break;
	case 32:
		for(int i = 0; i < height; ++i)
			for(int j = 0; j < width; ++j)
			{
				for(int k = 0; k < 3; ++k)
					resultData[i * resultPitch + j * 4 + k] = pixelData[(height - i - 1) * pitch + j * 4 + 2 - k];
				resultData[i * resultPitch + j * 4 + 3] = pixelData[(height - i - 1) * pitch + j * 4 + 3];
			}
		break;
	default:
		THROW("Unsupported bits per pixel value");
	}

	return textureData;

	END_TRY("Can't load TGA image");
}

END_INANITY_GRAPHICS
<|endoftext|>