<commit_before>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/*
 * xsendstring - send a bunch of keystrokes to the app having current input focus
 *
 * Calls X library functions defined in Xt and Xtst
 *
 * +. Initialize all the params of XKeyEvent
 * +  More escape sequences from http://msdn.microsoft.com/en-us/library/h21280bw%28VS.80%29.aspx
 * +  XGetErrorText and sprintf overflow
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <errno.h>
#include <limits.h>

#include <X11/Intrinsic.h> // in libxt-dev
#include <X11/keysym.h>
#include <X11/extensions/XTest.h> // in libxtst-dev

#include "./xsendstring.h"
#include "../sleep.h"
#include "../../core/PwsPlatform.h" // for NumberOf()
#include "../../core/StringX.h"

namespace { // anonymous namespace for hiding
  //           local variables and functions
typedef struct _KeyPress {
  KeyCode code;
  unsigned int state;
} KeyPressInfo;

struct AutotypeGlobals
{
	Boolean			error_detected;
	char			errorString[1024];
	KeyCode 		lshiftCode;
  pws_os::AutotypeMethod	method;
	Boolean			LiteralKeysymsInitialized;
} atGlobals	= { False, {0}, 0, pws_os::ATMETHOD_AUTO, False };

class autotype_exception: public std::exception
{
  public:
  virtual const char* what() const throw() {
    return atGlobals.errorString;
  }
};

/*
 * ErrorHandler will be called when X detects an error. This function
 * just sets a global flag and saves the error message text
 */
int ErrorHandler(Display *my_dpy, XErrorEvent *event)
{
  char xmsg[512] = {0};

  atGlobals.error_detected = TRUE;
  XGetErrorText(my_dpy, event->error_code, xmsg, NumberOf(xmsg) - 1);
  snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString)-1, "X error (%d): %s\n", event->request_code, xmsg);
  return 0;
}

/*
 * - characters which need to be manually converted to KeySyms
 */

static struct {
    char ch;
    const char* keystr;
	KeySym sym;
} LiteralKeysyms[] =
{
    { ' ', 		"space", 		NoSymbol },
    { '\t', 	"Tab",  		NoSymbol },
    { '\n', 	"Linefeed", 	NoSymbol },
    { '\r', 	"Return", 		NoSymbol },
    { '\010', 	"BackSpace", 	NoSymbol },  /* \b doesn't work */
    { '\177', 	"Delete", 		NoSymbol },
    { '\033', 	"Escape", 		NoSymbol },  /* \e doesn't work and \e is non-iso escape sequence*/
    { '!', 		"exclam", 		NoSymbol },
    { '#', 		"numbersign", 	NoSymbol },
    { '%', 		"percent", 		NoSymbol },
    { '$', 		"dollar", 		NoSymbol },
    { '&', 		"ampersand", 	NoSymbol },
    { '"', 		"quotedbl", 	NoSymbol },
    { '\'', 	"apostrophe", 	NoSymbol },
    { '(', 		"parenleft", 	NoSymbol },
    { ')', 		"parenright", 	NoSymbol },
    { '*', 		"asterisk", 	NoSymbol },
    { '=', 		"equal", 		NoSymbol },
    { '+', 		"plus", 		NoSymbol },
    { ',', 		"comma", 		NoSymbol },
    { '-', 		"minus", 		NoSymbol },
    { '.', 		"period", 		NoSymbol },
    { '/', 		"slash", 		NoSymbol },
    { ':', 		"colon", 		NoSymbol },
    { ';', 		"semicolon", 	NoSymbol },
    { '<', 		"less", 		44 	 }, /* I don't understand why we get '>' instead of '<' unless we hardcode this */
    { '>', 		"greater", 		NoSymbol },
    { '?', 		"question", 	NoSymbol },
    { '@', 		"at", 			NoSymbol },
    { '[', 		"bracketleft", 	NoSymbol },
    { ']', 		"bracketright", NoSymbol },
    { '\\', 	"backslash", 	NoSymbol },
    { '^', 		"asciicircum", 	NoSymbol },
    { '_', 		"underscore", 	NoSymbol },
    { '`', 		"grave", 		NoSymbol },
    { '{', 		"braceleft", 	NoSymbol },
    { '|', 		"bar", 			NoSymbol },
    { '}', 		"braceright", 	NoSymbol },
    { '~', 		"asciitilde", 	NoSymbol },
};

void InitLiteralKeysyms(void)
{
	size_t idx;
	for (idx = 0; idx < NumberOf(LiteralKeysyms); ++idx)
		if (LiteralKeysyms[idx].sym == NoSymbol)
			LiteralKeysyms[idx].sym = XStringToKeysym(LiteralKeysyms[idx].keystr);

	atGlobals.lshiftCode = XKeysymToKeycode(XOpenDisplay(NULL), XK_Shift_L);
}

KeySym GetLiteralKeysym(char* keystring)
{
	size_t idx;
	for (idx = 0; idx < NumberOf(LiteralKeysyms); ++idx)
		if (keystring[0] ==  LiteralKeysyms[idx].ch )
			return LiteralKeysyms[idx].sym;

	return NoSymbol;
}

void XTest_SendEvent(XKeyEvent *event)
{
	XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
}

void XSendKeys_SendEvent(XKeyEvent *event)
{
    XSendEvent(event->display, event->window, TRUE, KeyPressMask, reinterpret_cast<XEvent *>(event));
}

void XSendKeys_SendKeyEvent(XKeyEvent* event)
{
	event->type = KeyPress;
	XSendKeys_SendEvent(event);

	event->type = KeyRelease;
	XSendKeys_SendEvent(event);

	XFlush(event->display);
}

void XTest_SendKeyEvent(XKeyEvent* event)
{
	XKeyEvent shiftEvent;

	/* must simulate the shift-press for CAPS and shifted keypresses manually */
	if (event->state & ShiftMask) {
		memcpy(&shiftEvent, event, sizeof(shiftEvent));

		shiftEvent.keycode = atGlobals.lshiftCode;
		shiftEvent.type = KeyPress;

		XTest_SendEvent(&shiftEvent);
	}

	event->type = KeyPress;
	XTest_SendEvent(event);

	event->type = KeyRelease;
	XTest_SendEvent(event);

	if (event->state & ShiftMask) {
		shiftEvent.type = KeyRelease;
		XTest_SendEvent(&shiftEvent);
	}

	XFlush(event->display);

}

Bool UseXTest(void)
{
	int major_opcode, first_event, first_error;
	static Bool useXTest;
	static int checked = 0;

	if (!checked) {
		useXTest = XQueryExtension(XOpenDisplay(0), "XTEST", &major_opcode, &first_event, &first_error);
		checked = 1;
	}
	return useXTest;
}

void InitKeyEvent(XKeyEvent* event)
{
	int	  revert_to;
	event->display = XOpenDisplay(NULL);
	XGetInputFocus(event->display, &event->window, &revert_to);

	event->subwindow = None;
	event->x = event->y = event->x_root = event->y_root = 1;
	event->same_screen = TRUE;
}

int FindModifierMask(Display* disp, KeySym sym)
{
  int modmask = 0;
  XModifierKeymap* modmap = XGetModifierMapping(disp);
  if (modmap) {
    const int last = 8*modmap->max_keypermod;
    //begin at 4th row, where Mod1 starts
    for (int i = 3*modmap->max_keypermod && !modmask; i < last; i++) {
      //
      const KeyCode kc = modmap->modifiermap[i];
      if (!kc)
        continue;
      int keysyms_per_keycode = 0;
      // For each keycode attached to this modifier, get a list of all keysyms
      // attached with this keycode. If any of those keysyms is what we are looking
      // for, then this is the modifier to use
      KeySym* symlist = XGetKeyboardMapping(disp, kc, 1, &keysyms_per_keycode);
      if ( symlist) {
        for (int j = 0; j < keysyms_per_keycode; j++) {
          if (sym == symlist[j]) {
            modmask = (i / modmap->max_keypermod);
            break;
          }
        }
      }
    }
    XFreeModifiermap(modmap);
  }
  assert( modmask >= 3 && modmask <= 7);
  return 1 << modmask;
}

int CalcModifiersForKeysym(KeyCode code, KeySym sym, Display* disp)
{
  int keysyms_per_keycode = 0;
  const KeySym* symlist = XGetKeyboardMapping(disp, code, 1, &keysyms_per_keycode);
  if (symlist != NULL && keysyms_per_keycode > 0) {
    const int ModeSwitchMask = FindModifierMask(disp, XK_Mode_switch);
    const int Level3ShiftMask = FindModifierMask(disp, XK_ISO_Level3_Shift);
    int mods[] = {
      0,                  //none
      ShiftMask,
      ModeSwitchMask,
      ShiftMask | ModeSwitchMask,
      // beyond this, its all guesswork since there's no documentation, but see this:
      //
      //     http://superuser.com/questions/189869/xmodmap-six-characters-to-one-key
      //
      // Also, if you install mulitple keyboard layouts the number of keysyms-per-keycode
      // will keep increasing to a max of 16 (up to 4 layouts can be installed together
      // in Ubuntu 11.04).  For some keycodes, you will actually have non-NoSymbol
      // keysyms beyond the first four
      //
      // We probably shouldn't go here if Mode_switch and ISO_Level3_Shift are assigned to
      // the same modifier mask
      Level3ShiftMask,
      ShiftMask | Level3ShiftMask,
      ModeSwitchMask | Level3ShiftMask,
      ShiftMask | ModeSwitchMask | Level3ShiftMask,
    };
    const int max_keysym_index = std::min(int(NumberOf(mods)), keysyms_per_keycode);
    for (int idx = 0; idx < max_keysym_index; ++idx) {
      if (symlist[idx] == sym)
        return mods[idx];
    }
  }
  // we should at least find the keysym without any mods (index 0)
  assert(0);
  return 0;
}

/*
 * DoSendString - actually sends a string to the X Window having input focus
 *
 * The main task of this function is to convert the ascii char values
 * into X KeyCodes.  But they need to be converted to X KeySyms first
 * and then to the keycodes.  The KeyCodes can have any random values
 * and are not contiguous like the ascii values are.
 *
 * Some escape sequences can be converted to the appropriate KeyCodes
 * by this function.  See the code below for details
 */
void DoSendString(const StringX& str, pws_os::AutotypeMethod method, unsigned delayMS)
{

  if (!atGlobals.LiteralKeysymsInitialized) {
    InitLiteralKeysyms();
    atGlobals.LiteralKeysymsInitialized = True;
  }

  XKeyEvent event;
  InitKeyEvent(&event);

  // convert all the chars into keycodes and required shift states first
  // Abort if any of the characters cannot be converted
  typedef std::vector<KeyPressInfo> KeyPressInfoVector;
  KeyPressInfoVector keypresses;

  for (StringX::const_iterator srcIter = str.begin(); srcIter != str.end(); ++srcIter) {

    //throw away 'vertical tab' chars which are only used on Windows to send a shift+tab
    //as a workaround for some issues with IE
    if (*srcIter == _T('\v'))
      continue;

    //This array holds the multibyte representation of the current (wide) char, plus NULL
    char keystring[MB_LEN_MAX + 1] = {0};

    mbstate_t state = mbstate_t();//using init throw constructor because of missing initializer warning

    size_t ret = wcrtomb(keystring, *srcIter, &state);
    if (ret == static_cast<size_t>(-1)) {
      snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString),
              "char at index(%u), value(%d) couldn't be converted to keycode. %s\n",
                  static_cast<unsigned int>(std::distance(str.begin(), srcIter)), static_cast<int>(*srcIter), strerror(errno));
      atGlobals.error_detected = True;
      return;
    }

    ASSERT(ret < (NumberOf(keystring)-1));

    //Try a regular conversion first
    KeySym sym = XStringToKeysym(keystring);

    //Failing which, use our hard-coded special names for certain keys
    if (NoSymbol != sym || (sym = GetLiteralKeysym(keystring)) != NoSymbol) {
      KeyPressInfo keypress = {0, 0};
      if ((keypress.code = XKeysymToKeycode(event.display, sym)) != 0) {
        //non-zero return value implies sym -> code was successful
        keypress.state |= CalcModifiersForKeysym(keypress.code, sym, event.display);
        keypresses.push_back(keypress);
      }
      else {
        const char* symStr = XKeysymToString(sym);
        snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString),
              "Could not get keycode for key char(%s) - sym(%d) - str(%s). Aborting autotype\n",
                          keystring, static_cast<int>(sym), symStr ? symStr : "NULL");
        atGlobals.error_detected = True;
        return;
      }
    }
    else {
      snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString),
              "Cannot convert '%s' to keysym. Aborting autotype\n", keystring);
      atGlobals.error_detected = True;
      return;
    }
  }

  XSetErrorHandler(ErrorHandler);
  atGlobals.error_detected = False;

  bool useXTEST = (UseXTest() && method != pws_os::ATMETHOD_XSENDKEYS);
  void (*KeySendFunction)(XKeyEvent*);

  if ( useXTEST) {
    KeySendFunction = XTest_SendKeyEvent;
    XTestGrabControl(event.display, True);
  }
  else {
    KeySendFunction = XSendKeys_SendKeyEvent;
  }

  for (KeyPressInfoVector::const_iterator itr = keypresses.begin(); itr != keypresses.end()
                              && !atGlobals.error_detected; ++itr) {
    event.keycode = itr->code;
    event.state = itr->state;
    event.time = CurrentTime;

    KeySendFunction(&event);
    pws_os::sleep_ms(delayMS);
  }

  if (useXTEST) {
    XTestGrabControl(event.display, False);
  }
  else {
    XSync(event.display, False);
  }

  XSetErrorHandler(NULL);
}

} // anonymous namespace

