<commit_before>// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t
// RUN: %run %t _
// RUN: %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
// RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
// RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
// RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
// RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
// RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
// RUN: %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
// RUN: %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9

// FIXME: run all ubsan tests in 32- and 64-bit modes (?).
// RUN: %clangxx -fsanitize=float-cast-overflow -m32 %s -o %t
// RUN: %run %t _
// RUN: %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
// RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
// RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
// RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
// RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
// RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
// RUN: %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
// RUN: %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9

// This test assumes float and double are IEEE-754 single- and double-precision.

#include <stdint.h>
#include <stdio.h>
#include <string.h>

float Inf;
float NaN;

int main(int argc, char **argv) {
  float MaxFloatRepresentableAsInt = 0x7fffff80;
  (int)MaxFloatRepresentableAsInt; // ok
  (int)-MaxFloatRepresentableAsInt; // ok

  float MinFloatRepresentableAsInt = -0x7fffffff - 1;
  (int)MinFloatRepresentableAsInt; // ok

  float MaxFloatRepresentableAsUInt = 0xffffff00u;
  (unsigned int)MaxFloatRepresentableAsUInt; // ok

#ifdef __SIZEOF_INT128__
  unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);
  (void)(float)FloatMaxAsUInt128; // ok
#endif

  float NearlyMinusOne = -0.99999;
  unsigned Zero = NearlyMinusOne; // ok

  // Build a '+Inf'.
  char InfVal[] = { 0x00, 0x00, 0x80, 0x7f };
  float Inf;
  memcpy(&Inf, InfVal, 4);

  // Build a 'NaN'.
  char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f };
  float NaN;
  memcpy(&NaN, NaNVal, 4);

  double DblInf = (double)Inf; // ok

  switch (argv[1][0]) {
    // FIXME: Produce a source location for these checks and test for it here.

    // Floating point -> integer overflow.
  case '0':
    // Note that values between 0x7ffffe00 and 0x80000000 may or may not
    // successfully round-trip, depending on the rounding mode.
    // CHECK-0: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int'
    return MaxFloatRepresentableAsInt + 0x80;
  case '1':
    // CHECK-1: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int'
    return MinFloatRepresentableAsInt - 0x100;
  case '2':
    // CHECK-2: runtime error: value -1 is outside the range of representable values of type 'unsigned int'
    return (unsigned)-1.0;
  case '3':
    // CHECK-3: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'
    return (unsigned)(MaxFloatRepresentableAsUInt + 0x100);

  case '4':
    // CHECK-4: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    return Inf;
  case '5':
    // CHECK-5: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    return NaN;

    // Integer -> floating point overflow.
  case '6':
    // CHECK-6: {{runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'|__int128 not supported}}
#ifdef __SIZEOF_INT128__
    return (float)(FloatMaxAsUInt128 + 1);
#else
    puts("__int128 not supported");
    return 0;
#endif
  // FIXME: The backend cannot lower __fp16 operations on x86 yet.
  //case '7':
  //  (__fp16)65504; // ok
  //  // CHECK-7: runtime error: value 65505 is outside the range of representable values of type '__fp16'
  //  return (__fp16)65505;

    // Floating point -> floating point overflow.
  case '8':
    // CHECK-8: runtime error: value 1e+39 is outside the range of representable values of type 'float'
    return (float)1e39;
  case '9':
    volatile long double ld = 300.0;
    // CHECK-9: runtime error: value 300 is outside the range of representable values of type 'char'
    char c = ld;
    return c;
  }
}
<commit_msg>[ubsan] temporary disable testing with -m32 as there are bots that don't support it<commit_after>// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t
// RUN: %run %t _
// RUN: %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
// RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
// RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
// RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
// RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
// RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
// RUN: %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
// RUN: %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9

// FIXME: run all ubsan tests in 32- and 64-bit modes (?).
// FIXME: %clangxx -fsanitize=float-cast-overflow -m32 %s -o %t
// FIXME: %run %t _
// FIXME: %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
// FIXME: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
// FIXME: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
// FIXME: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
// FIXME: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
// FIXME: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
// FIXME: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
// FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
// FIXME: %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
// FIXME: %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9

// This test assumes float and double are IEEE-754 single- and double-precision.

#include <stdint.h>
#include <stdio.h>
#include <string.h>

float Inf;
float NaN;

int main(int argc, char **argv) {
  float MaxFloatRepresentableAsInt = 0x7fffff80;
  (int)MaxFloatRepresentableAsInt; // ok
  (int)-MaxFloatRepresentableAsInt; // ok

  float MinFloatRepresentableAsInt = -0x7fffffff - 1;
  (int)MinFloatRepresentableAsInt; // ok

  float MaxFloatRepresentableAsUInt = 0xffffff00u;
  (unsigned int)MaxFloatRepresentableAsUInt; // ok

#ifdef __SIZEOF_INT128__
  unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);
  (void)(float)FloatMaxAsUInt128; // ok
#endif

  float NearlyMinusOne = -0.99999;
  unsigned Zero = NearlyMinusOne; // ok

  // Build a '+Inf'.
  char InfVal[] = { 0x00, 0x00, 0x80, 0x7f };
  float Inf;
  memcpy(&Inf, InfVal, 4);

  // Build a 'NaN'.
  char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f };
  float NaN;
  memcpy(&NaN, NaNVal, 4);

  double DblInf = (double)Inf; // ok

  switch (argv[1][0]) {
    // FIXME: Produce a source location for these checks and test for it here.

    // Floating point -> integer overflow.
  case '0':
    // Note that values between 0x7ffffe00 and 0x80000000 may or may not
    // successfully round-trip, depending on the rounding mode.
    // CHECK-0: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int'
    return MaxFloatRepresentableAsInt + 0x80;
  case '1':
    // CHECK-1: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int'
    return MinFloatRepresentableAsInt - 0x100;
  case '2':
    // CHECK-2: runtime error: value -1 is outside the range of representable values of type 'unsigned int'
    return (unsigned)-1.0;
  case '3':
    // CHECK-3: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'
    return (unsigned)(MaxFloatRepresentableAsUInt + 0x100);

  case '4':
    // CHECK-4: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    return Inf;
  case '5':
    // CHECK-5: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    return NaN;

    // Integer -> floating point overflow.
  case '6':
    // CHECK-6: {{runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'|__int128 not supported}}
#ifdef __SIZEOF_INT128__
    return (float)(FloatMaxAsUInt128 + 1);
#else
    puts("__int128 not supported");
    return 0;
#endif
  // FIXME: The backend cannot lower __fp16 operations on x86 yet.
  //case '7':
  //  (__fp16)65504; // ok
  //  // CHECK-7: runtime error: value 65505 is outside the range of representable values of type '__fp16'
  //  return (__fp16)65505;

    // Floating point -> floating point overflow.
  case '8':
    // CHECK-8: runtime error: value 1e+39 is outside the range of representable values of type 'float'
    return (float)1e39;
  case '9':
    volatile long double ld = 300.0;
    // CHECK-9: runtime error: value 300 is outside the range of representable values of type 'char'
    char c = ld;
    return c;
  }
}
<|endoftext|>


<commit_before>/*
  Name:             kmkey
  Copyright:        Copyright (C) SIL International.
  Documentation:
  Description:
  Create Date:      19 Jun 2007

  Modified Date:    28 Mar 2016
  Authors:          mcdurdin
  Related Files:
  Dependencies:

  Bugs:
  Todo:
  Notes:
  History:          19 Jun 2007 - mcdurdin - I890 - Deadkeys not working correctly in TSF
                    19 Jun 2007 - mcdurdin - I822 - TSF Addin not working
                    07 Sep 2009 - mcdurdin - I2095 - TSF addin is not threadsafe
                    07 Nov 2012 - mcdurdin - I3549 - V9.0 - x64 version of kmtip addin
                    17 Nov 2012 - mcdurdin - I3567 - V9.0 - KeymanProcessOutput and KeymanGetContext return S_OK but are declared as BOOL
                    17 Nov 2012 - mcdurdin - I3568 - V9.0 - Support legacy output by testing for transitory context
                    20 Nov 2012 - mcdurdin - I3581 - V9.0 - KMTip needs to pass activated profile guid through to Keyman32 to switch keyboards
                    20 Nov 2012 - mcdurdin - I3581 - V9.0 - KMTip needs to pass activated profile guid through to Keyman32 to switch keyboards
                    28 Nov 2012 - mcdurdin - I3588 - V9.0 - Use preserved keys in TSF to handle key combinations in Keyman
                    28 Nov 2012 - mcdurdin - I3589 - V9.0 - Handle key state for KeyUp events in TSF
                    28 Nov 2012 - mcdurdin - I3590 - V9.0 - Initialise keystroke sink after we know which keyboard to activate
                    01 Dec 2012 - mcdurdin - I3608 - V9.0 - Shortcut test for VK_PACKET in kmtip
                    01 May 2014 - mcdurdin - I4201 - V9.0 - Shift + Arrows do not select text (only move caret) in Win 8 when Keyman keyboard is active
                    10 Jun 2014 - mcdurdin - I4262 - V9.0 - TSF deadkeys do not function correctly
                    16 Jun 2014 - mcdurdin - I4274 - V9.0 - kmtip does not work if already active before KM starts
                    13 Aug 2014 - mcdurdin - I4375 - V9.0 - Add registry flag deep integration to allow us to disable TIP context
                    13 Aug 2014 - mcdurdin - I4370 - Deadkeys are still not working in Winword TIP mode
                    14 Aug 2014 - mcdurdin - I4378 - V9.0 - Rapid typing in legacy mode breaks Keyman input
                    28 Mar 2016 - mcdurdin - I4933 - Compat issue with Firefox 42 and IE and Keyman 9 TSF
*/

#include "pch.h"
#include "kmtip.h"
#include "editsess.h"
#include "Compiler.h"
#include "registry.h"

struct deadkeyinfo
{
  int pos, val;
};

class CKeymanEditSession : public CEditSessionBase
{
public:
  CKeymanEditSession(ITfContext *pContext, HMODULE hKeyman, WPARAM wParam, LPARAM lParam, BOOL fUpdate, BOOL fPreserved, DWORD dwDeepIntegration) : CEditSessionBase(pContext)   // I3588   // I4375
  {
    _hKeyman = hKeyman;
    _wParam = wParam;
    _lParam = lParam;   // I3589
    _fUpdate = fUpdate;
    _fPreserved = fPreserved;   // I3588
    _dwDeepIntegration = dwDeepIntegration;   // I4375
  }

    // ITfEditSession
    STDMETHODIMP DoEditSession(TfEditCookie ec);

  HRESULT WINAPI KeymanProcessOutput(int n, PWSTR buf, int nbuf);   // I3567
  HRESULT WINAPI KeymanGetContext(int n, PWSTR buf);   // I3567
  HRESULT GetResult() { return _hr; }

private:
  BOOL _fUpdate;
  BOOL _fPreserved;   // I3588
  HRESULT _hr;
  HMODULE _hKeyman;
  WPARAM _wParam;
  LPARAM _lParam;   // I3589
  DWORD _dwDeepIntegration;   // I4375
  TfEditCookie _ec;
};

BOOL CKMTipTextService::_CheckKeymanLoaded() {   // I4274
  HMODULE hKeyman;
  LogEnter();

#ifdef _WIN64
  hKeyman = GetModuleHandle("keyman64.dll");   // I3549
#else
  hKeyman = GetModuleHandle("keyman32.dll");
#endif

  if(hKeyman == NULL) {
    _hKeyman = NULL;
    return FALSE;
  }

  if(hKeyman != _hKeyman) {
    _hKeyman = NULL;

    if(!_LoadKeyman() || !_InitKeyman()) {
      return FALSE;
    }
    TIPNotifyActivate(&guidActiveProfile);
  }

  return TRUE;
}

#define KEYEVENT_EXTRAINFO_KEYMAN 0xF00F0000   // I4370

BOOL CKMTipTextService::_KeymanProcessKeystroke(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL fUpdate, BOOL fPreserved)   // I3588
{
  CKeymanEditSession *pEditSession;
  HRESULT hr = S_OK;
  LogEnter();

  // Don't process Unicode characters injected or ProcessKey events which are generated by Windows
  if(wParam == VK_PACKET || wParam == VK_PROCESSKEY) return FALSE;   // I3608   // I4201

  Log(L"_KeymanProcessKeystroke (%x %x %s %s ex=%x)", wParam, lParam, fUpdate?L"update":L"", fPreserved?L"preserved":L"", GetMessageExtraInfo());   // I4378

  // Don't process keystrokes generated by Keyman (scan code = 0xFF)
  // But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
  // TODO: This is done in multiple places, but we probably only need to do it once
  if ((lParam & 0xFF0000) == 0xFF0000 &&
      wParam != VK_CAPITAL) {
    return FALSE;   // I4378
  }

  if(!_CheckKeymanLoaded()) {   // I4274
    Log(L"_KeymanProcessKeystroke: _CheckKeymanLoaded failed");
    return FALSE;
  }

  // we'll insert a char ourselves in place of this keystroke
  if ((pEditSession = new CKeymanEditSession(pContext, _hKeyman, wParam, lParam, fUpdate, fPreserved, _dwDeepIntegration)) == NULL) {  // I3588   // I3589   // I4375
    hr = E_OUTOFMEMORY;
  } else {
    HRESULT hrSession;
    if ((hr = pContext->RequestEditSession(_tfClientId, pEditSession,
      fUpdate ? TF_ES_SYNC | TF_ES_READWRITE : TF_ES_SYNC | TF_ES_READ, &hrSession)) != S_OK) {
      Log(L"_KeymanProcessKeystroke: RequestEditSession failed with %x (session hr=%x)", hr, hrSession);
      hr = E_FAIL;
    }
    else {
      hr = pEditSession->GetResult();
      // GetResult will return E_FAIL when we don't process the keystroke
      // but this actually isn't a failure (it should return S_FALSE, but
      // that can be work for another day)
    }
    pEditSession->Release();
  }

  return hr == S_OK;
}

//+---------------------------------------------------------------------------
//
// CKeymanEditSession
//
//----------------------------------------------------------------------------

CKeymanEditSession *ExtEditSession = NULL;

extern "C" __declspec(dllexport) HRESULT WINAPI ExtKeymanProcessOutput(int n, WCHAR *buf, int nbuf)   // I3567
{
  LogEnter();
  HRESULT res;
  if(ExtEditSession) res = ExtEditSession->KeymanProcessOutput(n, buf, nbuf);
  else res = E_FAIL;   // I3567
  return res;
}

extern "C" __declspec(dllexport) HRESULT WINAPI ExtKeymanGetContext(int n, PWSTR buf)   // I3567
{
  LogEnter();
  HRESULT res;
  if(ExtEditSession) res = ExtEditSession->KeymanGetContext(n, buf);
  else res = E_FAIL;   // I3567
  return res;
}

typedef BOOL (WINAPI *PTIPACTIVATEFUNC)(BOOL fActivate);
typedef BOOL (WINAPI *PTIPACTIVATEKEYBOARDFUNC)(GUID *profile);   // I3581
typedef HRESULT (WINAPI *PKEYMANPROCESSOUTPUTFUNC)(int n, WCHAR *buf, int nbuf);   // I3567
typedef HRESULT (WINAPI *PKEYMANGETCONTEXTFUNC)(int n, PWSTR buf);   // I3567
typedef BOOL (WINAPI *PTIPPROCESSKEYFUNC)(WPARAM wParam, LPARAM lParam, PKEYMANPROCESSOUTPUTFUNC outfunc,   // I3588   // I3589
                      PKEYMANGETCONTEXTFUNC ctfunc, BOOL Updateable, BOOL Preserved);

STDAPI CKeymanEditSession::DoEditSession(TfEditCookie ec)
{
  LogEnter();

  _ec = ec;
  _hr = S_OK;

  ExtEditSession = this;

  PTIPPROCESSKEYFUNC pTIPProcessKey = (PTIPPROCESSKEYFUNC) GetProcAddress(_hKeyman, "TIPProcessKey");
  if(!pTIPProcessKey)
  {
    DebugLastError(L"GetProcAddress");
    _hr = E_FAIL;
  }
  else
  {
    if (!(*pTIPProcessKey)(_wParam, _lParam, ExtKeymanProcessOutput, ExtKeymanGetContext, _fUpdate, _fPreserved)) {
      SendDebugMessage(L"DoEditSession: TIPProcessKey did not handle the keystroke");
      _hr = E_FAIL; // TODO: use S_FALSE -> this tells _KeymanProcessKeystroke to pass keystroke on
    }
  }
  ExtEditSession = NULL;

  // Call keyman32.processtipkey; this may call "KeymanGetContext(n, buf)";
  // keyman32.processtipkey this will call "KeymanProcessOutput"
  // which will delete n chrs from left of cursor and output a text string
  // beeps, deadkeys, etc. will be managed from within keyman32.dll itself

  // At this point, the text will already have been output
  // callback will have the information necessary
  // to know what is happening -- make sure that pContext is available globally

  // we need a lock to do our work
  // nb: this method is one of the few places where it is legal to use
  // the TF_ES_SYNC flag

  return S_OK;
}

char *debugstr(PWSTR buf);

HRESULT WINAPI CKeymanEditSession::KeymanProcessOutput(int n, WCHAR *buf, int nbuf)   // I3567
{
  LogEnter();

  if(ShouldDebug()) {
    char *p = debugstr(buf);
    SendDebugMessageFormat(L"KeymanProcessOutput: fUpdate = %d, deleting %d, inserting %d '%hs'", _fUpdate, n, nbuf, p);   // I4262
    delete p;
  }

  if(_fUpdate) {
    /* Delete characters left of selection */
    DeleteLeftOfSelection(_ec, _pContext, n);

    /* Add text to screen */

    InsertTextAtSelection(_ec, _pContext, buf, nbuf);   // I4262
  }
  return S_OK;
}

HRESULT WINAPI CKeymanEditSession::KeymanGetContext(int n, PWSTR buf)   // I3567
{
  LogEnter();

  HRESULT hr;
  TF_STATUS tfStatus;

  if(_dwDeepIntegration == DEEPINTEGRATION_DISABLE) {   // I4375
    Log(L"KeymanGetContext: Exit: deep integration disabled by registry (or default)");
    return S_FALSE;
  }

  if(!SUCCEEDED(hr = _pContext->GetStatus(&tfStatus)))   // I3568
  {
    Log(L"KeymanGetContext: Exit -- Failed GetStatus = %x", hr);
    return hr;
  }

  if(tfStatus.dwStaticFlags & TF_SS_TRANSITORY)   // I3568
  {
    Log(L"KeymanGetContext: Exit: Context does not support manipulation.  Using legacy interaction");
    return S_FALSE;
  }

  if(!GetLeftOfSelection(_ec, _pContext, buf, n)) {   // I4933
    return S_FALSE;   // I4933
  }

  return S_OK;
}

BOOL CKMTipTextService::TIPNotifyActivate(GUID *guidProfile)   // I3581   // I4274
{
  LogEnter();

  //_UninitKeystrokeSink();   // I3590
  if(!_InitKeystrokeSink()) {
    SendDebugMessage(L"TIPNotifyActivate: _InitKeystrokeSink failed");
    return FALSE;   // I3590
  }

  if(!_LoadKeyman()) {
    DebugLastError(L"GetModuleHandle(keymanxx.dll)");
    return FALSE;
  }

  PTIPACTIVATEKEYBOARDFUNC pTIPActivateKeyboard = (PTIPACTIVATEKEYBOARDFUNC) GetProcAddress(_hKeyman, "TIPActivateKeyboard");
  if(!pTIPActivateKeyboard) {
    DebugLastError(L"GetProcAddress(TIPActivateKeyboard)");
    return FALSE;
  }
  if(!(*pTIPActivateKeyboard)(guidProfile)) {
    SendDebugMessage(L"TIPNotifyActivate: TIPActivateKeyboard failed");
    return FALSE;
  }

  if (!_InitPreservedKeys()) {
    SendDebugMessage(L"TIPNotifyActivate: _InitPreservedKeys failed");
    return FALSE;
  }
  return TRUE;
}