/*
 * SendString - The interface method for CKeySend
 *
 * The actual work is done by DoSendString above. This function just
 * just throws an exception if DoSendString encounters an error.
 *
 */
void pws_os::SendString(const StringX& str, AutotypeMethod method, unsigned delayMS)
{
  atGlobals.error_detected = false;
  atGlobals.errorString[0] = 0;

  DoSendString(str, method, delayMS);

  if (atGlobals.error_detected)
    throw autotype_exception();
}
<commit_msg>We only need to track keysyms for wchar_t values less than 0x20<commit_after>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/*
 * xsendstring - send a bunch of keystrokes to the app having current input focus
 *
 * Calls X library functions defined in Xt and Xtst
 *
 * +. Initialize all the params of XKeyEvent
 * +  More escape sequences from http://msdn.microsoft.com/en-us/library/h21280bw%28VS.80%29.aspx
 * +  XGetErrorText and sprintf overflow
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <errno.h>
#include <limits.h>

#include <X11/Intrinsic.h> // in libxt-dev
#include <X11/keysym.h>
#include <X11/extensions/XTest.h> // in libxtst-dev

#include "./xsendstring.h"
#include "../sleep.h"
#include "../../core/PwsPlatform.h" // for NumberOf()
#include "../../core/StringX.h"

namespace { // anonymous namespace for hiding
  //           local variables and functions
typedef struct _KeyPress {
  KeyCode code;
  unsigned int state;
} KeyPressInfo;

struct AutotypeGlobals
{
	Boolean			error_detected;
	char			errorString[1024];
	KeyCode 		lshiftCode;
  pws_os::AutotypeMethod	method;
	Boolean			LiteralKeysymsInitialized;
} atGlobals	= { False, {0}, 0, pws_os::ATMETHOD_AUTO, False };

class autotype_exception: public std::exception
{
  public:
  virtual const char* what() const throw() {
    return atGlobals.errorString;
  }
};

/*
 * ErrorHandler will be called when X detects an error. This function
 * just sets a global flag and saves the error message text
 */
int ErrorHandler(Display *my_dpy, XErrorEvent *event)
{
  char xmsg[512] = {0};

  atGlobals.error_detected = TRUE;
  XGetErrorText(my_dpy, event->error_code, xmsg, NumberOf(xmsg) - 1);
  snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString)-1, "X error (%d): %s", event->request_code, xmsg);
  return 0;
}

void InitLiteralKeysyms(void)
{
	atGlobals.lshiftCode = XKeysymToKeycode(XOpenDisplay(NULL), XK_Shift_L);
}

void XTest_SendEvent(XKeyEvent *event)
{
	XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
}

void XSendKeys_SendEvent(XKeyEvent *event)
{
    XSendEvent(event->display, event->window, TRUE, KeyPressMask, reinterpret_cast<XEvent *>(event));
}

void XSendKeys_SendKeyEvent(XKeyEvent* event)
{
	event->type = KeyPress;
	XSendKeys_SendEvent(event);

	event->type = KeyRelease;
	XSendKeys_SendEvent(event);

	XFlush(event->display);
}

void XTest_SendKeyEvent(XKeyEvent* event)
{
	XKeyEvent shiftEvent;

	/* must simulate the shift-press for CAPS and shifted keypresses manually */
	if (event->state & ShiftMask) {
		memcpy(&shiftEvent, event, sizeof(shiftEvent));

		shiftEvent.keycode = atGlobals.lshiftCode;
		shiftEvent.type = KeyPress;

		XTest_SendEvent(&shiftEvent);
	}

	event->type = KeyPress;
	XTest_SendEvent(event);

	event->type = KeyRelease;
	XTest_SendEvent(event);

	if (event->state & ShiftMask) {
		shiftEvent.type = KeyRelease;
		XTest_SendEvent(&shiftEvent);
	}

	XFlush(event->display);

}

Bool UseXTest(void)
{
	int major_opcode, first_event, first_error;
	static Bool useXTest;
	static int checked = 0;

	if (!checked) {
		useXTest = XQueryExtension(XOpenDisplay(0), "XTEST", &major_opcode, &first_event, &first_error);
		checked = 1;
	}
	return useXTest;
}

void InitKeyEvent(XKeyEvent* event)
{
	int	  revert_to;
	event->display = XOpenDisplay(NULL);
	XGetInputFocus(event->display, &event->window, &revert_to);

	event->subwindow = None;
	event->x = event->y = event->x_root = event->y_root = 1;
	event->same_screen = TRUE;
}

int FindModifierMask(Display* disp, KeySym sym)
{
  int modmask = 0;
  XModifierKeymap* modmap = XGetModifierMapping(disp);
  if (modmap) {
    const int last = 8*modmap->max_keypermod;
    //begin at 4th row, where Mod1 starts
    for (int i = 3*modmap->max_keypermod && !modmask; i < last; i++) {
      //
      const KeyCode kc = modmap->modifiermap[i];
      if (!kc)
        continue;
      int keysyms_per_keycode = 0;
      // For each keycode attached to this modifier, get a list of all keysyms
      // attached with this keycode. If any of those keysyms is what we are looking
      // for, then this is the modifier to use
      KeySym* symlist = XGetKeyboardMapping(disp, kc, 1, &keysyms_per_keycode);
      if ( symlist) {
        for (int j = 0; j < keysyms_per_keycode; j++) {
          if (sym == symlist[j]) {
            modmask = (i / modmap->max_keypermod);
            break;
          }
        }
      }
    }
    XFreeModifiermap(modmap);
  }
  assert( modmask >= 3 && modmask <= 7);
  return 1 << modmask;
}

int CalcModifiersForKeysym(KeyCode code, KeySym sym, Display* disp)
{
  int keysyms_per_keycode = 0;
  const KeySym* symlist = XGetKeyboardMapping(disp, code, 1, &keysyms_per_keycode);
  if (symlist != NULL && keysyms_per_keycode > 0) {
    const int ModeSwitchMask = FindModifierMask(disp, XK_Mode_switch);
    const int Level3ShiftMask = FindModifierMask(disp, XK_ISO_Level3_Shift);
    int mods[] = {
      0,                  //none
      ShiftMask,
      ModeSwitchMask,
      ShiftMask | ModeSwitchMask,
      // beyond this, its all guesswork since there's no documentation, but see this:
      //
      //     http://superuser.com/questions/189869/xmodmap-six-characters-to-one-key
      //
      // Also, if you install mulitple keyboard layouts the number of keysyms-per-keycode
      // will keep increasing to a max of 16 (up to 4 layouts can be installed together
      // in Ubuntu 11.04).  For some keycodes, you will actually have non-NoSymbol
      // keysyms beyond the first four
      //
      // We probably shouldn't go here if Mode_switch and ISO_Level3_Shift are assigned to
      // the same modifier mask
      Level3ShiftMask,
      ShiftMask | Level3ShiftMask,
      ModeSwitchMask | Level3ShiftMask,
      ShiftMask | ModeSwitchMask | Level3ShiftMask,
    };
    const int max_keysym_index = std::min(int(NumberOf(mods)), keysyms_per_keycode);
    for (int idx = 0; idx < max_keysym_index; ++idx) {
      if (symlist[idx] == sym)
        return mods[idx];
    }
  }
  // we should at least find the keysym without any mods (index 0)
  assert(0);
  return 0;
}

KeySym wchar2keysym(wchar_t wc)
{
  if (wc < 0x100) {
    if (wc >= 0x20)
      return wc;
    switch(wc) {
      case L'\t': return XK_Tab;
      case L'\r': return XK_Return;
      case L'\n': return XK_Linefeed;
      case '\010': return XK_BackSpace;
      case '\177': return XK_Delete;
      case '\033': return XK_Escape;
      default:
        return NoSymbol;
    }
  }
  if (wc > 0x10ffff || (wc > 0x7e && wc < 0xa0))
    return NoSymbol;
  return wc | 0x01000000;
}

//converts a  single wchar_t to a byte string [i.e. char*]
class wchar2bytes
{
private:
  //MB_CUR_MAX is a function call, not a constant
  char* bytes;
public:
  wchar2bytes(wchar_t wc):  bytes(new char[MB_CUR_MAX*2 + sizeof(wchar_t)*2 + 2 + 1]) {
    mbstate_t ps = {0};
    size_t n;
    if ((n = wcrtomb(bytes, wc, &ps)) == size_t(-1))
      snprintf(bytes, NumberOf(bytes), "U+%04X", int(wc));
    else
      bytes[n] = 0;
  }
  ~wchar2bytes() { delete [] bytes; }
  const char* str() const {return bytes;}
};

/*
 * DoSendString - actually sends a string to the X Window having input focus
 *
 * The main task of this function is to convert the ascii char values
 * into X KeyCodes.  But they need to be converted to X KeySyms first
 * and then to the keycodes.  The KeyCodes can have any random values
 * and are not contiguous like the ascii values are.
 *
 * Some escape sequences can be converted to the appropriate KeyCodes
 * by this function.  See the code below for details
 */
void DoSendString(const StringX& str, pws_os::AutotypeMethod method, unsigned delayMS)
{

  if (!atGlobals.LiteralKeysymsInitialized) {
    InitLiteralKeysyms();
    atGlobals.LiteralKeysymsInitialized = True;
  }

  XKeyEvent event;
  InitKeyEvent(&event);

  // convert all the chars into keycodes and required shift states first
  // Abort if any of the characters cannot be converted
  typedef std::vector<KeyPressInfo> KeyPressInfoVector;
  KeyPressInfoVector keypresses;

  for (StringX::const_iterator srcIter = str.begin(); srcIter != str.end(); ++srcIter) {

    //throw away 'vertical tab' chars which are only used on Windows to send a shift+tab
    //as a workaround for some issues with IE
    if (*srcIter == _T('\v'))
      continue;

    //Try a regular conversion first
    KeySym sym = wchar2keysym(*srcIter);

    if (NoSymbol != sym) {
      KeyPressInfo keypress = {0, 0};
      if ((keypress.code = XKeysymToKeycode(event.display, sym)) != 0) {
        //non-zero return value implies sym -> code was successful
        keypress.state |= CalcModifiersForKeysym(keypress.code, sym, event.display);
        keypresses.push_back(keypress);
      }
      else {
        const char* symStr = XKeysymToString(sym);
        snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString),
              "Could not get keycode for key char(%s) - sym(%#X) - str(%s). Aborting autotype",
                          wchar2bytes(*srcIter).str(), static_cast<int>(sym), symStr ? symStr : "NULL");
        atGlobals.error_detected = True;
        return;
      }
    }
    else {
      snprintf(atGlobals.errorString, NumberOf(atGlobals.errorString),
              "Cannot convert '%s' [U+%04X] to keysym. Aborting autotype", wchar2bytes(*srcIter).str(), int(*srcIter));
      atGlobals.error_detected = True;
      return;
    }
  }

  XSetErrorHandler(ErrorHandler);
  atGlobals.error_detected = False;

  bool useXTEST = (UseXTest() && method != pws_os::ATMETHOD_XSENDKEYS);
  void (*KeySendFunction)(XKeyEvent*);

  if ( useXTEST) {
    KeySendFunction = XTest_SendKeyEvent;
    XTestGrabControl(event.display, True);
  }
  else {
    KeySendFunction = XSendKeys_SendKeyEvent;
  }

  for (KeyPressInfoVector::const_iterator itr = keypresses.begin(); itr != keypresses.end()
                              && !atGlobals.error_detected; ++itr) {
    event.keycode = itr->code;
    event.state = itr->state;
    event.time = CurrentTime;

    KeySendFunction(&event);
    pws_os::sleep_ms(delayMS);
  }

  if (useXTEST) {
    XTestGrabControl(event.display, False);
  }
  else {
    XSync(event.display, False);
  }

  XSetErrorHandler(NULL);
}

} // anonymous namespace