BOOL CKMTipTextService::_LoadKeyman()   // I3590
{

#ifdef _WIN64
  _hKeyman = GetModuleHandle("keyman64.dll");   // I3549
#else
  _hKeyman = GetModuleHandle("keyman32.dll");
#endif

  return _hKeyman != NULL;
}

BOOL CKMTipTextService::_InitKeyman()   // I3590   // I4274
{
  LogEnter();
  if(_hKeyman == NULL) {
    return FALSE;
  }

  PTIPACTIVATEFUNC pTIPActivate = (PTIPACTIVATEFUNC) GetProcAddress(_hKeyman, "TIPActivateEx");   // I3581
  if(!pTIPActivate) {
    _hKeyman = 0;
    return FALSE;
  }

  if(!(*pTIPActivate)(TRUE)) {
    _hKeyman = 0;
    return FALSE;
  }

  return TRUE;
}

void CKMTipTextService::_UninitKeyman() {
  LogEnter();

  if(_hKeyman != NULL)  {
    PTIPACTIVATEFUNC pTIPActivate = (PTIPACTIVATEFUNC) GetProcAddress(_hKeyman, "TIPActivateEx");   // I3581
    if(pTIPActivate) {
      (*pTIPActivate)(FALSE);
    }
  }
  _hKeyman = NULL;
}
<commit_msg>[Windows] Add extra logging to help diagnose #2143.<commit_after>/*
  Name:             kmkey
  Copyright:        Copyright (C) SIL International.
  Documentation:
  Description:
  Create Date:      19 Jun 2007

  Modified Date:    28 Mar 2016
  Authors:          mcdurdin
  Related Files:
  Dependencies:

  Bugs:
  Todo:
  Notes:
  History:          19 Jun 2007 - mcdurdin - I890 - Deadkeys not working correctly in TSF
                    19 Jun 2007 - mcdurdin - I822 - TSF Addin not working
                    07 Sep 2009 - mcdurdin - I2095 - TSF addin is not threadsafe
                    07 Nov 2012 - mcdurdin - I3549 - V9.0 - x64 version of kmtip addin
                    17 Nov 2012 - mcdurdin - I3567 - V9.0 - KeymanProcessOutput and KeymanGetContext return S_OK but are declared as BOOL
                    17 Nov 2012 - mcdurdin - I3568 - V9.0 - Support legacy output by testing for transitory context
                    20 Nov 2012 - mcdurdin - I3581 - V9.0 - KMTip needs to pass activated profile guid through to Keyman32 to switch keyboards
                    20 Nov 2012 - mcdurdin - I3581 - V9.0 - KMTip needs to pass activated profile guid through to Keyman32 to switch keyboards
                    28 Nov 2012 - mcdurdin - I3588 - V9.0 - Use preserved keys in TSF to handle key combinations in Keyman
                    28 Nov 2012 - mcdurdin - I3589 - V9.0 - Handle key state for KeyUp events in TSF
                    28 Nov 2012 - mcdurdin - I3590 - V9.0 - Initialise keystroke sink after we know which keyboard to activate
                    01 Dec 2012 - mcdurdin - I3608 - V9.0 - Shortcut test for VK_PACKET in kmtip
                    01 May 2014 - mcdurdin - I4201 - V9.0 - Shift + Arrows do not select text (only move caret) in Win 8 when Keyman keyboard is active
                    10 Jun 2014 - mcdurdin - I4262 - V9.0 - TSF deadkeys do not function correctly
                    16 Jun 2014 - mcdurdin - I4274 - V9.0 - kmtip does not work if already active before KM starts
                    13 Aug 2014 - mcdurdin - I4375 - V9.0 - Add registry flag deep integration to allow us to disable TIP context
                    13 Aug 2014 - mcdurdin - I4370 - Deadkeys are still not working in Winword TIP mode
                    14 Aug 2014 - mcdurdin - I4378 - V9.0 - Rapid typing in legacy mode breaks Keyman input
                    28 Mar 2016 - mcdurdin - I4933 - Compat issue with Firefox 42 and IE and Keyman 9 TSF
*/

#include "pch.h"
#include "kmtip.h"
#include "editsess.h"
#include "Compiler.h"
#include "registry.h"

struct deadkeyinfo
{
  int pos, val;
};

class CKeymanEditSession : public CEditSessionBase
{
public:
  CKeymanEditSession(ITfContext *pContext, HMODULE hKeyman, WPARAM wParam, LPARAM lParam, BOOL fUpdate, BOOL fPreserved, DWORD dwDeepIntegration) : CEditSessionBase(pContext)   // I3588   // I4375
  {
    _hKeyman = hKeyman;
    _wParam = wParam;
    _lParam = lParam;   // I3589
    _fUpdate = fUpdate;
    _fPreserved = fPreserved;   // I3588
    _dwDeepIntegration = dwDeepIntegration;   // I4375
  }

  // ITfEditSession
  STDMETHODIMP DoEditSession(TfEditCookie ec);

  HRESULT WINAPI KeymanProcessOutput(int n, PWSTR buf, int nbuf);   // I3567
  HRESULT WINAPI KeymanGetContext(int n, PWSTR buf);   // I3567
  HRESULT GetResult() { return _hr; }

private:
  BOOL _fUpdate;
  BOOL _fPreserved;   // I3588
  HRESULT _hr;
  HMODULE _hKeyman;
  WPARAM _wParam;
  LPARAM _lParam;   // I3589
  DWORD _dwDeepIntegration;   // I4375
  TfEditCookie _ec;
};

BOOL CKMTipTextService::_CheckKeymanLoaded() {   // I4274
  HMODULE hKeyman;
  LogEnter();

#ifdef _WIN64
  hKeyman = GetModuleHandle("keyman64.dll");   // I3549
#else
  hKeyman = GetModuleHandle("keyman32.dll");
#endif

  if (hKeyman == NULL) {
    _hKeyman = NULL;
    return FALSE;
  }

  if (hKeyman != _hKeyman) {
    _hKeyman = NULL;

    if (!_LoadKeyman() || !_InitKeyman()) {
      return FALSE;
    }
    TIPNotifyActivate(&guidActiveProfile);
  }

  return TRUE;
}

#define KEYEVENT_EXTRAINFO_KEYMAN 0xF00F0000   // I4370

BOOL CKMTipTextService::_KeymanProcessKeystroke(ITfContext *pContext, WPARAM wParam, LPARAM lParam, BOOL fUpdate, BOOL fPreserved)   // I3588
{
  CKeymanEditSession *pEditSession;
  HRESULT hr = S_OK;
  LogEnter();

  // Don't process Unicode characters injected or ProcessKey events which are generated by Windows
  if (wParam == VK_PACKET || wParam == VK_PROCESSKEY) return FALSE;   // I3608   // I4201

  Log(L"_KeymanProcessKeystroke (%x %x %s %s ex=%x)", wParam, lParam, fUpdate ? L"update" : L"", fPreserved ? L"preserved" : L"", GetMessageExtraInfo());   // I4378

  // Don't process keystrokes generated by Keyman (scan code = 0xFF)
  // But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
  // TODO: This is done in multiple places, but we probably only need to do it once
  if ((lParam & 0xFF0000) == 0xFF0000 &&
    wParam != VK_CAPITAL) {
    return FALSE;   // I4378
  }

  if (!_CheckKeymanLoaded()) {   // I4274
    Log(L"_KeymanProcessKeystroke: _CheckKeymanLoaded failed");
    return FALSE;
  }

  // we'll insert a char ourselves in place of this keystroke
  if ((pEditSession = new CKeymanEditSession(pContext, _hKeyman, wParam, lParam, fUpdate, fPreserved, _dwDeepIntegration)) == NULL) {  // I3588   // I3589   // I4375
    Log(L"_KeymanProcessKeystroke: new CKeymanEditSession failed, out of memory?");
    hr = E_OUTOFMEMORY;
  }
  else {
    HRESULT hrSession;
    if ((hr = pContext->RequestEditSession(_tfClientId, pEditSession,
      fUpdate ? TF_ES_SYNC | TF_ES_READWRITE : TF_ES_SYNC | TF_ES_READ, &hrSession)) != S_OK) {
      Log(L"_KeymanProcessKeystroke: RequestEditSession failed with %x (session hr=%x)", hr, hrSession);
      hr = E_FAIL;
    }
    else {
      if (hrSession == S_OK) {
        hr = pEditSession->GetResult();
        if (hr != S_OK) {
          Log(L"_KeymanProcessKeystroke: GetResult failed with %x", hr);
        }
        // GetResult will return E_FAIL when we don't process the keystroke
        // but this actually isn't a failure (it should return S_FALSE, but
        // that can be work for another day)
      }
      else {
        Log(L"_KeymanProcessKeystroke: RequestEditSession failed with session failure %x", hrSession);
        hr = E_FAIL;
      }
    }
    pEditSession->Release();
  }

  return hr == S_OK;
}

//+---------------------------------------------------------------------------
//
// CKeymanEditSession
//
//----------------------------------------------------------------------------

CKeymanEditSession *ExtEditSession = NULL;

extern "C" __declspec(dllexport) HRESULT WINAPI ExtKeymanProcessOutput(int n, WCHAR *buf, int nbuf)   // I3567
{
  LogEnter();
  HRESULT res;
  if (ExtEditSession) res = ExtEditSession->KeymanProcessOutput(n, buf, nbuf);
  else res = E_FAIL;   // I3567
  return res;
}

extern "C" __declspec(dllexport) HRESULT WINAPI ExtKeymanGetContext(int n, PWSTR buf)   // I3567
{
  LogEnter();
  HRESULT res;
  if (ExtEditSession) res = ExtEditSession->KeymanGetContext(n, buf);
  else res = E_FAIL;   // I3567
  return res;
}

typedef BOOL(WINAPI *PTIPACTIVATEFUNC)(BOOL fActivate);
typedef BOOL(WINAPI *PTIPACTIVATEKEYBOARDFUNC)(GUID *profile);   // I3581
typedef HRESULT(WINAPI *PKEYMANPROCESSOUTPUTFUNC)(int n, WCHAR *buf, int nbuf);   // I3567
typedef HRESULT(WINAPI *PKEYMANGETCONTEXTFUNC)(int n, PWSTR buf);   // I3567
typedef BOOL(WINAPI *PTIPPROCESSKEYFUNC)(WPARAM wParam, LPARAM lParam, PKEYMANPROCESSOUTPUTFUNC outfunc,   // I3588   // I3589
  PKEYMANGETCONTEXTFUNC ctfunc, BOOL Updateable, BOOL Preserved);

STDAPI CKeymanEditSession::DoEditSession(TfEditCookie ec)
{
  LogEnter();

  _ec = ec;
  _hr = S_OK;

  ExtEditSession = this;

  PTIPPROCESSKEYFUNC pTIPProcessKey = (PTIPPROCESSKEYFUNC)GetProcAddress(_hKeyman, "TIPProcessKey");
  if (!pTIPProcessKey)
  {
    DebugLastError(L"GetProcAddress");
    _hr = E_FAIL;
  }
  else
  {
    if (!(*pTIPProcessKey)(_wParam, _lParam, ExtKeymanProcessOutput, ExtKeymanGetContext, _fUpdate, _fPreserved)) {
      SendDebugMessage(L"DoEditSession: TIPProcessKey did not handle the keystroke");
      _hr = E_FAIL; // TODO: use S_FALSE -> this tells _KeymanProcessKeystroke to pass keystroke on
    }
  }
  ExtEditSession = NULL;

  // Call keyman32.processtipkey; this may call "KeymanGetContext(n, buf)";
  // keyman32.processtipkey this will call "KeymanProcessOutput"
  // which will delete n chrs from left of cursor and output a text string
  // beeps, deadkeys, etc. will be managed from within keyman32.dll itself

  // At this point, the text will already have been output
  // callback will have the information necessary
  // to know what is happening -- make sure that pContext is available globally

  // we need a lock to do our work
  // nb: this method is one of the few places where it is legal to use
  // the TF_ES_SYNC flag

  return S_OK;
}

char *debugstr(PWSTR buf);

HRESULT WINAPI CKeymanEditSession::KeymanProcessOutput(int n, WCHAR *buf, int nbuf)   // I3567
{
  LogEnter();

  if (ShouldDebug()) {
    char *p = debugstr(buf);
    SendDebugMessageFormat(L"KeymanProcessOutput: fUpdate = %d, deleting %d, inserting %d '%hs'", _fUpdate, n, nbuf, p);   // I4262
    delete p;
  }

  if (_fUpdate) {
    /* Delete characters left of selection */
    DeleteLeftOfSelection(_ec, _pContext, n);

    /* Add text to screen */

    InsertTextAtSelection(_ec, _pContext, buf, nbuf);   // I4262
  }
  return S_OK;
}

HRESULT WINAPI CKeymanEditSession::KeymanGetContext(int n, PWSTR buf)   // I3567
{
  LogEnter();

  HRESULT hr;
  TF_STATUS tfStatus;

  if (_dwDeepIntegration == DEEPINTEGRATION_DISABLE) {   // I4375
    Log(L"KeymanGetContext: Exit: deep integration disabled by registry (or default)");
    return S_FALSE;
  }

  if (!SUCCEEDED(hr = _pContext->GetStatus(&tfStatus)))   // I3568
  {
    Log(L"KeymanGetContext: Exit -- Failed GetStatus = %x", hr);
    return hr;
  }

  if (tfStatus.dwStaticFlags & TF_SS_TRANSITORY)   // I3568
  {
    Log(L"KeymanGetContext: Exit: Context does not support manipulation.  Using legacy interaction");
    return S_FALSE;
  }

  if (!GetLeftOfSelection(_ec, _pContext, buf, n)) {   // I4933
    return S_FALSE;   // I4933
  }

  return S_OK;
}

BOOL CKMTipTextService::TIPNotifyActivate(GUID *guidProfile)   // I3581   // I4274
{
  LogEnter();

  //_UninitKeystrokeSink();   // I3590
  if (!_InitKeystrokeSink()) {
    SendDebugMessage(L"TIPNotifyActivate: _InitKeystrokeSink failed");
    return FALSE;   // I3590
  }

  if (!_LoadKeyman()) {
    DebugLastError(L"GetModuleHandle(keymanxx.dll)");
    return FALSE;
  }

  PTIPACTIVATEKEYBOARDFUNC pTIPActivateKeyboard = (PTIPACTIVATEKEYBOARDFUNC)GetProcAddress(_hKeyman, "TIPActivateKeyboard");
  if (!pTIPActivateKeyboard) {
    DebugLastError(L"GetProcAddress(TIPActivateKeyboard)");
    return FALSE;
  }
  if (!(*pTIPActivateKeyboard)(guidProfile)) {
    SendDebugMessage(L"TIPNotifyActivate: TIPActivateKeyboard failed");
    return FALSE;
  }

  if (!_InitPreservedKeys()) {
    SendDebugMessage(L"TIPNotifyActivate: _InitPreservedKeys failed");
    return FALSE;
  }
  return TRUE;
}

BOOL CKMTipTextService::_LoadKeyman()   // I3590
{

#ifdef _WIN64
  _hKeyman = GetModuleHandle("keyman64.dll");   // I3549
#else
  _hKeyman = GetModuleHandle("keyman32.dll");
#endif

  return _hKeyman != NULL;
}

BOOL CKMTipTextService::_InitKeyman()   // I3590   // I4274
{
  LogEnter();
  if (_hKeyman == NULL) {
    return FALSE;
  }

  PTIPACTIVATEFUNC pTIPActivate = (PTIPACTIVATEFUNC)GetProcAddress(_hKeyman, "TIPActivateEx");   // I3581
  if (!pTIPActivate) {
    _hKeyman = 0;
    return FALSE;
  }

  if (!(*pTIPActivate)(TRUE)) {
    _hKeyman = 0;
    return FALSE;
  }

  return TRUE;
}

void CKMTipTextService::_UninitKeyman() {
  LogEnter();

  if (_hKeyman != NULL) {
    PTIPACTIVATEFUNC pTIPActivate = (PTIPACTIVATEFUNC)GetProcAddress(_hKeyman, "TIPActivateEx");   // I3581
    if (pTIPActivate) {
      (*pTIPActivate)(FALSE);
    }
  }
  _hKeyman = NULL;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the test suite of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

#include <QUrl>

//const QString qtest(qTableName( "qtest", __FILE__ )); // FIXME: what's this

//TESTED_FILES=

class tst_QSparqlQuery : public QObject
{
    Q_OBJECT

public:
    tst_QSparqlQuery();
    virtual ~tst_QSparqlQuery();

public slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

private slots:
    void replacement_data();
    void replacement();
    void unbind_and_replace_data();
    void unbind_and_replace();
    void different_datatypes_data();
    void different_datatypes();
};

tst_QSparqlQuery::tst_QSparqlQuery()
{
}

tst_QSparqlQuery::~tst_QSparqlQuery()
{
}

void tst_QSparqlQuery::initTestCase()
{
}

void tst_QSparqlQuery::cleanupTestCase()
{
}

void tst_QSparqlQuery::init()
{
}

void tst_QSparqlQuery::cleanup()
{
}

void tst_QSparqlQuery::replacement_data()
{
    QTest::addColumn<QString>("rawString");
    QTest::addColumn<QStringList>("placeholders");
    QTest::addColumn<QVariantList>("replacements");
    QTest::addColumn<QString>("replacedString");

    QTest::newRow("nothing") <<
        QString("nothing to replace") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOO" << "BAR") <<
        QString("nothing to replace");

    QTest::newRow("simple") <<
        QString("replace ?:foo ?:bar") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOO" << "BAR") <<
        QString("replace \"FOO\" \"BAR\"");

    QTest::newRow("length_changes") <<
        QString("replace ?:foo and ?:bar also") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOOVAL" << "BARVAL") <<
        QString("replace \"FOOVAL\" and \"BARVAL\" also");

    QTest::newRow("quoted") <<
        QString("do not replace '?:foo' or '?:bar'") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOOVAL" << "BARVAL") <<
        QString("do not replace '?:foo' or '?:bar'");

    QTest::newRow("reallife") <<
        QString("insert { _:c a nco:Contact ; "
                "nco:fullname ?:username ; "
                "nco:hasPhoneNumber _:pn . "
                "_:pn a nco:PhoneNumber ; "
                "nco:phoneNumber ?:userphone . }") <<
        (QStringList() << "username" << "userphone") <<
        (QVariantList() << "NAME" << "PHONE") <<
        QString("insert { _:c a nco:Contact ; "
                "nco:fullname \"NAME\" ; "
                "nco:hasPhoneNumber _:pn . "
                "_:pn a nco:PhoneNumber ; "
                "nco:phoneNumber \"PHONE\" . }");

    QTest::newRow("escape_quotes") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << "some\"thing") <<
        QString("the \"some\\\"thing\" goes here");
}

void tst_QSparqlQuery::replacement()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString);

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);

    // convenience accessor for bound values
    QMap<QString, QSparqlBinding> bv = q.boundValues();

    for (int i = 0; i < placeholders.size(); ++i) {
        QCOMPARE(q.boundValue(placeholders[i]), replacements[i]);
        QVERIFY(bv.contains(placeholders[i]));
        QCOMPARE(bv[placeholders[i]].value(), replacements[i]);
    }
    QCOMPARE(bv.size(), placeholders.size());
}

void tst_QSparqlQuery::unbind_and_replace_data()
{
    return replacement_data();
}

void tst_QSparqlQuery::unbind_and_replace()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString, QSparqlQuery::InsertStatement);
    q.unbindValues();

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);
}