/*
 * SendString - The interface method for CKeySend
 *
 * The actual work is done by DoSendString above. This function just
 * just throws an exception if DoSendString encounters an error.
 *
 */
void pws_os::SendString(const StringX& str, AutotypeMethod method, unsigned delayMS)
{
  atGlobals.error_detected = false;
  atGlobals.errorString[0] = 0;

  DoSendString(str, method, delayMS);

  if (atGlobals.error_detected)
    throw autotype_exception();
}
<|endoftext|>


<commit_before><commit_msg>Correct lngmerge not to work with eof<commit_after><|endoftext|>


<commit_before><commit_msg>convert system path to url<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "DependencySplitter.hpp"
#include "../dnf-sack.h"
#include "../utils/regex/regex.hpp"

namespace libdnf {

static const Regex RELDEP_REGEX =
    Regex("^(\\S*)\\s*(<=|>=|<|>|=)?\\s*(\\S*)$", REG_EXTENDED);

static bool
getCmpFlags(int *cmp_type, std::string matchCmpType)
{
    int subexpr_len = matchCmpType.size();
    auto match_start = matchCmpType.c_str();
    if (subexpr_len == 2) {
        if (strncmp(match_start, "<=", 2) == 0) {
            *cmp_type |= HY_LT;
            *cmp_type |= HY_EQ;
        }
        else if (strncmp(match_start, ">=", 2) == 0) {
            *cmp_type |= HY_GT;
            *cmp_type |= HY_EQ;
        }
        else
            return false;
    } else if (subexpr_len == 1) {
        if (*match_start == '<')
            *cmp_type |= HY_LT;
        else if (*match_start == '>')
            *cmp_type |= HY_GT;
        else if (*match_start == '=')
            *cmp_type |= HY_EQ;
        else
            return false;
    } else
        return false;
    return true;
}

bool
DependencySplitter::parse(const char * reldepStr)
{
    enum { NAME = 1, CMP_TYPE = 2, EVR = 3, _LAST_ };
    auto matchResult = RELDEP_REGEX.match(reldepStr, false, _LAST_);
    if (!matchResult.isMatched() || matchResult.getMatchedLen(NAME) == 0) {
        return false;
    }
    name = matchResult.getMatchedString(NAME);
    evr = matchResult.getMatchedString(EVR);
    cmpType = 0;
    int evrLen = matchResult.getMatchedLen(EVR);
    int cmpTypeLen = matchResult.getMatchedLen(CMP_TYPE);
    if (cmpTypeLen < 1) {
        if (evrLen > 0) {
            // name contains the space char, e.g. filename like "hello world.jpg"
            evr.clear();
            name = reldepStr;
        }
        return true;
    }
    if (evrLen < 1)
        return false;

    return getCmpFlags(&cmpType, matchResult.getMatchedString(CMP_TYPE));
}

}
<commit_msg>Accept '==' as an operator in reldeps (RhBug:1847946)<commit_after>/*
 * Copyright (C) 2018 Red Hat, Inc.
 *
 * Licensed under the GNU Lesser General Public License Version 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "DependencySplitter.hpp"
#include "../dnf-sack.h"
#include "../log.hpp"
#include "../utils/regex/regex.hpp"

#include "bgettext/bgettext-lib.h"
#include "tinyformat/tinyformat.hpp"

namespace libdnf {

static const Regex RELDEP_REGEX =
    Regex("^(\\S*)\\s*(<=|>=|<|>|=|==)?\\s*(\\S*)$", REG_EXTENDED);

static bool
getCmpFlags(int *cmp_type, std::string matchCmpType)
{
    auto logger(Log::getLogger());
    int subexpr_len = matchCmpType.size();
    auto match_start = matchCmpType.c_str();
    if (subexpr_len == 2) {
        if (strncmp(match_start, "<=", 2) == 0) {
            *cmp_type |= HY_LT;
            *cmp_type |= HY_EQ;
        }
        else if (strncmp(match_start, ">=", 2) == 0) {
            *cmp_type |= HY_GT;
            *cmp_type |= HY_EQ;
        }
        else if (strncmp(match_start, "==", 2) == 0) {
            auto msg = tfm::format(_("Using '==' operator in reldeps can result in an undefined "
                                     "behavior. It is deprecated and the support will be dropped "
                                     "in future versions. Use '=' operator instead."));
            logger->warning(msg);
            *cmp_type |= HY_EQ;
        }
        else
            return false;
    } else if (subexpr_len == 1) {
        if (*match_start == '<')
            *cmp_type |= HY_LT;
        else if (*match_start == '>')
            *cmp_type |= HY_GT;
        else if (*match_start == '=')
            *cmp_type |= HY_EQ;
        else
            return false;
    } else
        return false;
    return true;
}

bool
DependencySplitter::parse(const char * reldepStr)
{
    enum { NAME = 1, CMP_TYPE = 2, EVR = 3, _LAST_ };
    auto matchResult = RELDEP_REGEX.match(reldepStr, false, _LAST_);
    if (!matchResult.isMatched() || matchResult.getMatchedLen(NAME) == 0) {
        return false;
    }
    name = matchResult.getMatchedString(NAME);
    evr = matchResult.getMatchedString(EVR);
    cmpType = 0;
    int evrLen = matchResult.getMatchedLen(EVR);
    int cmpTypeLen = matchResult.getMatchedLen(CMP_TYPE);
    if (cmpTypeLen < 1) {
        if (evrLen > 0) {
            // name contains the space char, e.g. filename like "hello world.jpg"
            evr.clear();
            name = reldepStr;
        }
        return true;
    }
    if (evrLen < 1)
        return false;

    return getCmpFlags(&cmpType, matchResult.getMatchedString(CMP_TYPE));
}

}
<|endoftext|>


<commit_before>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <type_traits>
#include <utility>

#include <hadesmem/config.hpp>

// TODO: Implement same interface as std::optional<T> to make switching later
// easier.

// TODO: Add tests.

// TODO: Add constexpr support. (http://bit.ly/U7lSYy)

namespace hadesmem
{

    namespace detail
    {

        // WARNING: T must have no-throw move, no-throw move assignment and
        // no-throw destruction.
        template <typename T>
        class Optional
        {
        private:
            using Boolean = void(Optional::*)() const;

        public:
            HADESMEM_DETAIL_CONSTEXPR Optional() HADESMEM_DETAIL_NOEXCEPT
                : t_(),
                valid_(false)
            { }

            explicit Optional(T const& t)
                : t_(),
                valid_(false)
            {
                Construct(t);
            }

            // TODO: Conditional noexcept.
            explicit Optional(T&& t)
                : t_(),
                valid_(false)
            {
                Construct(std::move(t));
            }

            Optional(Optional const& other)
                : t_(),
                valid_(false)
            {
                Construct(other.Get());
            }

            Optional& operator=(Optional const& other)
            {
                Optional tmp(other);
                *this = std::move(tmp);

                return *this;
            }

            // TODO: Conditional noexcept.
            Optional(Optional&& other)
                : t_(),
                valid_(false)
            {
                Construct(std::move(other.Get()));
                other.valid_ = false;
            }

            // TODO: Conditional noexcept.
            Optional& operator=(Optional&& other)
            {
                Destroy();
                Construct(std::move(other.Get()));
                other.valid_ = false;

                return *this;
            }

            Optional& operator=(T const& t)
            {
                Destroy();
                Construct(t);

                return *this;
            }

            Optional& operator=(T&& t) HADESMEM_DETAIL_NOEXCEPT
            {
                Destroy();
                Construct(std::move(t));

                return *this;
            }

            ~Optional() HADESMEM_DETAIL_NOEXCEPT
            {
                Destroy();
            }

            // TODO: Emplacement support. (Including default construction of T.)

#if defined(HADESMEM_DETAIL_NO_EXPLICIT_CONVERSION_OPERATOR)
            operator Boolean() const HADESMEM_DETAIL_NOEXCEPT
            {
                return valid_ ? &Optional::NotComparable : nullptr;
            }
#else // #if defined(HADESMEM_DETAIL_NO_EXPLICIT_CONVERSION_OPERATOR)
            explicit operator bool() const HADESMEM_DETAIL_NOEXCEPT
            {
                return valid_;
            }
#endif // #if defined(HADESMEM_DETAIL_NO_EXPLICIT_CONVERSION_OPERATOR)

            T& Get() HADESMEM_DETAIL_NOEXCEPT
            {
                return *GetPtr();
            }

            T const& Get() const HADESMEM_DETAIL_NOEXCEPT
            {
                return *GetPtr();
            }

            T& operator*() HADESMEM_DETAIL_NOEXCEPT
            {
                return Get();
            }

            T const& operator*() const HADESMEM_DETAIL_NOEXCEPT
            {
                return Get();
            }

            T* GetPtr() HADESMEM_DETAIL_NOEXCEPT
            {
                return static_cast<T*>(static_cast<void*>(&t_));
            }

            T const* GetPtr() const HADESMEM_DETAIL_NOEXCEPT
            {
                return static_cast<T const*>(static_cast<void const*>(&t_));
            }

            T* operator->() HADESMEM_DETAIL_NOEXCEPT
            {
                return GetPtr();
            }

            T const* operator->() const HADESMEM_DETAIL_NOEXCEPT
            {
                return GetPtr();
            }

        private:
            void NotComparable() const HADESMEM_DETAIL_NOEXCEPT
            {}

            template <typename U>
            void Construct(U&& u)
            {
                if (valid_)
                {
                    Destroy();
                }

                new (&t_) T(std::forward<U>(u));
                valid_ = true;
            }

            void Destroy() HADESMEM_DETAIL_NOEXCEPT
            {
                if (valid_)
                {
                    GetPtr()->~T();
                    valid_ = false;
                }
            }

            std::aligned_storage_t<sizeof(T), std::alignment_of<T>::value> t_;
            bool valid_;
        };

        // TODO: Add conditional noexcept to operator overloads.

        template <typename T>
        inline bool operator==(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return (!lhs && !rhs) || ((rhs && lhs) && *rhs == *lhs);
        }

        template <typename T>
        inline bool operator!=(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return !(lhs == rhs);
        }

        template <typename T>
        inline bool operator<(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return (!lhs && !rhs) || ((rhs && lhs) && *rhs < *lhs);
        }

    }

}
<commit_msg>* [Optional] Clean up explicit bool operator.<commit_after>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <type_traits>
#include <utility>

#include <hadesmem/config.hpp>

// TODO: Implement same interface as std::optional<T> to make switching later
// easier.

// TODO: Add tests.

// TODO: Add constexpr support. (http://bit.ly/U7lSYy)

namespace hadesmem
{

    namespace detail
    {

        // WARNING: T must have no-throw move, no-throw move assignment and
        // no-throw destruction.
        template <typename T>
        class Optional
        {
        public:
            HADESMEM_DETAIL_CONSTEXPR Optional() HADESMEM_DETAIL_NOEXCEPT
                : t_(),
                valid_(false)
            { }

            explicit Optional(T const& t)
                : t_(),
                valid_(false)
            {
                Construct(t);
            }

            // TODO: Conditional noexcept.
            explicit Optional(T&& t)
                : t_(),
                valid_(false)
            {
                Construct(std::move(t));
            }

            Optional(Optional const& other)
                : t_(),
                valid_(false)
            {
                Construct(other.Get());
            }

            Optional& operator=(Optional const& other)
            {
                Optional tmp(other);
                *this = std::move(tmp);

                return *this;
            }

            // TODO: Conditional noexcept.
            Optional(Optional&& other)
                : t_(),
                valid_(false)
            {
                Construct(std::move(other.Get()));
                other.valid_ = false;
            }

            // TODO: Conditional noexcept.
            Optional& operator=(Optional&& other)
            {
                Destroy();
                Construct(std::move(other.Get()));
                other.valid_ = false;

                return *this;
            }

            Optional& operator=(T const& t)
            {
                Destroy();
                Construct(t);

                return *this;
            }

            Optional& operator=(T&& t) HADESMEM_DETAIL_NOEXCEPT
            {
                Destroy();
                Construct(std::move(t));

                return *this;
            }

            ~Optional() HADESMEM_DETAIL_NOEXCEPT
            {
                Destroy();
            }

            // TODO: Emplacement support. (Including default construction of T.)

            explicit operator bool() const HADESMEM_DETAIL_NOEXCEPT
            {
                return valid_;
            }

            T& Get() HADESMEM_DETAIL_NOEXCEPT
            {
                return *GetPtr();
            }

            T const& Get() const HADESMEM_DETAIL_NOEXCEPT
            {
                return *GetPtr();
            }

            T& operator*() HADESMEM_DETAIL_NOEXCEPT
            {
                return Get();
            }

            T const& operator*() const HADESMEM_DETAIL_NOEXCEPT
            {
                return Get();
            }

            T* GetPtr() HADESMEM_DETAIL_NOEXCEPT
            {
                return static_cast<T*>(static_cast<void*>(&t_));
            }

            T const* GetPtr() const HADESMEM_DETAIL_NOEXCEPT
            {
                return static_cast<T const*>(static_cast<void const*>(&t_));
            }

            T* operator->() HADESMEM_DETAIL_NOEXCEPT
            {
                return GetPtr();
            }

            T const* operator->() const HADESMEM_DETAIL_NOEXCEPT
            {
                return GetPtr();
            }

        private:
            template <typename U>
            void Construct(U&& u)
            {
                if (valid_)
                {
                    Destroy();
                }

                new (&t_) T(std::forward<U>(u));
                valid_ = true;
            }

            void Destroy() HADESMEM_DETAIL_NOEXCEPT
            {
                if (valid_)
                {
                    GetPtr()->~T();
                    valid_ = false;
                }
            }

            std::aligned_storage_t<sizeof(T), std::alignment_of<T>::value> t_;
            bool valid_;
        };

        // TODO: Add conditional noexcept to operator overloads.

        template <typename T>
        inline bool operator==(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return (!lhs && !rhs) || ((rhs && lhs) && *rhs == *lhs);
        }

        template <typename T>
        inline bool operator!=(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return !(lhs == rhs);
        }

        template <typename T>
        inline bool operator<(Optional<T> const& lhs, Optional<T> const& rhs)
        {
            return (!lhs && !rhs) || ((rhs && lhs) && *rhs < *lhs);
        }

    }

}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_COMPONENTS_STAR5_HPP
#define RJ_GAME_COMPONENTS_STAR5_HPP

#include <SFML/Graphics.hpp>

#include <cmath>

namespace rj
{
	class star5 : public sf::ConvexShape
	{
		static constexpr float m_pi{3.14159265359f};
		float m_length;

	public:
		star5(float length) :
			m_length{length}
		{this->init();}

		void set_length(float l) noexcept
		{m_length = l; this->recalculate();}

		float get_length() const noexcept
		{return m_length;}

	private:
		void init() noexcept
		{
			this->setPointCount(5);
			this->recalculate();
		}

		void recalculate() noexcept
		{
			this->setPoint(0, {m_length * std::cos((2 * m_pi) / 5), m_length * std::sin((2 * m_pi) /5)});
			this->setPoint(1, {m_length * std::cos((6 * m_pi) / 5), m_length * std::sin((6 * m_pi) / 5)});
			this->setPoint(2, {m_length * std::cos((10 * m_pi) / 5), m_length * std::sin((10 * m_pi) / 5)});
			this->setPoint(3, {m_length * std::cos((4 * m_pi) / 5), m_length * std::sin((4 * m_pi) / 5)});
			this->setPoint(4, {m_length * std::cos((8 * m_pi) / 5), m_length * std::sin((8 * m_pi) / 5)});
		}
	};
}

#endif // RJ_GAME_COMPONENTS_STAR5_HPP
<commit_msg>added new ctor<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_COMPONENTS_STAR5_HPP
#define RJ_GAME_COMPONENTS_STAR5_HPP

#include <rectojump/global/common.hpp>

#include <SFML/Graphics.hpp>

#include <cmath>

namespace rj
{
	class star5 : public sf::ConvexShape
	{
		static constexpr float m_pi{3.14159265359f};
		float m_length;

	public:
		star5(float length) :
			m_length{length}
		{this->init();}

		star5(float length, const vec2f& pos) :
			star5{length}
		{this->setPosition(pos);}

		void set_length(float l) noexcept
		{m_length = l; this->recalculate();}

		float get_length() const noexcept
		{return m_length;}

	private:
		void init() noexcept
		{
			this->setPointCount(5);
			this->recalculate();
		}

		void recalculate() noexcept
		{
			this->setPoint(0, {m_length * std::cos((2 * m_pi) / 5), m_length * std::sin((2 * m_pi) /5)});
			this->setPoint(1, {m_length * std::cos((6 * m_pi) / 5), m_length * std::sin((6 * m_pi) / 5)});
			this->setPoint(2, {m_length * std::cos((10 * m_pi) / 5), m_length * std::sin((10 * m_pi) / 5)});
			this->setPoint(3, {m_length * std::cos((4 * m_pi) / 5), m_length * std::sin((4 * m_pi) / 5)});
			this->setPoint(4, {m_length * std::cos((8 * m_pi) / 5), m_length * std::sin((8 * m_pi) / 5)});
		}
	};
}

#endif // RJ_GAME_COMPONENTS_STAR5_HPP
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN

#include "catch.hpp"
#include "rapidjson/document.h"
#include "mstch/mstch.hpp"
#include "test_context.hpp"
#include "test_data.hpp"
#include "specs_data.hpp"
#include "specs_lambdas.hpp"

using namespace mstchtest;

mstch::node to_value(const rapidjson::Value& val) {
  if (val.IsString())
    return std::string{val.GetString()};
  if (val.IsBool())
    return val.GetBool();
  if (val.IsDouble())
    return val.GetDouble();
  if (val.IsInt())
    return val.GetInt();
  return mstch::node{};
}

mstch::array to_array(const rapidjson::Value& val);

mstch::map to_object(const rapidjson::Value& val) {
  mstch::map ret;
  for (auto i = val.MemberBegin(); i != val.MemberEnd(); ++i) {
    if (i->value.IsArray())
      ret.insert(std::make_pair(i->name.GetString(), to_array(i->value)));
    else if (i->value.IsObject())
      ret.insert(std::make_pair(i->name.GetString(), to_object(i->value)));
    else
      ret.insert(std::make_pair(i->name.GetString(), to_value(i->value)));
  }
  return ret;
}

mstch::array to_array(const rapidjson::Value& val) {
  mstch::array ret;
  for (auto i = val.Begin(); i != val.End(); ++i) {
    if (i->IsArray())
      ret.push_back(to_array(*i));
    else if (i->IsObject())
      ret.push_back(to_object(*i));
    else
      ret.push_back(to_value(*i));
  }
  return ret;
}

mstch::node parse_with_rapidjson(const std::string& str) {
  rapidjson::Document doc;
  doc.Parse(str.c_str());
  return to_object(doc);
}

#define MSTCH_PARTIAL_TEST(x) TEST_CASE(#x) { \
  REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data, {{"partial", x ## _partial}})); \
}

#define MSTCH_TEST(x) TEST_CASE(#x) { \
  REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data)); \
}

#define SPECS_TEST(x) TEST_CASE("specs_" #x) { \
  using boost::get; \
  auto data = parse_with_rapidjson(x ## _json); \
  for (auto& test_item: get<mstch::array>(get<mstch::map>(data)["tests"])) {\
    auto test = get<mstch::map>(test_item); \
    std::map<std::string,std::string> partials; \
    if (test.count("partials")) \
      for (auto& partial_item: get<mstch::map>(test["partials"])) \
        partials.insert(std::make_pair(partial_item.first, get<std::string>(partial_item.second))); \
    for (auto& data_item: get<mstch::map>(test["data"])) \
      if (data_item.first == "lambda") \
        data_item.second = specs_lambdas[get<std::string>(test["name"])]; \
    SECTION(get<std::string>(test["name"])) \
      REQUIRE(mstch::render( \
          get<std::string>(test["template"]), \
          test["data"], partials) == \
          get<std::string>(test["expected"])); \
  } \
}

MSTCH_TEST(ampersand_escape)
MSTCH_TEST(apostrophe)
MSTCH_TEST(array_of_strings)
MSTCH_TEST(backslashes)
MSTCH_TEST(bug_11_eating_whitespace)
MSTCH_TEST(bug_length_property)
MSTCH_TEST(changing_delimiters)
MSTCH_TEST(comments)
MSTCH_TEST(complex)
MSTCH_TEST(context_lookup)
MSTCH_TEST(delimiters)
MSTCH_TEST(disappearing_whitespace)
MSTCH_TEST(dot_notation)
MSTCH_TEST(double_render)
MSTCH_TEST(empty_list)
MSTCH_TEST(empty_sections)
MSTCH_TEST(empty_string)
MSTCH_TEST(empty_template)
MSTCH_TEST(error_eof_in_section)
MSTCH_TEST(error_eof_in_tag)
MSTCH_TEST(error_not_found)
MSTCH_TEST(escaped)
MSTCH_TEST(falsy)
MSTCH_TEST(falsy_array)
MSTCH_TEST(grandparent_context)
MSTCH_TEST(higher_order_sections)
MSTCH_TEST(implicit_iterator)
MSTCH_TEST(included_tag)
MSTCH_TEST(inverted_section)
MSTCH_TEST(keys_with_questionmarks)
MSTCH_TEST(multiline_comment)
MSTCH_TEST(nested_dot)
MSTCH_TEST(nested_higher_order_sections)
MSTCH_TEST(nested_iterating)
MSTCH_TEST(nesting)
MSTCH_TEST(nesting_same_name)
MSTCH_TEST(null_lookup_array)
MSTCH_TEST(null_lookup_object)
MSTCH_TEST(null_string)
MSTCH_TEST(null_view)
MSTCH_PARTIAL_TEST(partial_array)
MSTCH_PARTIAL_TEST(partial_array_of_partials)
MSTCH_PARTIAL_TEST(partial_array_of_partials_implicit)
MSTCH_PARTIAL_TEST(partial_empty)
MSTCH_PARTIAL_TEST(partial_template)
MSTCH_PARTIAL_TEST(partial_view)
MSTCH_PARTIAL_TEST(partial_whitespace)
MSTCH_TEST(recursion_with_same_names)
MSTCH_TEST(reuse_of_enumerables)
MSTCH_TEST(section_as_context)
MSTCH_PARTIAL_TEST(section_functions_in_partials)
MSTCH_TEST(simple)
MSTCH_TEST(string_as_context)
MSTCH_TEST(two_in_a_row)
MSTCH_TEST(two_sections)
MSTCH_TEST(unescaped)
MSTCH_TEST(whitespace)
MSTCH_TEST(zero_view)

SPECS_TEST(comments)
SPECS_TEST(delimiters)
SPECS_TEST(interpolation)
SPECS_TEST(inverted)
SPECS_TEST(partials)
SPECS_TEST(sections)
SPECS_TEST(lambdas)
<commit_msg>fix for libc++<commit_after>#define CATCH_CONFIG_MAIN

#include "catch.hpp"
#include "rapidjson/document.h"
#include "mstch/mstch.hpp"
#include "test_context.hpp"
#include "test_data.hpp"
#include "specs_data.hpp"
#include "specs_lambdas.hpp"

using namespace mstchtest;

mstch::node to_value(const rapidjson::Value& val) {
  if (val.IsString())
    return std::string{val.GetString()};
  if (val.IsBool())
    return val.GetBool();
  if (val.IsDouble())
    return val.GetDouble();
  if (val.IsInt())
    return val.GetInt();
  return mstch::node{};
}

mstch::array to_array(const rapidjson::Value& val);

mstch::map to_object(const rapidjson::Value& val) {
  mstch::map ret;
  for (auto i = val.MemberBegin(); i != val.MemberEnd(); ++i) {
    if (i->value.IsArray())
      ret.insert(std::make_pair(i->name.GetString(), to_array(i->value)));
    else if (i->value.IsObject())
      ret.insert(std::make_pair(i->name.GetString(), to_object(i->value)));
    else
      ret.insert(std::make_pair(i->name.GetString(), to_value(i->value)));
  }
  return ret;
}

mstch::array to_array(const rapidjson::Value& val) {
  mstch::array ret;
  for (auto i = val.Begin(); i != val.End(); ++i) {
    if (i->IsArray())
      ret.push_back(to_array(*i));
    else if (i->IsObject())
      ret.push_back(to_object(*i));
    else
      ret.push_back(to_value(*i));
  }
  return ret;
}

mstch::node parse_with_rapidjson(const std::string& str) {
  rapidjson::Document doc;
  doc.Parse(str.c_str());
  return to_object(doc);
}

#define MSTCH_PARTIAL_TEST(x) TEST_CASE(#x) { \
  REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data, {{"partial", x ## _partial}})); \
}

#define MSTCH_TEST(x) TEST_CASE(#x) { \
  REQUIRE(x ## _txt == mstch::render(x ## _mustache, x ## _data)); \
}

#define SPECS_TEST(x) TEST_CASE("specs_" #x) { \
  using boost::get; \
  auto data = parse_with_rapidjson(x ## _json); \
  for (auto& test_item: get<mstch::array>(get<mstch::map>(data)["tests"])) {\
    auto test = get<mstch::map>(test_item); \
    std::map<std::string,std::string> partials; \
    if (test.count("partials")) \
      for (auto& partial_item: get<mstch::map>(test["partials"])) \
        partials.insert(std::make_pair(partial_item.first, get<std::string>(partial_item.second))); \
    mstch::map context; \
    for (auto& data_item: get<mstch::map>(test["data"])) \
      if (data_item.first == "lambda") \
        context.insert(std::make_pair(data_item.first, specs_lambdas[get<std::string>(test["name"])])); \
      else \
        context.insert(data_item); \
    SECTION(get<std::string>(test["name"])) \
      REQUIRE(mstch::render( \
          get<std::string>(test["template"]), \
          context, partials) == \
          get<std::string>(test["expected"])); \
  } \
}

MSTCH_TEST(ampersand_escape)
MSTCH_TEST(apostrophe)
MSTCH_TEST(array_of_strings)
MSTCH_TEST(backslashes)
MSTCH_TEST(bug_11_eating_whitespace)
MSTCH_TEST(bug_length_property)
MSTCH_TEST(changing_delimiters)
MSTCH_TEST(comments)
MSTCH_TEST(complex)
MSTCH_TEST(context_lookup)
MSTCH_TEST(delimiters)
MSTCH_TEST(disappearing_whitespace)
MSTCH_TEST(dot_notation)
MSTCH_TEST(double_render)
MSTCH_TEST(empty_list)
MSTCH_TEST(empty_sections)
MSTCH_TEST(empty_string)
MSTCH_TEST(empty_template)
MSTCH_TEST(error_eof_in_section)
MSTCH_TEST(error_eof_in_tag)
MSTCH_TEST(error_not_found)
MSTCH_TEST(escaped)
MSTCH_TEST(falsy)
MSTCH_TEST(falsy_array)
MSTCH_TEST(grandparent_context)
MSTCH_TEST(higher_order_sections)
MSTCH_TEST(implicit_iterator)
MSTCH_TEST(included_tag)
MSTCH_TEST(inverted_section)
MSTCH_TEST(keys_with_questionmarks)
MSTCH_TEST(multiline_comment)
MSTCH_TEST(nested_dot)
MSTCH_TEST(nested_higher_order_sections)
MSTCH_TEST(nested_iterating)
MSTCH_TEST(nesting)
MSTCH_TEST(nesting_same_name)
MSTCH_TEST(null_lookup_array)
MSTCH_TEST(null_lookup_object)
MSTCH_TEST(null_string)
MSTCH_TEST(null_view)
MSTCH_PARTIAL_TEST(partial_array)
MSTCH_PARTIAL_TEST(partial_array_of_partials)
MSTCH_PARTIAL_TEST(partial_array_of_partials_implicit)
MSTCH_PARTIAL_TEST(partial_empty)
MSTCH_PARTIAL_TEST(partial_template)
MSTCH_PARTIAL_TEST(partial_view)
MSTCH_PARTIAL_TEST(partial_whitespace)
MSTCH_TEST(recursion_with_same_names)
MSTCH_TEST(reuse_of_enumerables)
MSTCH_TEST(section_as_context)
MSTCH_PARTIAL_TEST(section_functions_in_partials)
MSTCH_TEST(simple)
MSTCH_TEST(string_as_context)
MSTCH_TEST(two_in_a_row)
MSTCH_TEST(two_sections)
MSTCH_TEST(unescaped)
MSTCH_TEST(whitespace)
MSTCH_TEST(zero_view)

SPECS_TEST(comments)
SPECS_TEST(delimiters)
SPECS_TEST(interpolation)
SPECS_TEST(inverted)
SPECS_TEST(partials)
SPECS_TEST(sections)
SPECS_TEST(lambdas)
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "test.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/thread.hpp"

#include <boost/bind.hpp>

using namespace libtorrent;

void check_timer_loop(mutex& m, time_point& last, condition_variable& cv)
{
	mutex::scoped_lock l(m);
	cv.wait(l);
	l.unlock();

	for (int i = 0; i < 10000; ++i)
	{
		mutex::scoped_lock l(m);
		time_point now = clock_type::now();
		TEST_CHECK(now >= last);
		last = now;
	}
}

int test_main()
{

	// make sure the time classes have correct semantics

	TEST_EQUAL(total_milliseconds(milliseconds(100)), 100);
	TEST_EQUAL(total_milliseconds(milliseconds(1)),  1);
	TEST_EQUAL(total_milliseconds(seconds(1)), 1000);
	TEST_EQUAL(total_seconds(minutes(1)), 60);
	TEST_EQUAL(total_seconds(hours(1)), 3600);

	// make sure it doesn't wrap at 32 bit arithmetic
	TEST_EQUAL(total_seconds(seconds(281474976)), 281474976);
	TEST_EQUAL(total_milliseconds(milliseconds(281474976)), 281474976);

	// make sure the timer is monotonic

	time_point now = clock_type::now();
	time_point last = now;
	for (int i = 0; i < 1000; ++i)
	{
		now = clock_type::now();
		TEST_CHECK(now >= last);
		last = now;
	}

	mutex m;
	condition_variable cv;
	thread t1(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t2(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t3(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t4(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));

	sleep(100);

	cv.notify_all();

	t1.join();
	t2.join();
	t3.join();
	t4.join();

	return 0;
}

<commit_msg>fix test_time build<commit_after>/*

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

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

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

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

*/