void tst_QSparqlQuery::different_datatypes_data()
{
    QTest::addColumn<QString>("rawString");
    QTest::addColumn<QStringList>("placeholders");
    QTest::addColumn<QVariantList>("replacements");
    QTest::addColumn<QString>("replacedString");

    QTest::newRow("int") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << QVariant(64)) <<
        QString("the 64 goes here");

    /*QTest::newRow("double") <<
        QString("the ?:value goes here") <<
        (QStringList() << "?:value") <<
        (QVariantList() << -3.1) <<
        QString("the -3.1 goes here");*/

    QTest::newRow("bool") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << true) <<
        QString("the true goes here");

    QTest::newRow("string") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << "cat") <<
        QString("the \"cat\" goes here");

    QTest::newRow("url") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << QUrl("http://www.test.com")) <<
        QString("the <http://www.test.com> goes here");
}

void tst_QSparqlQuery::different_datatypes()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString, QSparqlQuery::InsertStatement);

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);
}

QTEST_MAIN( tst_QSparqlQuery )
#include "tst_qsparqlquery.moc"
<commit_msg>* Add a test using a placement variable in a query string of the format '$:foo'<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (ivan.frade@nokia.com)
**
** This file is part of the test suite of the QtSparql module (not yet part of the Qt Toolkit).
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at ivan.frade@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QtSparql/QtSparql>

#include <QUrl>

//const QString qtest(qTableName( "qtest", __FILE__ )); // FIXME: what's this

//TESTED_FILES=

class tst_QSparqlQuery : public QObject
{
    Q_OBJECT

public:
    tst_QSparqlQuery();
    virtual ~tst_QSparqlQuery();

public slots:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

private slots:
    void replacement_data();
    void replacement();
    void unbind_and_replace_data();
    void unbind_and_replace();
    void different_datatypes_data();
    void different_datatypes();
};

tst_QSparqlQuery::tst_QSparqlQuery()
{
}

tst_QSparqlQuery::~tst_QSparqlQuery()
{
}

void tst_QSparqlQuery::initTestCase()
{
}

void tst_QSparqlQuery::cleanupTestCase()
{
}

void tst_QSparqlQuery::init()
{
}

void tst_QSparqlQuery::cleanup()
{
}

void tst_QSparqlQuery::replacement_data()
{
    QTest::addColumn<QString>("rawString");
    QTest::addColumn<QStringList>("placeholders");
    QTest::addColumn<QVariantList>("replacements");
    QTest::addColumn<QString>("replacedString");

    QTest::newRow("nothing") <<
        QString("nothing to replace") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOO" << "BAR") <<
        QString("nothing to replace");

    QTest::newRow("simple") <<
        QString("replace ?:foo ?:bar") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOO" << "BAR") <<
        QString("replace \"FOO\" \"BAR\"");

    QTest::newRow("length_changes") <<
        QString("replace ?:foo and ?:bar also") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOOVAL" << "BARVAL") <<
        QString("replace \"FOOVAL\" and \"BARVAL\" also");

    QTest::newRow("quoted") <<
        QString("do not replace '?:foo' or '?:bar'") <<
        (QStringList() << "foo" << "bar") <<
        (QVariantList() << "FOOVAL" << "BARVAL") <<
        QString("do not replace '?:foo' or '?:bar'");

    QTest::newRow("reallife") <<
        QString("insert { _:c a nco:Contact ; "
                "nco:fullname ?:username ; "
                "nco:hasPhoneNumber _:pn . "
                "_:pn a nco:PhoneNumber ; "
                "nco:phoneNumber ?:userphone . }") <<
        (QStringList() << "username" << "userphone") <<
        (QVariantList() << "NAME" << "PHONE") <<
        QString("insert { _:c a nco:Contact ; "
                "nco:fullname \"NAME\" ; "
                "nco:hasPhoneNumber _:pn . "
                "_:pn a nco:PhoneNumber ; "
                "nco:phoneNumber \"PHONE\" . }");

    QTest::newRow("escape_quotes") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << "some\"thing") <<
        QString("the \"some\\\"thing\" goes here");
}

void tst_QSparqlQuery::replacement()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString);

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);

    // convenience accessor for bound values
    QMap<QString, QSparqlBinding> bv = q.boundValues();

    for (int i = 0; i < placeholders.size(); ++i) {
        QCOMPARE(q.boundValue(placeholders[i]), replacements[i]);
        QVERIFY(bv.contains(placeholders[i]));
        QCOMPARE(bv[placeholders[i]].value(), replacements[i]);
    }
    QCOMPARE(bv.size(), placeholders.size());
}

void tst_QSparqlQuery::unbind_and_replace_data()
{
    return replacement_data();
}

void tst_QSparqlQuery::unbind_and_replace()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString, QSparqlQuery::InsertStatement);
    q.unbindValues();

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);
}

void tst_QSparqlQuery::different_datatypes_data()
{
    QTest::addColumn<QString>("rawString");
    QTest::addColumn<QStringList>("placeholders");
    QTest::addColumn<QVariantList>("replacements");
    QTest::addColumn<QString>("replacedString");

    QTest::newRow("int") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << QVariant(64)) <<
        QString("the 64 goes here");

    QTest::newRow("int") <<
        QString("the $:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << QVariant(64)) <<
        QString("the 64 goes here");

    /*QTest::newRow("double") <<
        QString("the ?:value goes here") <<
        (QStringList() << "?:value") <<
        (QVariantList() << -3.1) <<
        QString("the -3.1 goes here");*/

    QTest::newRow("bool") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << true) <<
        QString("the true goes here");

    QTest::newRow("string") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << "cat") <<
        QString("the \"cat\" goes here");

    QTest::newRow("url") <<
        QString("the ?:value goes here") <<
        (QStringList() << "value") <<
        (QVariantList() << QUrl("http://www.test.com")) <<
        QString("the <http://www.test.com> goes here");
}

void tst_QSparqlQuery::different_datatypes()
{
    QFETCH(QString, rawString);
    QFETCH(QStringList, placeholders);
    QFETCH(QVariantList, replacements);
    QFETCH(QString, replacedString);
    QSparqlQuery q(rawString, QSparqlQuery::InsertStatement);

    for (int i = 0; i < placeholders.size(); ++i)
        q.bindValue(placeholders[i], replacements[i]);

    QCOMPARE(q.query(), rawString);
    QCOMPARE(q.preparedQueryText(), replacedString);
}

QTEST_MAIN( tst_QSparqlQuery )
#include "tst_qsparqlquery.moc"
<|endoftext|>


<commit_before>// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/base/platform/time.h"

#if V8_OS_POSIX
#include <sys/time.h>
#endif

#if V8_OS_WIN
#include "src/base/win32-headers.h"
#endif

#include "src/base/platform/elapsed-timer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace v8 {
namespace base {

TEST(TimeDelta, FromAndIn) {
  EXPECT_EQ(TimeDelta::FromDays(2), TimeDelta::FromHours(48));
  EXPECT_EQ(TimeDelta::FromHours(3), TimeDelta::FromMinutes(180));
  EXPECT_EQ(TimeDelta::FromMinutes(2), TimeDelta::FromSeconds(120));
  EXPECT_EQ(TimeDelta::FromSeconds(2), TimeDelta::FromMilliseconds(2000));
  EXPECT_EQ(TimeDelta::FromMilliseconds(2), TimeDelta::FromMicroseconds(2000));
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromDays(13).InDays());
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromHours(13).InHours());
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromMinutes(13).InMinutes());
  EXPECT_EQ(static_cast<int64_t>(13), TimeDelta::FromSeconds(13).InSeconds());
  EXPECT_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
  EXPECT_EQ(static_cast<int64_t>(13),
            TimeDelta::FromMilliseconds(13).InMilliseconds());
  EXPECT_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
  EXPECT_EQ(static_cast<int64_t>(13),
            TimeDelta::FromMicroseconds(13).InMicroseconds());
}

#if V8_OS_MACOSX
TEST(TimeDelta, MachTimespec) {
  TimeDelta null = TimeDelta();
  EXPECT_EQ(null, TimeDelta::FromMachTimespec(null.ToMachTimespec()));
  TimeDelta delta1 = TimeDelta::FromMilliseconds(42);
  EXPECT_EQ(delta1, TimeDelta::FromMachTimespec(delta1.ToMachTimespec()));
  TimeDelta delta2 = TimeDelta::FromDays(42);
  EXPECT_EQ(delta2, TimeDelta::FromMachTimespec(delta2.ToMachTimespec()));
}
#endif

TEST(Time, JsTime) {
  Time t = Time::FromJsTime(700000.3);
  EXPECT_EQ(700000.3, t.ToJsTime());
}

#if V8_OS_POSIX
TEST(Time, Timespec) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromTimespec(null.ToTimespec()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromTimespec(now.ToTimespec()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromTimespec(now_sys.ToTimespec()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromTimespec(unix_epoch.ToTimespec()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromTimespec(max.ToTimespec()));
}

TEST(Time, Timeval) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromTimeval(null.ToTimeval()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromTimeval(now.ToTimeval()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromTimeval(now_sys.ToTimeval()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromTimeval(unix_epoch.ToTimeval()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromTimeval(max.ToTimeval()));
}
#endif

#if V8_OS_WIN
TEST(Time, Filetime) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromFiletime(null.ToFiletime()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromFiletime(now.ToFiletime()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromFiletime(now_sys.ToFiletime()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromFiletime(unix_epoch.ToFiletime()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromFiletime(max.ToFiletime()));
}
#endif

namespace {

template <typename T>
static void ResolutionTest(T (*Now)(), TimeDelta target_granularity) {
  // We're trying to measure that intervals increment in a VERY small amount
  // of time -- according to the specified target granularity. Unfortunately,
  // if we happen to have a context switch in the middle of our test, the
  // context switch could easily exceed our limit. So, we iterate on this
  // several times. As long as we're able to detect the fine-granularity
  // timers at least once, then the test has succeeded.
  static const TimeDelta kExpirationTimeout = TimeDelta::FromSeconds(1);
  ElapsedTimer timer;
  timer.Start();
  TimeDelta delta;
  do {
    T start = Now();
    T now = start;
    // Loop until we can detect that the clock has changed. Non-HighRes timers
    // will increment in chunks, i.e. 15ms. By spinning until we see a clock
    // change, we detect the minimum time between measurements.
    do {
      now = Now();
      delta = now - start;
    } while (now <= start);
    EXPECT_NE(static_cast<int64_t>(0), delta.InMicroseconds());
  } while (delta > target_granularity && !timer.HasExpired(kExpirationTimeout));
  EXPECT_LE(delta, target_granularity);
}

}

TEST(Time, NowResolution) {
  // We assume that Time::Now() has at least 16ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
  ResolutionTest<Time>(&Time::Now, kTargetGranularity);
}

TEST(TimeTicks, NowResolution) {
  // We assume that TimeTicks::Now() has at least 16ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
  ResolutionTest<TimeTicks>(&TimeTicks::Now, kTargetGranularity);
}

TEST(TimeTicks, HighResolutionNowResolution) {
  if (!TimeTicks::IsHighResolutionClockWorking()) return;

  // We assume that TimeTicks::HighResolutionNow() has sub-ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(1);
  ResolutionTest<TimeTicks>(&TimeTicks::HighResolutionNow, kTargetGranularity);
}

TEST(TimeTicks, IsMonotonic) {
  TimeTicks previous_normal_ticks;
  TimeTicks previous_highres_ticks;
  ElapsedTimer timer;
  timer.Start();
  while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) {
    TimeTicks normal_ticks = TimeTicks::Now();
    TimeTicks highres_ticks = TimeTicks::HighResolutionNow();
    EXPECT_GE(normal_ticks, previous_normal_ticks);
    EXPECT_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0);
    EXPECT_GE(highres_ticks, previous_highres_ticks);
    EXPECT_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0);
    previous_normal_ticks = normal_ticks;
    previous_highres_ticks = highres_ticks;
  }
}

}  // namespace base
}  // namespace v8
<commit_msg>Fix Mac build.<commit_after>// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/base/platform/time.h"

#if V8_OS_MACOSX
#include <mach/mach_time.h>
#endif
#if V8_OS_POSIX
#include <sys/time.h>
#endif

#if V8_OS_WIN
#include "src/base/win32-headers.h"
#endif

#include "src/base/platform/elapsed-timer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace v8 {
namespace base {

TEST(TimeDelta, FromAndIn) {
  EXPECT_EQ(TimeDelta::FromDays(2), TimeDelta::FromHours(48));
  EXPECT_EQ(TimeDelta::FromHours(3), TimeDelta::FromMinutes(180));
  EXPECT_EQ(TimeDelta::FromMinutes(2), TimeDelta::FromSeconds(120));
  EXPECT_EQ(TimeDelta::FromSeconds(2), TimeDelta::FromMilliseconds(2000));
  EXPECT_EQ(TimeDelta::FromMilliseconds(2), TimeDelta::FromMicroseconds(2000));
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromDays(13).InDays());
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromHours(13).InHours());
  EXPECT_EQ(static_cast<int>(13), TimeDelta::FromMinutes(13).InMinutes());
  EXPECT_EQ(static_cast<int64_t>(13), TimeDelta::FromSeconds(13).InSeconds());
  EXPECT_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
  EXPECT_EQ(static_cast<int64_t>(13),
            TimeDelta::FromMilliseconds(13).InMilliseconds());
  EXPECT_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
  EXPECT_EQ(static_cast<int64_t>(13),
            TimeDelta::FromMicroseconds(13).InMicroseconds());
}

#if V8_OS_MACOSX
TEST(TimeDelta, MachTimespec) {
  TimeDelta null = TimeDelta();
  EXPECT_EQ(null, TimeDelta::FromMachTimespec(null.ToMachTimespec()));
  TimeDelta delta1 = TimeDelta::FromMilliseconds(42);
  EXPECT_EQ(delta1, TimeDelta::FromMachTimespec(delta1.ToMachTimespec()));
  TimeDelta delta2 = TimeDelta::FromDays(42);
  EXPECT_EQ(delta2, TimeDelta::FromMachTimespec(delta2.ToMachTimespec()));
}
#endif

TEST(Time, JsTime) {
  Time t = Time::FromJsTime(700000.3);
  EXPECT_EQ(700000.3, t.ToJsTime());
}

#if V8_OS_POSIX
TEST(Time, Timespec) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromTimespec(null.ToTimespec()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromTimespec(now.ToTimespec()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromTimespec(now_sys.ToTimespec()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromTimespec(unix_epoch.ToTimespec()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromTimespec(max.ToTimespec()));
}

TEST(Time, Timeval) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromTimeval(null.ToTimeval()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromTimeval(now.ToTimeval()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromTimeval(now_sys.ToTimeval()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromTimeval(unix_epoch.ToTimeval()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromTimeval(max.ToTimeval()));
}
#endif

#if V8_OS_WIN
TEST(Time, Filetime) {
  Time null;
  EXPECT_TRUE(null.IsNull());
  EXPECT_EQ(null, Time::FromFiletime(null.ToFiletime()));
  Time now = Time::Now();
  EXPECT_EQ(now, Time::FromFiletime(now.ToFiletime()));
  Time now_sys = Time::NowFromSystemTime();
  EXPECT_EQ(now_sys, Time::FromFiletime(now_sys.ToFiletime()));
  Time unix_epoch = Time::UnixEpoch();
  EXPECT_EQ(unix_epoch, Time::FromFiletime(unix_epoch.ToFiletime()));
  Time max = Time::Max();
  EXPECT_TRUE(max.IsMax());
  EXPECT_EQ(max, Time::FromFiletime(max.ToFiletime()));
}
#endif

namespace {

template <typename T>
static void ResolutionTest(T (*Now)(), TimeDelta target_granularity) {
  // We're trying to measure that intervals increment in a VERY small amount
  // of time -- according to the specified target granularity. Unfortunately,
  // if we happen to have a context switch in the middle of our test, the
  // context switch could easily exceed our limit. So, we iterate on this
  // several times. As long as we're able to detect the fine-granularity
  // timers at least once, then the test has succeeded.
  static const TimeDelta kExpirationTimeout = TimeDelta::FromSeconds(1);
  ElapsedTimer timer;
  timer.Start();
  TimeDelta delta;
  do {
    T start = Now();
    T now = start;
    // Loop until we can detect that the clock has changed. Non-HighRes timers
    // will increment in chunks, i.e. 15ms. By spinning until we see a clock
    // change, we detect the minimum time between measurements.
    do {
      now = Now();
      delta = now - start;
    } while (now <= start);
    EXPECT_NE(static_cast<int64_t>(0), delta.InMicroseconds());
  } while (delta > target_granularity && !timer.HasExpired(kExpirationTimeout));
  EXPECT_LE(delta, target_granularity);
}

}

TEST(Time, NowResolution) {
  // We assume that Time::Now() has at least 16ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
  ResolutionTest<Time>(&Time::Now, kTargetGranularity);
}

TEST(TimeTicks, NowResolution) {
  // We assume that TimeTicks::Now() has at least 16ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
  ResolutionTest<TimeTicks>(&TimeTicks::Now, kTargetGranularity);
}

TEST(TimeTicks, HighResolutionNowResolution) {
  if (!TimeTicks::IsHighResolutionClockWorking()) return;

  // We assume that TimeTicks::HighResolutionNow() has sub-ms resolution.
  static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(1);
  ResolutionTest<TimeTicks>(&TimeTicks::HighResolutionNow, kTargetGranularity);
}

TEST(TimeTicks, IsMonotonic) {
  TimeTicks previous_normal_ticks;
  TimeTicks previous_highres_ticks;
  ElapsedTimer timer;
  timer.Start();
  while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) {
    TimeTicks normal_ticks = TimeTicks::Now();
    TimeTicks highres_ticks = TimeTicks::HighResolutionNow();
    EXPECT_GE(normal_ticks, previous_normal_ticks);
    EXPECT_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0);
    EXPECT_GE(highres_ticks, previous_highres_ticks);
    EXPECT_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0);
    previous_normal_ticks = normal_ticks;
    previous_highres_ticks = highres_ticks;
  }
}

}  // namespace base
}  // namespace v8
<|endoftext|>


<commit_before>#include "gtest\gtest.h"
#include "TiledFixture.h"

TEST_F(TiledFixture, map_attributes_should_be_parsed)
{

    ASSERT_EQ("1.0", _parsedMap->get_version());
    ASSERT_EQ("1.0.3", _parsedMap->get_tiledVersion());
    ASSERT_EQ(Orientation::ORTOGNAL, _parsedMap->get_orientation());
    ASSERT_EQ(RenderOrder::RIGHT_DOWN, _parsedMap->get_renderOrder());
    ASSERT_EQ(10, _parsedMap->get_width());
    ASSERT_EQ(10, _parsedMap->get_height());
    ASSERT_EQ(32, _parsedMap->get_tileWidth());
    ASSERT_EQ(32, _parsedMap->get_tileHeight());
}

<commit_msg>ADD: Test for map that check objectgroup<commit_after>#include "gtest\gtest.h"
#include "TiledFixture.h"

TEST_F(TiledFixture, map_attributes_should_be_parsed)
{

    ASSERT_EQ("1.0", _parsedMap->get_version());
    ASSERT_EQ("1.0.3", _parsedMap->get_tiledVersion());
    ASSERT_EQ(Orientation::ORTOGNAL, _parsedMap->get_orientation());
    ASSERT_EQ(RenderOrder::RIGHT_DOWN, _parsedMap->get_renderOrder());
    ASSERT_EQ(10, _parsedMap->get_width());
    ASSERT_EQ(10, _parsedMap->get_height());
    ASSERT_EQ(32, _parsedMap->get_tileWidth());
    ASSERT_EQ(32, _parsedMap->get_tileHeight());
}