#include "test.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/thread.hpp"

#include <boost/bind.hpp>

using namespace libtorrent;

void check_timer_loop(mutex& m, time_point& last, condition_variable& cv)
{
	mutex::scoped_lock l(m);
	cv.wait(l);
	l.unlock();

	for (int i = 0; i < 10000; ++i)
	{
		mutex::scoped_lock l(m);
		time_point now = clock_type::now();
		TEST_CHECK(now >= last);
		last = now;
	}
}

int test_main()
{

	// make sure the time classes have correct semantics

	TEST_EQUAL(total_milliseconds(milliseconds(100)), 100);
	TEST_EQUAL(total_milliseconds(milliseconds(1)),  1);
	TEST_EQUAL(total_milliseconds(seconds(1)), 1000);
	TEST_EQUAL(total_seconds(minutes(1)), 60);
	TEST_EQUAL(total_seconds(hours(1)), 3600);

	// make sure it doesn't wrap at 32 bit arithmetic
	TEST_EQUAL(total_seconds(seconds(281474976)), 281474976);
	TEST_EQUAL(total_milliseconds(milliseconds(281474976)), 281474976);

	// make sure the timer is monotonic

	time_point now = clock_type::now();
	time_point last = now;
	for (int i = 0; i < 1000; ++i)
	{
		now = clock_type::now();
		TEST_CHECK(now >= last);
		last = now;
	}

	mutex m;
	condition_variable cv;
	thread t1(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t2(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t3(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));
	thread t4(boost::bind(&check_timer_loop, boost::ref(m), boost::ref(last), boost::ref(cv)));

	test_sleep(100);

	cv.notify_all();

	t1.join();
	t2.join();
	t3.join();
	t4.join();

	return 0;
}

<|endoftext|>


<commit_before>#include "testing/testing.hpp"

#include "indexer/cell_coverer.hpp"
#include "indexer/indexer_tests/bounds.hpp"

#include "geometry/covering_utils.hpp"

#include "coding/hex.hpp"

#include "base/logging.hpp"

// Unit test uses m2::CellId<30> for historical reasons, the actual production code uses RectId.
typedef m2::CellId<30> CellIdT;

UNIT_TEST(CellIdToStringRecode)
{
  char const kTest[] = "21032012203";
  TEST_EQUAL(CellIdT::FromString(kTest).ToString(), kTest, ());
}

UNIT_TEST(GoldenCoverRect)
{
  vector<CellIdT> cells;
  CoverRect<OrthoBounds>({27.43, 53.83, 27.70, 53.96}, 4, RectId::DEPTH_LEVELS - 1, cells);

  TEST_EQUAL(cells.size(), 4, ());

  TEST_EQUAL(cells[0].ToString(), "32012211300", ());
  TEST_EQUAL(cells[1].ToString(), "32012211301", ());
  TEST_EQUAL(cells[2].ToString(), "32012211302", ());
  TEST_EQUAL(cells[3].ToString(), "32012211303", ());
}

UNIT_TEST(ArtificialCoverRect)
{
  typedef Bounds<0, 0, 16, 16> TestBounds;

  vector<CellIdT> cells;
  CoverRect<TestBounds>({5, 5, 11, 11}, 4, RectId::DEPTH_LEVELS - 1, cells);

  TEST_EQUAL(cells.size(), 4, ());

  TEST_EQUAL(cells[0].ToString(), "03", ());
  TEST_EQUAL(cells[1].ToString(), "12", ());
  TEST_EQUAL(cells[2].ToString(), "21", ());
  TEST_EQUAL(cells[3].ToString(), "30", ());
}

UNIT_TEST(MaxDepthCoverSpiral)
{
  using TestBounds = Bounds<0, 0, 8, 8>;

  for (auto levelMax = 0; levelMax <= 2; ++levelMax)
  {
    auto cells = vector<m2::CellId<3>>{};

    CoverSpiral<TestBounds, m2::CellId<3>>({2.1, 4.1, 2.1, 4.1}, levelMax, cells);

    TEST_EQUAL(cells.size(), 1, ());
    TEST_EQUAL(cells[0].Level(), levelMax - 1, ());
  }
}
<commit_msg>[indexer] Fix test MaxDepthCoverSpiral<commit_after>#include "testing/testing.hpp"

#include "indexer/cell_coverer.hpp"
#include "indexer/indexer_tests/bounds.hpp"

#include "geometry/covering_utils.hpp"

#include "coding/hex.hpp"

#include "base/logging.hpp"

// Unit test uses m2::CellId<30> for historical reasons, the actual production code uses RectId.
typedef m2::CellId<30> CellIdT;

UNIT_TEST(CellIdToStringRecode)
{
  char const kTest[] = "21032012203";
  TEST_EQUAL(CellIdT::FromString(kTest).ToString(), kTest, ());
}

UNIT_TEST(GoldenCoverRect)
{
  vector<CellIdT> cells;
  CoverRect<OrthoBounds>({27.43, 53.83, 27.70, 53.96}, 4, RectId::DEPTH_LEVELS - 1, cells);

  TEST_EQUAL(cells.size(), 4, ());

  TEST_EQUAL(cells[0].ToString(), "32012211300", ());
  TEST_EQUAL(cells[1].ToString(), "32012211301", ());
  TEST_EQUAL(cells[2].ToString(), "32012211302", ());
  TEST_EQUAL(cells[3].ToString(), "32012211303", ());
}

UNIT_TEST(ArtificialCoverRect)
{
  typedef Bounds<0, 0, 16, 16> TestBounds;

  vector<CellIdT> cells;
  CoverRect<TestBounds>({5, 5, 11, 11}, 4, RectId::DEPTH_LEVELS - 1, cells);

  TEST_EQUAL(cells.size(), 4, ());

  TEST_EQUAL(cells[0].ToString(), "03", ());
  TEST_EQUAL(cells[1].ToString(), "12", ());
  TEST_EQUAL(cells[2].ToString(), "21", ());
  TEST_EQUAL(cells[3].ToString(), "30", ());
}

UNIT_TEST(MaxDepthCoverSpiral)
{
  using TestBounds = Bounds<0, 0, 8, 8>;

  for (auto levelMax = 0; levelMax <= 2; ++levelMax)
  {
    auto cells = vector<m2::CellId<3>>{};

    CoverSpiral<TestBounds, m2::CellId<3>>({2.1, 4.1, 2.1, 4.1}, levelMax, cells);

    TEST_EQUAL(cells.size(), 1, ());
    TEST_EQUAL(cells[0].Level(), levelMax, ());
  }
}
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "test.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"
#include "setup_transfer.hpp" // for load_file
#include "libtorrent/file.hpp" // for combine_path

#include <vector>

using namespace libtorrent;

int test_main()
{
	std::vector<char> utf8_source;
	error_code ec;
	load_file(combine_path("..", "utf8_test.txt"), utf8_source, ec, 1000000);
	if (ec) fprintf(stderr, "failed to open file: (%d) %s\n", ec.value()
		, ec.message().c_str());
	TEST_CHECK(!ec);

	// test lower level conversions

	// utf8 -> utf16 -> utf32 -> utf8
	{
		std::vector<UTF16> utf16(utf8_source.size());
		UTF8 const* in8 = (UTF8 const*)&utf8_source[0];
		UTF16* out16 = &utf16[0];
		ConversionResult ret = ConvertUTF8toUTF16(&in8, in8 + utf8_source.size()
			, &out16, out16 + utf16.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);

		std::vector<UTF32> utf32(utf8_source.size());
		UTF16 const* in16 = &utf16[0];
		UTF32* out32 = &utf32[0];
		ret = ConvertUTF16toUTF32(&in16, out16
			, &out32, out32 + utf32.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);

		std::vector<UTF8> utf8(utf8_source.size());
		UTF32 const* in32 = &utf32[0];
		UTF8* out8 = &utf8[0];
		ret = ConvertUTF32toUTF8(&in32, out32
			, &out8, out8 + utf8.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		TEST_EQUAL(out8 - &utf8[0], utf8_source.size());
		TEST_CHECK(std::equal(&utf8[0], out8, (UTF8 const*)&utf8_source[0]));
	}

	// utf8 -> utf32 -> utf16 -> utf8
	{
		std::vector<UTF32> utf32(utf8_source.size());
		UTF8 const* in8 = (UTF8 const*)&utf8_source[0];
		UTF32* out32 = &utf32[0];
		ConversionResult ret = ConvertUTF8toUTF32(&in8, in8 + utf8_source.size()
			, &out32, out32 + utf32.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);

		std::vector<UTF16> utf16(utf8_source.size());
		UTF32 const* in32 = &utf32[0];
		UTF16* out16 = &utf16[0];
		ret = ConvertUTF32toUTF16(&in32, out32
			, &out16, out16 + utf16.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);

		std::vector<UTF8> utf8(utf8_source.size());
		UTF16 const* in16 = &utf16[0];
		UTF8* out8 = &utf8[0];
		ret = ConvertUTF16toUTF8(&in16, out16
			, &out8, out8 + utf8.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		TEST_EQUAL(out8 - &utf8[0], utf8_source.size());
		TEST_CHECK(std::equal(&utf8[0], out8, (UTF8 const*)&utf8_source[0]));
	}

	// test higher level conversions

	std::string utf8;
	std::copy(utf8_source.begin(), utf8_source.end(), std::back_inserter(utf8));

	std::wstring wide;
	utf8_conv_result_t ret = utf8_wchar(utf8, wide);
	TEST_EQUAL(ret, conversion_ok);

	std::string identity;
	ret = wchar_utf8(wide, identity);
	TEST_EQUAL(ret, conversion_ok);

	TEST_EQUAL(utf8, identity);
	return 0;
}

<commit_msg>extend utf8 unit test<commit_after>/*

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

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

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

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

*/

#include "test.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"
#include "setup_transfer.hpp" // for load_file
#include "libtorrent/file.hpp" // for combine_path

#include <vector>

using namespace libtorrent;

void verify_transforms(char const* utf8_source, int utf8_source_len = -1)
{
	if (utf8_source_len == -1)
		utf8_source_len = strlen(utf8_source);

	// utf8 -> utf16 -> utf32 -> utf8
	{
		std::vector<UTF16> utf16(utf8_source_len);
		UTF8 const* in8 = (UTF8 const*)utf8_source;
		UTF16* out16 = &utf16[0];
		ConversionResult ret = ConvertUTF8toUTF16(&in8, in8 + utf8_source_len
			, &out16, out16 + utf16.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		std::vector<UTF32> utf32(utf8_source_len);
		UTF16 const* in16 = &utf16[0];
		UTF32* out32 = &utf32[0];
		ret = ConvertUTF16toUTF32(&in16, out16
			, &out32, out32 + utf32.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		std::vector<UTF8> utf8(utf8_source_len);
		UTF32 const* in32 = &utf32[0];
		UTF8* out8 = &utf8[0];
		ret = ConvertUTF32toUTF8(&in32, out32
			, &out8, out8 + utf8.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		TEST_EQUAL(out8 - &utf8[0], utf8_source_len);
		TEST_CHECK(std::equal(&utf8[0], out8, (UTF8 const*)utf8_source));
	}

	// utf8 -> utf32 -> utf16 -> utf8
	{
		std::vector<UTF32> utf32(utf8_source_len);
		UTF8 const* in8 = (UTF8 const*)utf8_source;
		UTF32* out32 = &utf32[0];
		ConversionResult ret = ConvertUTF8toUTF32(&in8, in8 + utf8_source_len
			, &out32, out32 + utf32.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		std::vector<UTF16> utf16(utf8_source_len);
		UTF32 const* in32 = &utf32[0];
		UTF16* out16 = &utf16[0];
		ret = ConvertUTF32toUTF16(&in32, out32
			, &out16, out16 + utf16.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		std::vector<UTF8> utf8(utf8_source_len);
		UTF16 const* in16 = &utf16[0];
		UTF8* out8 = &utf8[0];
		ret = ConvertUTF16toUTF8(&in16, out16
			, &out8, out8 + utf8.size(), strictConversion);

		TEST_EQUAL(ret, conversionOK);
		if (ret != conversionOK && utf8_source_len < 10)
		{
			for (char const* i = utf8_source; *i != 0; ++i)
				fprintf(stderr, "%x ", UTF8(*i));
		}

		TEST_EQUAL(out8 - &utf8[0], utf8_source_len);
		TEST_CHECK(std::equal(&utf8[0], out8, (UTF8 const*)utf8_source));
	}
}

void expect_error(char const* utf8, ConversionResult expect)
{
	UTF8 const* in8 = (UTF8 const*)utf8;
	std::vector<UTF32> utf32(strlen(utf8));
	UTF32* out32 = &utf32[0];
	ConversionResult ret = ConvertUTF8toUTF32(&in8, in8 + strlen(utf8)
		, &out32, out32 + utf32.size(), strictConversion);

	TEST_EQUAL(ret, expect);
	if (ret != expect)
	{
		fprintf(stderr, "%d expected %d\n", ret, expect);
		for (char const* i = utf8; *i != 0; ++i)
			fprintf(stderr, "%x ", UTF8(*i));
	}

	in8 = (UTF8 const*)utf8;
	std::vector<UTF16> utf16(strlen(utf8));
	UTF16* out16 = &utf16[0];
	ret = ConvertUTF8toUTF16(&in8, in8 + strlen(utf8)
		, &out16, out16 + utf16.size(), strictConversion);

	TEST_EQUAL(ret, expect);
	if (ret != expect)
	{
		fprintf(stderr, "%d expected %d\n", ret, expect);
		for (char const* i = utf8; *i != 0; ++i)
			fprintf(stderr, "%x ", UTF8(*i));
	}
}

int test_main()
{
	std::vector<char> utf8_source;
	error_code ec;
	load_file(combine_path("..", "utf8_test.txt"), utf8_source, ec, 1000000);
	if (ec) fprintf(stderr, "failed to open file: (%d) %s\n", ec.value()
		, ec.message().c_str());
	TEST_CHECK(!ec);

	// test lower level conversions

	verify_transforms(&utf8_source[0], utf8_source.size());

	verify_transforms("\xc3\xb0");
	verify_transforms("\xed\x9f\xbf");
	verify_transforms("\xee\x80\x80");
	verify_transforms("\xef\xbf\xbd");
	verify_transforms("\xf4\x8f\xbf\xbf");
	verify_transforms("\xf0\x91\x80\x80\x30");

	// Unexpected continuation bytes
	expect_error("\x80", sourceIllegal);
	expect_error("\xbf", sourceIllegal);

	// Impossible bytes
	// The following two bytes cannot appear in a correct UTF-8 string
	expect_error("\xff", sourceExhausted);
	expect_error("\xfe", sourceExhausted);
	expect_error("\xff\xff\xfe\xfe", sourceExhausted);

	// Examples of an overlong ASCII character
	expect_error("\xc0\xaf", sourceIllegal);
	expect_error("\xe0\x80\xaf", sourceIllegal);
	expect_error("\xf0\x80\x80\xaf", sourceIllegal);
	expect_error("\xf8\x80\x80\x80\xaf ", sourceIllegal);
	expect_error("\xfc\x80\x80\x80\x80\xaf", sourceIllegal);

	// Maximum overlong sequences
	expect_error("\xc1\xbf", sourceIllegal);
	expect_error("\xe0\x9f\xbf", sourceIllegal);
	expect_error("\xf0\x8f\xbf\xbf", sourceIllegal);
	expect_error("\xf8\x87\xbf\xbf\xbf", sourceIllegal);
	expect_error("\xfc\x83\xbf\xbf\xbf\xbf", sourceIllegal);

	// Overlong representation of the NUL character
	expect_error("\xc0\x80", sourceIllegal);
	expect_error("\xe0\x80\x80", sourceIllegal);
	expect_error("\xf0\x80\x80\x80", sourceIllegal);
	expect_error("\xf8\x80\x80\x80\x80", sourceIllegal);
	expect_error("\xfc\x80\x80\x80\x80\x80", sourceIllegal);

	// Single UTF-16 surrogates
	expect_error("\xed\xa0\x80", sourceIllegal);
	expect_error("\xed\xad\xbf", sourceIllegal);
	expect_error("\xed\xae\x80", sourceIllegal);
	expect_error("\xed\xaf\xbf", sourceIllegal);
	expect_error("\xed\xb0\x80", sourceIllegal);
	expect_error("\xed\xbe\x80", sourceIllegal);
	expect_error("\xed\xbf\xbf", sourceIllegal);

	// Paired UTF-16 surrogates
	expect_error("\xed\xa0\x80\xed\xb0\x80", sourceIllegal);
	expect_error("\xed\xa0\x80\xed\xbf\xbf", sourceIllegal);
	expect_error("\xed\xad\xbf\xed\xb0\x80", sourceIllegal);
	expect_error("\xed\xad\xbf\xed\xbf\xbf", sourceIllegal);
	expect_error("\xed\xae\x80\xed\xb0\x80", sourceIllegal);
	expect_error("\xed\xae\x80\xed\xbf\xbf", sourceIllegal);
	expect_error("\xed\xaf\xbf\xed\xb0\x80", sourceIllegal);
	expect_error("\xed\xaf\xbf\xed\xbf\xbf", sourceIllegal);

	// test higher level conversions

	std::string utf8;
	std::copy(utf8_source.begin(), utf8_source.end(), std::back_inserter(utf8));

	std::wstring wide;
	utf8_conv_result_t ret = utf8_wchar(utf8, wide);
	TEST_EQUAL(ret, conversion_ok);

	std::string identity;
	ret = wchar_utf8(wide, identity);
	TEST_EQUAL(ret, conversion_ok);

	TEST_EQUAL(utf8, identity);
	return 0;
}

<|endoftext|>


<commit_before>/*******************************************************************************
**
** Filename   : util
** Created on : 03 April, 2005
** Copyright  : (c) 2005 Till Adam
** Email      : <adam@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.
**
**   It 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
**
**   In addition, as a special exception, the copyright holders give
**   permission to link the code of this program with any edition of
**   the Qt library by Trolltech AS, Norway (or with modified versions
**   of Qt that use the same license as Qt), and distribute linked
**   combinations including the two.  You must obey the GNU General
**   Public License in all respects for all of the code used other than
**   Qt.  If you modify this file, you may extend this exception to
**   your version of the file, but you are not obligated to do so.  If
**   you do not wish to do so, delete this exception statement from
**   your version.
**
*******************************************************************************/

#include "util.h"

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

void KMail::Util::reconnectSignalSlotPair( QObject *src, const char *signal, QObject *dst, const char *slot )
{
  QObject::disconnect( src, signal, dst, slot );
  QObject::connect( src, signal, dst, slot );
}

size_t KMail::Util::crlf2lf( char* str, const size_t strLen )
{
    if ( !str || strLen == 0 )
        return 0;

    const char* source = str;
    const char* sourceEnd = source + strLen;

    // search the first occurrence of "\r\n"
    for ( ; source < sourceEnd - 1; ++source ) {
        if ( *source == '\r' && *( source + 1 ) == '\n' )
            break;
    }

    if ( source == sourceEnd - 1 ) {
        // no "\r\n" found
        return strLen;
    }

    // replace all occurrences of "\r\n" with "\n" (in place)
    char* target = const_cast<char*>( source ); // target points to '\r'
    ++source; // source points to '\n'
    for ( ; source < sourceEnd; ++source ) {
        if ( *source != '\r' || *( source + 1 ) != '\n' )
            * target++ = *source;
    }
    *target = '\0'; // terminate result
    return target - str;
}

QByteArray KMail::Util::lf2crlf( const QByteArray & src )
{
    QByteArray result;
    result.resize( 2*src.size() );  // maximal possible length

    QByteArray::ConstIterator s = src.begin();
    QByteArray::Iterator d = result.begin();
  // we use cPrev to make sure we insert '\r' only there where it is missing
    char cPrev = '?';
    const char* end = src.end();
    while ( s != end ) {
        if ( ('\n' == *s) && ('\r' != cPrev) )
            *d++ = '\r';
        cPrev = *s;
        *d++ = *s++;
    }
    result.truncate( d - result.begin() );
    return result;
}

QByteArray KMail::Util::ByteArray( const DwString& str )
{
  const int strLen = str.size();
  QByteArray arr;
  arr.resize( strLen );
  memcpy( arr.data(), str.data(), strLen );
  return arr;
}

DwString KMail::Util::dwString( const QByteArray& str )
{
  if ( !str.data() ) // DwString doesn't like char*=0
    return DwString();
  return DwString( str.data(), str.size() );
}

bool KMail::Util::checkOverwrite( const KUrl &url, QWidget *w )
{
  if ( KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, w ) ) {
    if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel(
         w,
         i18n( "A file named \"%1\" already exists. "
             "Are you sure you want to overwrite it?", url.prettyUrl() ),
             i18n( "Overwrite File?" ),
                   KStandardGuiItem::overwrite() ) )
      return false;
  }
  return true;
}

#ifdef Q_WS_MACX
#include <QDesktopServices>
#endif

bool KMail::Util::handleUrlOnMac( const KUrl& url )
{
#ifdef Q_WS_MACX
  QDesktopServices::openUrl( url );
  return true;
#else
  Q_UNUSED( url );
  return false;
#endif
}

KMail::Util::RecursionPreventer::RecursionPreventer( int &counter )
  : mCounter( counter )
{
  mCounter++;
}

KMail::Util::RecursionPreventer::~RecursionPreventer()
{
  mCounter--;
}

bool KMail::Util::RecursionPreventer::isRecursive() const
{
  return mCounter > 1;
}<commit_msg>Fix minor krazy issue: source files should end with newlines.<commit_after>/*******************************************************************************
**
** Filename   : util
** Created on : 03 April, 2005
** Copyright  : (c) 2005 Till Adam
** Email      : <adam@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.
**
**   It 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
**
**   In addition, as a special exception, the copyright holders give
**   permission to link the code of this program with any edition of
**   the Qt library by Trolltech AS, Norway (or with modified versions
**   of Qt that use the same license as Qt), and distribute linked
**   combinations including the two.  You must obey the GNU General
**   Public License in all respects for all of the code used other than
**   Qt.  If you modify this file, you may extend this exception to
**   your version of the file, but you are not obligated to do so.  If
**   you do not wish to do so, delete this exception statement from
**   your version.
**
*******************************************************************************/

#include "util.h"

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

void KMail::Util::reconnectSignalSlotPair( QObject *src, const char *signal, QObject *dst, const char *slot )
{
  QObject::disconnect( src, signal, dst, slot );
  QObject::connect( src, signal, dst, slot );
}

size_t KMail::Util::crlf2lf( char* str, const size_t strLen )
{
    if ( !str || strLen == 0 )
        return 0;

    const char* source = str;
    const char* sourceEnd = source + strLen;

    // search the first occurrence of "\r\n"
    for ( ; source < sourceEnd - 1; ++source ) {
        if ( *source == '\r' && *( source + 1 ) == '\n' )
            break;
    }

    if ( source == sourceEnd - 1 ) {
        // no "\r\n" found
        return strLen;
    }

    // replace all occurrences of "\r\n" with "\n" (in place)
    char* target = const_cast<char*>( source ); // target points to '\r'
    ++source; // source points to '\n'
    for ( ; source < sourceEnd; ++source ) {
        if ( *source != '\r' || *( source + 1 ) != '\n' )
            * target++ = *source;
    }
    *target = '\0'; // terminate result
    return target - str;
}

QByteArray KMail::Util::lf2crlf( const QByteArray & src )
{
    QByteArray result;
    result.resize( 2*src.size() );  // maximal possible length

    QByteArray::ConstIterator s = src.begin();
    QByteArray::Iterator d = result.begin();
  // we use cPrev to make sure we insert '\r' only there where it is missing
    char cPrev = '?';
    const char* end = src.end();
    while ( s != end ) {
        if ( ('\n' == *s) && ('\r' != cPrev) )
            *d++ = '\r';
        cPrev = *s;
        *d++ = *s++;
    }
    result.truncate( d - result.begin() );
    return result;
}

QByteArray KMail::Util::ByteArray( const DwString& str )
{
  const int strLen = str.size();
  QByteArray arr;
  arr.resize( strLen );
  memcpy( arr.data(), str.data(), strLen );
  return arr;
}

DwString KMail::Util::dwString( const QByteArray& str )
{
  if ( !str.data() ) // DwString doesn't like char*=0
    return DwString();
  return DwString( str.data(), str.size() );
}

bool KMail::Util::checkOverwrite( const KUrl &url, QWidget *w )
{
  if ( KIO::NetAccess::exists( url, KIO::NetAccess::DestinationSide, w ) ) {
    if ( KMessageBox::Cancel == KMessageBox::warningContinueCancel(
         w,
         i18n( "A file named \"%1\" already exists. "
             "Are you sure you want to overwrite it?", url.prettyUrl() ),
             i18n( "Overwrite File?" ),
                   KStandardGuiItem::overwrite() ) )
      return false;
  }
  return true;
}

#ifdef Q_WS_MACX
#include <QDesktopServices>
#endif

bool KMail::Util::handleUrlOnMac( const KUrl& url )
{
#ifdef Q_WS_MACX
  QDesktopServices::openUrl( url );
  return true;
#else
  Q_UNUSED( url );
  return false;
#endif
}

KMail::Util::RecursionPreventer::RecursionPreventer( int &counter )
  : mCounter( counter )
{
  mCounter++;
}

KMail::Util::RecursionPreventer::~RecursionPreventer()
{
  mCounter--;
}

bool KMail::Util::RecursionPreventer::isRecursive() const
{
  return mCounter > 1;
}

<|endoftext|>


<commit_before>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \authors
  \authors     (lord.tiran@gmail.com)
  \authors     (rdo@rk9.bmstu.ru)
  \date      13.12.2009
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <stdio.h>
#define BOOST_TEST_MODULE RDORuntime_Array_Test
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_value.h"
#include "simulator/runtime/rdo_array.h"
#include "simulator/runtime/rdo_type.h"
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDORuntime_Array_Test)

typedef  rdo::vector<rsint>                                            Container;
typedef  std::pair<rdoRuntime::LPRDOArrayValue, rdoRuntime::RDOValue>  Array;

Array createArray(CREF(Container) data)
{
	rdoRuntime::LPRDOArrayType  pType  = rdo::Factory<rdoRuntime::RDOArrayType>::create(rdoRuntime::g_int);
	ASSERT(pType);
	rdoRuntime::LPRDOArrayValue pValue = rdo::Factory<rdoRuntime::RDOArrayValue>::create(pType);
	ASSERT(pValue);

	STL_FOR_ALL_CONST(data, it)
	{
		pValue->push_back(rdoRuntime::RDOValue(*it));
	}

	return std::make_pair(pValue, rdoRuntime::RDOValue(pType, pValue));
}

tstring getString(CREF(rdoRuntime::LPRDOArrayValue) pArray, CREF(rdoRuntime::LPRDOArrayIterator) pIt)
{
	if (!pIt->equal(pArray->end()))
	{
		return pIt->getValue().getAsString();
	}
	return _T("");
}

tstring getString(CREF(rdoRuntime::RDOValue) it, CREF(rdoRuntime::RDOValue) end)
{
	if (it != end)
	{
		return it.getAsString();
	}
	return _T("");
}

BOOST_AUTO_TEST_CASE(ArrayTestCreate)
{
	BOOST_CHECK(createArray(Container()(1)(2)(3)).second.getAsString() == _T("[1, 2, 3]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestInsert)
{
	Array array1 = createArray(Container()(1)(2)(3));
	Array array2 = createArray(Container()(4)(5)(6));

	array1.first->insert(array1.first->begin()->next(), array2.first->begin(), array2.first->end());

	BOOST_CHECK(array1.second.getAsString() == _T("[1, 4, 5, 6, 2, 3]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestErase)
{
	Array array = createArray(Container()(1)(2)(3));

	array.first->erase(array.first->begin()->next(), array.first->begin()->preInc(3));

	BOOST_CHECK(array.second.getAsString() == _T("[1]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPrePlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->begin();
	while (!pIt->equal(array.first->end()))
	{
		result += getString(array.first, pIt->preInc(1));
	}
	BOOST_CHECK(result == _T("23"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPostPlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->begin();
	while (!pIt->equal(array.first->end()))
	{
		result += getString(array.first, pIt->postInc(1));
	}
	BOOST_CHECK(result == _T("123"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPreMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->end();
	do
	{
		result += getString(array.first, pIt->preInc(-1));
	}
	while (!pIt->equal(array.first->begin()));

	BOOST_CHECK(result == _T("321"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPostMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->end();
	do
	{
		result += getString(array.first, pIt->postInc(-1));
	}
	while (!pIt->equal(array.first->begin()));

	BOOST_CHECK(result == _T("32"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePrePlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt  = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd = array.first->end  ();
	rdoRuntime::RDOValue it (pIt,  pIt );
	rdoRuntime::RDOValue end(pEnd, pEnd);
	BOOST_CHECK(it != end);

	while (it != end)
	{
		result += getString(++it, end);
	}
	BOOST_CHECK(result == _T("23"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePostPlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt  = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd = array.first->end  ();
	rdoRuntime::RDOValue it (pIt,  pIt );
	rdoRuntime::RDOValue end(pEnd, pEnd);
	BOOST_CHECK(it != end);

	while (it != end)
	{
		result += getString(it++, end);
	}
	BOOST_CHECK(result == _T("123"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePreMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt    = array.first->end  ();
	rdoRuntime::LPRDOArrayIterator pBegin = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd   = array.first->end  ();
	rdoRuntime::RDOValue it   (pIt,    pIt   );
	rdoRuntime::RDOValue begin(pBegin, pBegin);
	rdoRuntime::RDOValue end  (pEnd,   pEnd  );
	BOOST_CHECK(it != begin);
	BOOST_CHECK(it == end  );

	do
	{
		result += getString(--it, end);
	}
	while (it != begin);
	BOOST_CHECK(result == _T("321"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePostMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt    = array.first->end  ();
	rdoRuntime::LPRDOArrayIterator pBegin = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd   = array.first->end  ();
	rdoRuntime::RDOValue it   (pIt,    pIt   );
	rdoRuntime::RDOValue begin(pBegin, pBegin);
	rdoRuntime::RDOValue end  (pEnd,   pEnd  );
	BOOST_CHECK(it != begin);
	BOOST_CHECK(it == end  );

	do
	{
		result += getString(it--, end);
	}
	while (it != begin);
	BOOST_CHECK(result == _T("32"));
}

BOOST_AUTO_TEST_CASE(ArrayTestSetItem)
{
	Array array = createArray(Container()(1)(2)(3));
	rdoRuntime::LPRDORuntime pRuntime = rdo::Factory<rdoRuntime::RDORuntime>::create();

	ruint ind = 1;
	ruint item = 48;
	rdoRuntime::RDOValue index (ind);
	rdoRuntime::RDOValue value (item);
	array.first->setItem(index, value);

	BOOST_CHECK(array.second.getAsString() == _T("[1, 48, 3]"));

	ind = 3;
	index = ind;
	rbool found = false;

	try
	{
		array.first->setItem(index, value);
	}
	catch (rdoRuntime::RDORuntimeException ex)
	{
		if (! ex.message().empty())
		{
			found = ex.message() == _T("   ");
		}
	}

	if (!found)
		BOOST_CHECK(false);
}

BOOST_AUTO_TEST_CASE(ArrayTestGetItem)
{
	Array array = createArray(Container()(1)(48)(3));
	rdoRuntime::LPRDORuntime pRuntime = rdo::Factory<rdoRuntime::RDORuntime>::create();

	ruint ind = 1;
	rdoRuntime::RDOValue index (ind);
	rdoRuntime::RDOValue value (array.first->getItem(index));

	BOOST_CHECK(value.getAsString() == _T("48"));

	ind = 3;
	index = ind;
	rbool found = false;

	try
	{
		array.first->getItem(index);
	}
	catch (rdoRuntime::RDORuntimeException ex)
	{
		if (! ex.message().empty())
		{
			found = ex.message() == _T("   ");
		}
	}

	if (!found)
		BOOST_CHECK(false);
}
BOOST_AUTO_TEST_SUITE_END() // RDORuntime_Array_Test
<commit_msg> - использование CREF  - форматирование<commit_after>/*!
  \copyright (c) RDO-Team, 2011
  \file      main.cpp
  \authors
  \authors     (lord.tiran@gmail.com)
  \authors     (rdo@rk9.bmstu.ru)
  \date      13.12.2009
  \brief
  \indent    4T
*/

// ---------------------------------------------------------------------------- PCH
// ----------------------------------------------------------------------- INCLUDES
#include <iostream>
#include <stdio.h>
#define BOOST_TEST_MODULE RDORuntime_Array_Test
#include <boost/test/included/unit_test.hpp>
// ----------------------------------------------------------------------- SYNOPSIS
#include "simulator/runtime/rdo_value.h"
#include "simulator/runtime/rdo_array.h"
#include "simulator/runtime/rdo_type.h"
// --------------------------------------------------------------------------------

BOOST_AUTO_TEST_SUITE(RDORuntime_Array_Test)

typedef  rdo::vector<rsint>                                            Container;
typedef  std::pair<rdoRuntime::LPRDOArrayValue, rdoRuntime::RDOValue>  Array;

Array createArray(CREF(Container) data)
{
	rdoRuntime::LPRDOArrayType  pType  = rdo::Factory<rdoRuntime::RDOArrayType>::create(rdoRuntime::g_int);
	ASSERT(pType);
	rdoRuntime::LPRDOArrayValue pValue = rdo::Factory<rdoRuntime::RDOArrayValue>::create(pType);
	ASSERT(pValue);

	STL_FOR_ALL_CONST(data, it)
	{
		pValue->push_back(rdoRuntime::RDOValue(*it));
	}

	return std::make_pair(pValue, rdoRuntime::RDOValue(pType, pValue));
}

tstring getString(CREF(rdoRuntime::LPRDOArrayValue) pArray, CREF(rdoRuntime::LPRDOArrayIterator) pIt)
{
	if (!pIt->equal(pArray->end()))
	{
		return pIt->getValue().getAsString();
	}
	return _T("");
}

tstring getString(CREF(rdoRuntime::RDOValue) it, CREF(rdoRuntime::RDOValue) end)
{
	if (it != end)
	{
		return it.getAsString();
	}
	return _T("");
}

BOOST_AUTO_TEST_CASE(ArrayTestCreate)
{
	BOOST_CHECK(createArray(Container()(1)(2)(3)).second.getAsString() == _T("[1, 2, 3]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestInsert)
{
	Array array1 = createArray(Container()(1)(2)(3));
	Array array2 = createArray(Container()(4)(5)(6));

	array1.first->insert(array1.first->begin()->next(), array2.first->begin(), array2.first->end());

	BOOST_CHECK(array1.second.getAsString() == _T("[1, 4, 5, 6, 2, 3]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestErase)
{
	Array array = createArray(Container()(1)(2)(3));

	array.first->erase(array.first->begin()->next(), array.first->begin()->preInc(3));

	BOOST_CHECK(array.second.getAsString() == _T("[1]"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPrePlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->begin();
	while (!pIt->equal(array.first->end()))
	{
		result += getString(array.first, pIt->preInc(1));
	}
	BOOST_CHECK(result == _T("23"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPostPlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->begin();
	while (!pIt->equal(array.first->end()))
	{
		result += getString(array.first, pIt->postInc(1));
	}
	BOOST_CHECK(result == _T("123"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPreMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->end();
	do
	{
		result += getString(array.first, pIt->preInc(-1));
	}
	while (!pIt->equal(array.first->begin()));

	BOOST_CHECK(result == _T("321"));
}

BOOST_AUTO_TEST_CASE(ArrayTestIteratorPostMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt = array.first->end();
	do
	{
		result += getString(array.first, pIt->postInc(-1));
	}
	while (!pIt->equal(array.first->begin()));

	BOOST_CHECK(result == _T("32"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePrePlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt  = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd = array.first->end  ();
	rdoRuntime::RDOValue it (pIt,  pIt );
	rdoRuntime::RDOValue end(pEnd, pEnd);
	BOOST_CHECK(it != end);

	while (it != end)
	{
		result += getString(++it, end);
	}
	BOOST_CHECK(result == _T("23"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePostPlus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt  = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd = array.first->end  ();
	rdoRuntime::RDOValue it (pIt,  pIt );
	rdoRuntime::RDOValue end(pEnd, pEnd);
	BOOST_CHECK(it != end);

	while (it != end)
	{
		result += getString(it++, end);
	}
	BOOST_CHECK(result == _T("123"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePreMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt    = array.first->end  ();
	rdoRuntime::LPRDOArrayIterator pBegin = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd   = array.first->end  ();
	rdoRuntime::RDOValue it   (pIt,    pIt   );
	rdoRuntime::RDOValue begin(pBegin, pBegin);
	rdoRuntime::RDOValue end  (pEnd,   pEnd  );
	BOOST_CHECK(it != begin);
	BOOST_CHECK(it == end  );

	do
	{
		result += getString(--it, end);
	}
	while (it != begin);
	BOOST_CHECK(result == _T("321"));
}

BOOST_AUTO_TEST_CASE(ArrayTestValuePostMinus)
{
	Array array = createArray(Container()(1)(2)(3));

	tstring result;
	rdoRuntime::LPRDOArrayIterator pIt    = array.first->end  ();
	rdoRuntime::LPRDOArrayIterator pBegin = array.first->begin();
	rdoRuntime::LPRDOArrayIterator pEnd   = array.first->end  ();
	rdoRuntime::RDOValue it   (pIt,    pIt   );
	rdoRuntime::RDOValue begin(pBegin, pBegin);
	rdoRuntime::RDOValue end  (pEnd,   pEnd  );
	BOOST_CHECK(it != begin);
	BOOST_CHECK(it == end  );

	do
	{
		result += getString(it--, end);
	}
	while (it != begin);
	BOOST_CHECK(result == _T("32"));
}

BOOST_AUTO_TEST_CASE(ArrayTestSetItem)
{
	Array array = createArray(Container()(1)(2)(3));
	rdoRuntime::LPRDORuntime pRuntime = rdo::Factory<rdoRuntime::RDORuntime>::create();

	ruint ind  = 1;
	ruint item = 48;
	rdoRuntime::RDOValue index(ind);
	rdoRuntime::RDOValue value(item);
	array.first->setItem(index, value);

	BOOST_CHECK(array.second.getAsString() == _T("[1, 48, 3]"));

	ind         = 3;
	index       = ind;
	rbool found = false;

	try
	{
		array.first->setItem(index, value);
	}
	catch (CREF(rdoRuntime::RDORuntimeException) ex)
	{
		if (!ex.message().empty())
		{
			found = ex.message() == _T("   ");
		}
	}

	if (!found)
	{
		BOOST_CHECK(false);
	}
}

BOOST_AUTO_TEST_CASE(ArrayTestGetItem)
{
	Array array = createArray(Container()(1)(48)(3));
	rdoRuntime::LPRDORuntime pRuntime = rdo::Factory<rdoRuntime::RDORuntime>::create();

	ruint ind = 1;
	rdoRuntime::RDOValue index(ind);
	rdoRuntime::RDOValue value(array.first->getItem(index));

	BOOST_CHECK(value.getAsString() == _T("48"));

	ind         = 3;
	index       = ind;
	rbool found = false;

	try
	{
		array.first->getItem(index);
	}
	catch (CREF(rdoRuntime::RDORuntimeException) ex)
	{
		if (!ex.message().empty())
		{
			found = ex.message() == _T("   ");
		}
	}

	if (!found)
	{
		BOOST_CHECK(false);
	}
}
BOOST_AUTO_TEST_SUITE_END() // RDORuntime_Array_Test
<|endoftext|>


<commit_before><commit_msg>coverity#705153 Missing break in switch, surely this is not intentional<commit_after><|endoftext|>