TEST_F(TiledFixture, map_should_have_TestObject_parsed)
{
    auto group = _parsedMap->getObjectGroup("TestObject");

    ASSERT_EQ(group.get_name(), "TestObject");
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAutoCorrelativeStatistics.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkToolkits.h"

#include "vtkAutoCorrelativeStatistics.h"
#include "vtkStatisticsAlgorithmPrivate.h"

#include "vtkDataObjectCollection.h"
#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"

#include <vtksys/stl/set>
#include <vtksys/ios/sstream>
#include <limits>

vtkStandardNewMacro(vtkAutoCorrelativeStatistics);

// ----------------------------------------------------------------------
vtkAutoCorrelativeStatistics::vtkAutoCorrelativeStatistics()
{
  this->AssessNames->SetNumberOfValues( 1 );
  this->AssessNames->SetValue( 0, "d^2" ); // Squared Mahalanobis distance
}

// ----------------------------------------------------------------------
vtkAutoCorrelativeStatistics::~vtkAutoCorrelativeStatistics()
{
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::PrintSelf( ostream &os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Aggregate( vtkDataObjectCollection* inMetaColl,
                                              vtkMultiBlockDataSet* outMeta )
{
  if ( ! outMeta )
    {
    return;
    }

  // Get hold of the first model (data object) in the collection
  vtkCollectionSimpleIterator it;
  inMetaColl->InitTraversal( it );
  vtkDataObject *inMetaDO = inMetaColl->GetNextDataObject( it );

  // Verify that the first input model is indeed contained in a multiblock data set
  vtkMultiBlockDataSet* inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
  if ( ! inMeta )
    {
    return;
    }

  // Verify that the first primary statistics are indeed contained in a table
  vtkTable* primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab )
    {
    return;
    }

  vtkIdType nRow = primaryTab->GetNumberOfRows();
  if ( ! nRow )
    {
    // No statistics were calculated.
    return;
    }

  // Use this first model to initialize the aggregated one
  vtkTable* aggregatedTab = vtkTable::New();
  aggregatedTab->DeepCopy( primaryTab );

  // Now, loop over all remaining models and update aggregated each time
  while ( ( inMetaDO = inMetaColl->GetNextDataObject( it ) ) )
    {
    // Verify that the current model is indeed contained in a multiblock data set
    inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
    if ( ! inMeta )
      {
      aggregatedTab->Delete();

      return;
      }

    // Verify that the current primary statistics are indeed contained in a table
    primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
    if ( ! primaryTab )
      {
      aggregatedTab->Delete();

      return;
      }

    if ( primaryTab->GetNumberOfRows() != nRow )
      {
      // Models do not match
      aggregatedTab->Delete();

      return;
      }

    // Iterate over all model rows
    for ( int r = 0; r < nRow; ++ r )
      {
      // Verify that variable names match each other
      if ( primaryTab->GetValueByName( r, "Variable" ) != aggregatedTab->GetValueByName( r, "Variable" ) )
        {
        // Models do not match
        aggregatedTab->Delete();

        return;
        }

      // Get aggregated statistics
      int n = aggregatedTab->GetValueByName( r, "Cardinality" ).ToInt();

      // Get current model statistics
      int n_c = primaryTab->GetValueByName( r, "Cardinality" ).ToInt();

      // Update global statics
      int N = n + n_c;

      // Store updated model
      aggregatedTab->SetValueByName( r, "Cardinality", N );
      }
    }

  // Finally set first block of aggregated model to primary statistics table
  outMeta->SetNumberOfBlocks( 1 );
  outMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Primary Statistics" );
  outMeta->SetBlock( 0, aggregatedTab );

  // Clean up
  aggregatedTab->Delete();
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Learn( vtkTable* inData,
                                          vtkTable* vtkNotUsed( inParameters ),
                                          vtkMultiBlockDataSet* outMeta )
{
  if ( ! inData )
    {
    return;
    }

  if ( ! outMeta )
    {
    return;
    }

  // The primary statistics table
  vtkTable* primaryTab = vtkTable::New();

  vtkStringArray* stringCol = vtkStringArray::New();
  stringCol->SetName( "Variable" );
  primaryTab->AddColumn( stringCol );
  stringCol->Delete();

  vtkIdTypeArray* idTypeCol = vtkIdTypeArray::New();
  idTypeCol->SetName( "Cardinality" );
  primaryTab->AddColumn( idTypeCol );
  idTypeCol->Delete();

  // Loop over requests
  vtkIdType nRow = inData->GetNumberOfRows();
  for ( vtksys_stl::set<vtksys_stl::set<vtkStdString> >::const_iterator rit = this->Internals->Requests.begin();
        rit != this->Internals->Requests.end(); ++ rit )
    {
    // Each request contains only one column of interest (if there are others, they are ignored)
    vtksys_stl::set<vtkStdString>::const_iterator it = rit->begin();
    vtkStdString varName = *it;
    if ( ! inData->GetColumnByName( varName ) )
      {
      vtkWarningMacro( "InData table does not have a column "
                       << varName.c_str()
                       << ". Ignoring it." );
      continue;
      }

    // FIXME: calculate stuff here

    // FIXME: end calculations here

    vtkVariantArray* row = vtkVariantArray::New();

    row->SetNumberOfValues( 2 );

    row->SetValue( 0, varName );
    row->SetValue( 1, nRow );

    primaryTab->InsertNextRow( row );

    row->Delete();
    } // rit

  // Finally set first block of output meta port to primary statistics table
  outMeta->SetNumberOfBlocks( 1 );
  outMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Primary Statistics" );
  outMeta->SetBlock( 0, primaryTab );

  // Clean up
  primaryTab->Delete();
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Derive( vtkMultiBlockDataSet* inMeta )
{
  if ( ! inMeta || inMeta->GetNumberOfBlocks() < 1 )
    {
    return;
    }

  vtkTable* primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab  )
    {
    return;
    }

  int numDoubles = 9;
  vtkStdString doubleNames[] = { "Variance t1",
                                 "Variance t2",
                                 "Covariance",
                                 "Determinant",
                                 "Slope t2/t1",
                                 "Intercept t2/t1",
                                 "Slope t1/t2",
                                 "Intercept t1/t2",
                                 "Pearson r" };

  // Create table for derived statistics
  vtkIdType nRow = primaryTab->GetNumberOfRows();
  vtkTable* derivedTab = vtkTable::New();
  vtkDoubleArray* doubleCol;
  for ( int j = 0; j < numDoubles; ++ j )
    {
    if ( ! derivedTab->GetColumnByName( doubleNames[j] ) )
      {
      doubleCol = vtkDoubleArray::New();
      doubleCol->SetName( doubleNames[j] );
      doubleCol->SetNumberOfTuples( nRow );
      derivedTab->AddColumn( doubleCol );
      doubleCol->Delete();
      }
    }

  // Storage for derived values
  double* derivedVals = new double[numDoubles]; //

  for ( int i = 0; i < nRow; ++ i )
    {
    // FIXME: do something here
    }

  // Finally set second block of output meta port to derived statistics table
  inMeta->SetNumberOfBlocks( 2 );
  inMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Derived Statistics" );
  inMeta->SetBlock( 1, derivedTab );

  // Clean up
  derivedTab->Delete();
  delete [] derivedVals;
}

// ----------------------------------------------------------------------
// Use the invalid value of -1 for p-values if R is absent
vtkDoubleArray* vtkAutoCorrelativeStatistics::CalculatePValues(vtkDoubleArray *statCol)
{
  // A column must be created first
  vtkDoubleArray* testCol = vtkDoubleArray::New();

  // Fill this column
  vtkIdType n = statCol->GetNumberOfTuples();
  testCol->SetNumberOfTuples( n );
  for ( vtkIdType r = 0; r < n; ++ r )
    {
    testCol->SetTuple1( r, -1 );
    }

  return testCol;
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::SelectAssessFunctor( vtkTable* outData,
                                                    vtkDataObject* inMetaDO,
                                                    vtkStringArray* rowNames,
                                                    AssessFunctor*& dfunc )
{
  dfunc = 0;
  vtkMultiBlockDataSet* inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
  if ( ! inMeta )
    {
    return;
    }

  vtkTable* primaryTab= vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab )
    {
    return;
    }

  vtkTable* derivedTab = vtkTable::SafeDownCast( inMeta->GetBlock( 1 ) );
  if ( ! derivedTab )
    {
    return;
    }

  vtkIdType nRowPrim = primaryTab->GetNumberOfRows();
  if ( nRowPrim != derivedTab->GetNumberOfRows() )
    {
    return;
    }

  vtkStdString varName = rowNames->GetValue( 0 );

  // Downcast meta columns to string arrays for efficient data access
  vtkStringArray* vars = vtkStringArray::SafeDownCast( primaryTab->GetColumnByName( "Variable" ) );
  if ( ! vars )
    {
    return;
    }

  // Loop over primary statistics table until the requested variable is found
  for ( int r = 0; r < nRowPrim; ++ r )
    {
    if ( vars->GetValue( r ) == varName )
      {
      // Grab the data for the requested variable
      vtkAbstractArray* arr = outData->GetColumnByName( varName );
      if ( ! arr )
        {
        return;
        }

      // For auto-correlative statistics, type must be convertible to DataArray
      // E.g., StringArrays do not fit here
      vtkDataArray* vals = vtkDataArray::SafeDownCast( arr );
      if ( ! vals )
        {
        return;
        }

      // FIXME: Fetch necessary values here and do something with them

      return;
      }
    }

  // If arrived here it means that the variable of interest was not found in the parameter table
}
<commit_msg>Fixed PrintSelf() defect<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkAutoCorrelativeStatistics.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkToolkits.h"

#include "vtkAutoCorrelativeStatistics.h"
#include "vtkStatisticsAlgorithmPrivate.h"

#include "vtkDataObjectCollection.h"
#include "vtkDoubleArray.h"
#include "vtkIdTypeArray.h"
#include "vtkInformation.h"
#include "vtkMath.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkStdString.h"
#include "vtkTable.h"
#include "vtkVariantArray.h"

#include <vtksys/stl/set>
#include <vtksys/ios/sstream>
#include <limits>

vtkStandardNewMacro(vtkAutoCorrelativeStatistics);

// ----------------------------------------------------------------------
vtkAutoCorrelativeStatistics::vtkAutoCorrelativeStatistics()
{
  this->AssessNames->SetNumberOfValues( 1 );
  this->AssessNames->SetValue( 0, "d^2" ); // Squared Mahalanobis distance
}

// ----------------------------------------------------------------------
vtkAutoCorrelativeStatistics::~vtkAutoCorrelativeStatistics()
{
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::PrintSelf( ostream &os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );
  os << indent << "AutoCorrelationOffset: " << this->AutoCorrelationOffset << "\n";
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Aggregate( vtkDataObjectCollection* inMetaColl,
                                              vtkMultiBlockDataSet* outMeta )
{
  if ( ! outMeta )
    {
    return;
    }

  // Get hold of the first model (data object) in the collection
  vtkCollectionSimpleIterator it;
  inMetaColl->InitTraversal( it );
  vtkDataObject *inMetaDO = inMetaColl->GetNextDataObject( it );

  // Verify that the first input model is indeed contained in a multiblock data set
  vtkMultiBlockDataSet* inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
  if ( ! inMeta )
    {
    return;
    }

  // Verify that the first primary statistics are indeed contained in a table
  vtkTable* primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab )
    {
    return;
    }

  vtkIdType nRow = primaryTab->GetNumberOfRows();
  if ( ! nRow )
    {
    // No statistics were calculated.
    return;
    }

  // Use this first model to initialize the aggregated one
  vtkTable* aggregatedTab = vtkTable::New();
  aggregatedTab->DeepCopy( primaryTab );

  // Now, loop over all remaining models and update aggregated each time
  while ( ( inMetaDO = inMetaColl->GetNextDataObject( it ) ) )
    {
    // Verify that the current model is indeed contained in a multiblock data set
    inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
    if ( ! inMeta )
      {
      aggregatedTab->Delete();

      return;
      }

    // Verify that the current primary statistics are indeed contained in a table
    primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
    if ( ! primaryTab )
      {
      aggregatedTab->Delete();

      return;
      }

    if ( primaryTab->GetNumberOfRows() != nRow )
      {
      // Models do not match
      aggregatedTab->Delete();

      return;
      }

    // Iterate over all model rows
    for ( int r = 0; r < nRow; ++ r )
      {
      // Verify that variable names match each other
      if ( primaryTab->GetValueByName( r, "Variable" ) != aggregatedTab->GetValueByName( r, "Variable" ) )
        {
        // Models do not match
        aggregatedTab->Delete();

        return;
        }

      // Get aggregated statistics
      int n = aggregatedTab->GetValueByName( r, "Cardinality" ).ToInt();

      // Get current model statistics
      int n_c = primaryTab->GetValueByName( r, "Cardinality" ).ToInt();

      // Update global statics
      int N = n + n_c;

      // Store updated model
      aggregatedTab->SetValueByName( r, "Cardinality", N );
      }
    }

  // Finally set first block of aggregated model to primary statistics table
  outMeta->SetNumberOfBlocks( 1 );
  outMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Primary Statistics" );
  outMeta->SetBlock( 0, aggregatedTab );

  // Clean up
  aggregatedTab->Delete();
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Learn( vtkTable* inData,
                                          vtkTable* vtkNotUsed( inParameters ),
                                          vtkMultiBlockDataSet* outMeta )
{
  if ( ! inData )
    {
    return;
    }

  if ( ! outMeta )
    {
    return;
    }

  // The primary statistics table
  vtkTable* primaryTab = vtkTable::New();

  vtkStringArray* stringCol = vtkStringArray::New();
  stringCol->SetName( "Variable" );
  primaryTab->AddColumn( stringCol );
  stringCol->Delete();

  vtkIdTypeArray* idTypeCol = vtkIdTypeArray::New();
  idTypeCol->SetName( "Cardinality" );
  primaryTab->AddColumn( idTypeCol );
  idTypeCol->Delete();

  // Loop over requests
  vtkIdType nRow = inData->GetNumberOfRows();
  for ( vtksys_stl::set<vtksys_stl::set<vtkStdString> >::const_iterator rit = this->Internals->Requests.begin();
        rit != this->Internals->Requests.end(); ++ rit )
    {
    // Each request contains only one column of interest (if there are others, they are ignored)
    vtksys_stl::set<vtkStdString>::const_iterator it = rit->begin();
    vtkStdString varName = *it;
    if ( ! inData->GetColumnByName( varName ) )
      {
      vtkWarningMacro( "InData table does not have a column "
                       << varName.c_str()
                       << ". Ignoring it." );
      continue;
      }

    // FIXME: calculate stuff here

    // FIXME: end calculations here

    vtkVariantArray* row = vtkVariantArray::New();

    row->SetNumberOfValues( 2 );

    row->SetValue( 0, varName );
    row->SetValue( 1, nRow );

    primaryTab->InsertNextRow( row );

    row->Delete();
    } // rit

  // Finally set first block of output meta port to primary statistics table
  outMeta->SetNumberOfBlocks( 1 );
  outMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Primary Statistics" );
  outMeta->SetBlock( 0, primaryTab );

  // Clean up
  primaryTab->Delete();
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::Derive( vtkMultiBlockDataSet* inMeta )
{
  if ( ! inMeta || inMeta->GetNumberOfBlocks() < 1 )
    {
    return;
    }

  vtkTable* primaryTab = vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab  )
    {
    return;
    }

  int numDoubles = 9;
  vtkStdString doubleNames[] = { "Variance t1",
                                 "Variance t2",
                                 "Covariance",
                                 "Determinant",
                                 "Slope t2/t1",
                                 "Intercept t2/t1",
                                 "Slope t1/t2",
                                 "Intercept t1/t2",
                                 "Pearson r" };

  // Create table for derived statistics
  vtkIdType nRow = primaryTab->GetNumberOfRows();
  vtkTable* derivedTab = vtkTable::New();
  vtkDoubleArray* doubleCol;
  for ( int j = 0; j < numDoubles; ++ j )
    {
    if ( ! derivedTab->GetColumnByName( doubleNames[j] ) )
      {
      doubleCol = vtkDoubleArray::New();
      doubleCol->SetName( doubleNames[j] );
      doubleCol->SetNumberOfTuples( nRow );
      derivedTab->AddColumn( doubleCol );
      doubleCol->Delete();
      }
    }

  // Storage for derived values
  double* derivedVals = new double[numDoubles]; //

  for ( int i = 0; i < nRow; ++ i )
    {
    // FIXME: do something here
    }

  // Finally set second block of output meta port to derived statistics table
  inMeta->SetNumberOfBlocks( 2 );
  inMeta->GetMetaData( static_cast<unsigned>( 0 ) )->Set( vtkCompositeDataSet::NAME(), "Derived Statistics" );
  inMeta->SetBlock( 1, derivedTab );

  // Clean up
  derivedTab->Delete();
  delete [] derivedVals;
}

// ----------------------------------------------------------------------
// Use the invalid value of -1 for p-values if R is absent
vtkDoubleArray* vtkAutoCorrelativeStatistics::CalculatePValues(vtkDoubleArray *statCol)
{
  // A column must be created first
  vtkDoubleArray* testCol = vtkDoubleArray::New();

  // Fill this column
  vtkIdType n = statCol->GetNumberOfTuples();
  testCol->SetNumberOfTuples( n );
  for ( vtkIdType r = 0; r < n; ++ r )
    {
    testCol->SetTuple1( r, -1 );
    }

  return testCol;
}

// ----------------------------------------------------------------------
void vtkAutoCorrelativeStatistics::SelectAssessFunctor( vtkTable* outData,
                                                    vtkDataObject* inMetaDO,
                                                    vtkStringArray* rowNames,
                                                    AssessFunctor*& dfunc )
{
  dfunc = 0;
  vtkMultiBlockDataSet* inMeta = vtkMultiBlockDataSet::SafeDownCast( inMetaDO );
  if ( ! inMeta )
    {
    return;
    }

  vtkTable* primaryTab= vtkTable::SafeDownCast( inMeta->GetBlock( 0 ) );
  if ( ! primaryTab )
    {
    return;
    }

  vtkTable* derivedTab = vtkTable::SafeDownCast( inMeta->GetBlock( 1 ) );
  if ( ! derivedTab )
    {
    return;
    }

  vtkIdType nRowPrim = primaryTab->GetNumberOfRows();
  if ( nRowPrim != derivedTab->GetNumberOfRows() )
    {
    return;
    }

  vtkStdString varName = rowNames->GetValue( 0 );

  // Downcast meta columns to string arrays for efficient data access
  vtkStringArray* vars = vtkStringArray::SafeDownCast( primaryTab->GetColumnByName( "Variable" ) );
  if ( ! vars )
    {
    return;
    }

  // Loop over primary statistics table until the requested variable is found
  for ( int r = 0; r < nRowPrim; ++ r )
    {
    if ( vars->GetValue( r ) == varName )
      {
      // Grab the data for the requested variable
      vtkAbstractArray* arr = outData->GetColumnByName( varName );
      if ( ! arr )
        {
        return;
        }

      // For auto-correlative statistics, type must be convertible to DataArray
      // E.g., StringArrays do not fit here
      vtkDataArray* vals = vtkDataArray::SafeDownCast( arr );
      if ( ! vals )
        {
        return;
        }

      // FIXME: Fetch necessary values here and do something with them

      return;
      }
    }

  // If arrived here it means that the variable of interest was not found in the parameter table
}
<|endoftext|>


<commit_before>/* Find the length of STRING, but scan at most MAXLEN characters.
   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
   Written by Simon Josefsson.

   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, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

/* Find the length of STRING, but scan at most MAXLEN characters.
   If no '\0' terminator is found in that many characters, return MAXLEN.  */

#include <cstdlib>
#include <string>

size_t
strnlen (const char *string, size_t maxlen)
{
  const char *end = (const char*) memchr (string, '\0', maxlen);
  return end ? (size_t) (end - string) : maxlen;
}
<commit_msg>util: wrong header files being included    fixes MacOS bug for https://bugs.launchpad.net/opencog/+bug/1054661<commit_after>/* Find the length of STRING, but scan at most MAXLEN characters.
   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
   Written by Simon Josefsson.

   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, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

/* Find the length of STRING, but scan at most MAXLEN characters.
   If no '\0' terminator is found in that many characters, return MAXLEN.  */

#include <stdlib.h>
#include <string.h>

size_t
strnlen (const char *string, size_t maxlen)
{
  const char *end = (const char*) memchr (string, '\0', maxlen);
  return end ? (size_t) (end - string) : maxlen;
}
<|endoftext|>