<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: salsession.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-24 10:01:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _VCL_SALSESSION_HXX
#define _VCL_SALSESSION_HXX

#ifndef _VCL_DLLAPI_H
#include "vcl/dllapi.h"
#endif

enum SalSessionEventType
{
    Interaction,
    SaveRequest,
    ShutdownCancel
};

struct SalSessionEvent
{
    SalSessionEventType         m_eType;

    SalSessionEvent( SalSessionEventType eType )
            : m_eType( eType )
    {}
};

struct SalSessionInteractionEvent : public SalSessionEvent
{
    bool                        m_bInteractionGranted;

    SalSessionInteractionEvent( bool bGranted )
            : SalSessionEvent( Interaction ),
              m_bInteractionGranted( bGranted )
    {}
};

struct SalSessionSaveRequestEvent : public SalSessionEvent
{
    bool                        m_bShutdown;
    bool                        m_bCancelable;

    SalSessionSaveRequestEvent( bool bShutdown, bool bCancelable )
            : SalSessionEvent( SaveRequest ),
              m_bShutdown( bShutdown ),
              m_bCancelable( bCancelable )
    {}
};

struct SalSessionShutdownCancelEvent : public SalSessionEvent
{
    SalSessionShutdownCancelEvent()
            : SalSessionEvent( ShutdownCancel )
    {}
};

typedef void(*SessionProc)( SalSessionEvent *pEvent);

class VCL_DLLPUBLIC SalSession
{
    SessionProc         m_aProc;
public:
    SalSession()
            : m_aProc( 0 )
    {}
    virtual ~SalSession();

    void SetCallback( SessionProc aCallback )
    {
        m_aProc = aCallback;
    }
    void CallCallback( SalSessionEvent* pEvent )
    {
        if( m_aProc )
            m_aProc( pEvent );
    }

    // query the session manager for a user interaction slot
    virtual void queryInteraction() = 0;
    // signal the session manager that we're done with user interaction
    virtual void interactionDone() = 0;
    // signal that we're done saving
    virtual void saveDone() = 0;
    // try to cancel the sutdown in progress
    virtual bool cancelShutdown() = 0;
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.2.224); FILE MERGED 2008/04/01 13:01:15 thb 1.2.224.2: #i85898# Stripping all external header guards 2008/03/28 15:44:17 rt 1.2.224.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: salsession.hxx,v $
 * $Revision: 1.3 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _VCL_SALSESSION_HXX
#define _VCL_SALSESSION_HXX

#include "vcl/dllapi.h"

enum SalSessionEventType
{
    Interaction,
    SaveRequest,
    ShutdownCancel
};

struct SalSessionEvent
{
    SalSessionEventType         m_eType;

    SalSessionEvent( SalSessionEventType eType )
            : m_eType( eType )
    {}
};

struct SalSessionInteractionEvent : public SalSessionEvent
{
    bool                        m_bInteractionGranted;

    SalSessionInteractionEvent( bool bGranted )
            : SalSessionEvent( Interaction ),
              m_bInteractionGranted( bGranted )
    {}
};

struct SalSessionSaveRequestEvent : public SalSessionEvent
{
    bool                        m_bShutdown;
    bool                        m_bCancelable;

    SalSessionSaveRequestEvent( bool bShutdown, bool bCancelable )
            : SalSessionEvent( SaveRequest ),
              m_bShutdown( bShutdown ),
              m_bCancelable( bCancelable )
    {}
};

struct SalSessionShutdownCancelEvent : public SalSessionEvent
{
    SalSessionShutdownCancelEvent()
            : SalSessionEvent( ShutdownCancel )
    {}
};

typedef void(*SessionProc)( SalSessionEvent *pEvent);

class VCL_DLLPUBLIC SalSession
{
    SessionProc         m_aProc;
public:
    SalSession()
            : m_aProc( 0 )
    {}
    virtual ~SalSession();

    void SetCallback( SessionProc aCallback )
    {
        m_aProc = aCallback;
    }
    void CallCallback( SalSessionEvent* pEvent )
    {
        if( m_aProc )
            m_aProc( pEvent );
    }

    // query the session manager for a user interaction slot
    virtual void queryInteraction() = 0;
    // signal the session manager that we're done with user interaction
    virtual void interactionDone() = 0;
    // signal that we're done saving
    virtual void saveDone() = 0;
    // try to cancel the sutdown in progress
    virtual bool cancelShutdown() = 0;
};

#endif
<|endoftext|>


<commit_before>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/test/test_suite.h"
#include "base/test/test_switches.h"
#include "remoting/test/refresh_token_store.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace switches {
const char kSingleProcessTestsSwitchName[] = "single-process-tests";
const char kUserNameSwitchName[] = "username";
const char kHostNameSwitchName[] = "hostname";
const char kRefreshTokenPathSwitchName[] = "refresh-token-path";
}

int main(int argc, char* argv[]) {
  testing::InitGoogleTest(&argc, argv);
  base::TestSuite test_suite(argc, argv);

  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  DCHECK(command_line);

  // Do not retry if tests fails.
  command_line->AppendSwitchASCII(switches::kTestLauncherRetryLimit, "0");

  // Different tests may require access to the same host if run in parallel.
  // To avoid shared resource contention, tests will be run one at a time.
  command_line->AppendSwitch(switches::kSingleProcessTestsSwitchName);

  // The username is used to run the tests and determines which refresh token to
  // select in the refresh token file.
  std::string username =
      command_line->GetSwitchValueASCII(switches::kUserNameSwitchName);

  if (username.empty()) {
    LOG(ERROR) << "No username passed in, can't authenticate or run tests!";
    return -1;
  }
  DVLOG(1) << "Running chromoting tests as: " << username;

  base::FilePath refresh_token_path =
     command_line->GetSwitchValuePath(switches::kRefreshTokenPathSwitchName);

  // The hostname determines which host to initiate a session with from the list
  // returned from the Directory service.
  std::string hostname =
      command_line->GetSwitchValueASCII(switches::kHostNameSwitchName);

  if (hostname.empty()) {
    LOG(ERROR) << "No hostname passed in, connect to host requires hostname!";
    return -1;
  }
  DVLOG(1) << "Chromoting tests will connect to: " << hostname;

  // TODO(TonyChun): Move this logic into a shared environment class.
  scoped_ptr<remoting::test::RefreshTokenStore> refresh_token_store =
      remoting::test::RefreshTokenStore::OnDisk(username, refresh_token_path);

  std::string refresh_token = refresh_token_store->FetchRefreshToken();

  if (refresh_token.empty()) {
    // RefreshTokenStore already logs which specific error occured.
    return -1;
  }

  return 0;
}
<commit_msg>Retrieve access token, --help print, and auth_code functionality implemented.<commit_after>// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_suite.h"
#include "base/test/test_switches.h"
#include "google_apis/google_api_keys.h"
#include "net/base/escape.h"
#include "remoting/test/access_token_fetcher.h"
#include "remoting/test/refresh_token_store.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace switches {
const char kAuthCodeSwitchName[] = "authcode";
const char kHelpSwitchName[] = "help";
const char kHostNameSwitchName[] = "hostname";
const char kLoggingLevelSwitchName[] = "verbosity";
const char kRefreshTokenPathSwitchName[] = "refresh-token-path";
const char kSingleProcessTestsSwitchName[] = "single-process-tests";
const char kUserNameSwitchName[] = "username";
}

namespace {
const char kChromotingAuthScopeValues[] =
    "https://www.googleapis.com/auth/chromoting "
    "https://www.googleapis.com/auth/googletalk "
    "https://www.googleapis.com/auth/userinfo.email";

std::string GetAuthorizationCodeUri() {
  // Replace space characters with a '+' sign when formatting.
  bool use_plus = true;
  return base::StringPrintf(
      "https://accounts.google.com/o/oauth2/auth"
      "?scope=%s"
      "&redirect_uri=https://chromoting-oauth.talkgadget.google.com/"
      "talkgadget/oauth/chrome-remote-desktop/dev"
      "&response_type=code"
      "&client_id=%s"
      "&access_type=offline"
      "&approval_prompt=force",
      net::EscapeUrlEncodedData(kChromotingAuthScopeValues, use_plus).c_str(),
      net::EscapeUrlEncodedData(
          google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING),
          use_plus).c_str());
}

void PrintUsage() {
  printf("\n************************************\n");
  printf("*** Chromoting Test Driver Usage ***\n");
  printf("************************************\n");

  printf("\nUsage:\n");
  printf("  chromoting_test_driver --username=<example@gmail.com> [options]\n");
  printf("\nRequired Parameters:\n");
  printf("  %s: Specifies which account to use when running tests\n",
         switches::kUserNameSwitchName);
  printf("\nOptional Parameters:\n");
  printf("  %s: Exchanged for a refresh and access token for authentication\n",
         switches::kAuthCodeSwitchName);
  printf("  %s: Path to a JSON file containing username/refresh_token KVPs\n",
         switches::kRefreshTokenPathSwitchName);
  printf("  %s: Displays additional usage information\n",
         switches::kHelpSwitchName);
}

void PrintAuthCodeInfo() {
  printf("\n*******************************\n");
  printf("*** Auth Code Example Usage ***\n");
  printf("*******************************\n\n");

  printf("If this is the first time you are running the tool,\n");
  printf("you will need to provide an authorization code.\n");
  printf("This code will be exchanged for a long term refresh token which\n");
  printf("will be stored locally and used to acquire a short lived access\n");
  printf("token to connect to the remoting service apis and establish a\n");
  printf("remote host connection.\n\n");

  printf("Note: You may need to repeat this step if the stored refresh token");
  printf("\n      has been revoked or expired.\n");
  printf("      Passing in the same auth code twice will result in an error\n");

  printf(
      "\nFollow these steps to produce an auth code:\n"
      " - Open the Authorization URL link shown below in your browser\n"
      " - Approve the requested permissions for the tool\n"
      " - Copy the 'code' value in the redirected URL\n"
      " - Run the tool and pass in copied auth code as a parameter\n");

  printf("\nAuthorization URL:\n");
  printf("%s\n", GetAuthorizationCodeUri().c_str());

  printf("\nRedirected URL Example:\n");
  printf(
      "https://chromoting-oauth.talkgadget.google.com/talkgadget/oauth/"
      "chrome-remote-desktop/dev?code=4/AKtf...\n");

  printf("\nTool usage example with the newly created auth code:\n");
  printf("chromoting_test_driver --%s=example@gmail.com --%s=4/AKtf...\n\n",
         switches::kUserNameSwitchName, switches::kAuthCodeSwitchName);
}

void PrintJsonFileInfo() {
  printf("\n****************************************\n");
  printf("*** Refresh Token File Example Usage ***\n");
  printf("****************************************\n\n");

  printf("In order to use this option, a valid JSON file must exist, be\n");
  printf("properly formatted, and contain a username/token KVP.\n");
  printf("Contents of example_file.json\n");
  printf("{\n");
  printf("  \"username1@fauxdomain.com\": \"1/3798Gsdf898shksdvfyi8sshad\",\n");
  printf("  \"username2@fauxdomain.com\": \"1/8974sdf87asdgadfgaerhfRsAa\",\n");
  printf("}\n\n");

  printf("\nTool usage example:\n");
  printf("chromoting_test_driver --%s=%s --%s=./example_file.json\n\n",
         switches::kUserNameSwitchName, "username1@fauxdomain.com",
         switches::kRefreshTokenPathSwitchName);
}

} // namespace

void OnAccessTokenRetrieved(
    base::Closure done_closure,
    const std::string& access_token,
    const std::string& refresh_token) {

  DVLOG(1) << "OnAccessTokenRetrieved() Called";

  DVLOG(1) << "Access Token: " << access_token;

  done_closure.Run();
}

int main(int argc, char* argv[]) {
  testing::InitGoogleTest(&argc, argv);
  base::TestSuite test_suite(argc, argv);

  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  DCHECK(command_line);

  // Do not retry if tests fails.
  command_line->AppendSwitchASCII(switches::kTestLauncherRetryLimit, "0");

  // Different tests may require access to the same host if run in parallel.
  // To avoid shared resource contention, tests will be run one at a time.
  command_line->AppendSwitch(switches::kSingleProcessTestsSwitchName);

  if (command_line->HasSwitch(switches::kHelpSwitchName)) {
    PrintUsage();
    PrintJsonFileInfo();
    PrintAuthCodeInfo();
    return 0;
  }

  // Update the logging verbosity level is user specified one.
  std::string verbosity_level(
      command_line->GetSwitchValueASCII(switches::kLoggingLevelSwitchName));
  if (!verbosity_level.empty()) {
    // Turn on logging for the test_driver and remoting components.
    // This switch is parsed during logging::InitLogging.
    command_line->AppendSwitchASCII("vmodule",
                                    "*/remoting/*=" + verbosity_level);
    logging::LoggingSettings logging_settings;
    logging::InitLogging(logging_settings);
  }

  // The username is used to run the tests and determines which refresh token to
  // select in the refresh token file.
  std::string username =
      command_line->GetSwitchValueASCII(switches::kUserNameSwitchName);

  if (username.empty()) {
    LOG(ERROR) << "No username passed in, can't authenticate or run tests!";
    return -1;
  }
  DVLOG(1) << "Running chromoting tests as: " << username;

  // Check to see if the user passed in a one time use auth_code for
  // refreshing their credentials.
  std::string auth_code =
      command_line->GetSwitchValueASCII(switches::kAuthCodeSwitchName);

  base::FilePath refresh_token_path =
     command_line->GetSwitchValuePath(switches::kRefreshTokenPathSwitchName);

  // The hostname determines which host to initiate a session with from the list
  // returned from the Directory service.
  std::string hostname =
      command_line->GetSwitchValueASCII(switches::kHostNameSwitchName);

  if (hostname.empty()) {
    LOG(ERROR) << "No hostname passed in, connect to host requires hostname!";
    return -1;
  }
  DVLOG(1) << "Chromoting tests will connect to: " << hostname;

  // TODO(TonyChun): Move this logic into a shared environment class.
  scoped_ptr<remoting::test::RefreshTokenStore> refresh_token_store =
      remoting::test::RefreshTokenStore::OnDisk(username, refresh_token_path);

  std::string refresh_token = refresh_token_store->FetchRefreshToken();
  if (auth_code.empty() && refresh_token.empty()) {
    // RefreshTokenStore already logs which specific error occured.
    return -1;
  }

  // Used for running network request tasks.
  // TODO(TonyChun): Move this logic into a shared environment class.
  base::MessageLoopForIO message_loop;

  // Uses the refresh token to get the access token from GAIA.
  remoting::test::AccessTokenFetcher access_token_fetcher;

  base::RunLoop run_loop;

  remoting::test::AccessTokenCallback access_token_callback =
      base::Bind(&OnAccessTokenRetrieved, run_loop.QuitClosure());

  if (!auth_code.empty()) {
    access_token_fetcher.GetAccessTokenFromAuthCode(auth_code,
                                                    access_token_callback);
  } else {
    DCHECK(!refresh_token.empty());
    access_token_fetcher.GetAccessTokenFromRefreshToken(refresh_token,
                                                        access_token_callback);
  }

  run_loop.Run();

  return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
using namespace std;
//Enum where the 4th number has the value of 5
enum{zero, one, two, three, five = 5, six};

int main(){
	//Pringting the different values
	cout << "The first value is " << zero << endl
		 << "The second value is " << one << endl
		 << "The third values is " << two << endl
		 << "The fourth value is " << three << endl
		 << "The fifth value is " << five << endl
		 << "The sixth value is " << six << endl;

}
<commit_msg>Update S8_Enumerated_Types.cpp<commit_after>//
//  Program Name - S8_Enumerated_Types.cpp
//  Series: GetOnToC++ Step: 8
//
//  Purpose: This program illustrates how to change the values of enumerated types
//
//  Compile: g++ S8_Enumerated_Types.cpp -o S8_Enumerated_Types
//  Execute: ./S8_Enumerated_Types
//
//  Created by Narayan Mahadevan on 18/08/13.
//
#include <iostream>
using namespace std;
//Enum where the 4th number has the value of 5
enum{zero, one, two, three, five = 5, six};

int main(){
	//Pringting the different values
	cout << "The first value is " << zero << endl
		 << "The second value is " << one << endl
		 << "The third values is " << two << endl
		 << "The fourth value is " << three << endl
		 << "The fifth value is " << five << endl
		 << "The sixth value is " << six << endl;

}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2004 by Stanislav Karchebny                             *
 *   Stanislav.Karchebny@kdemail.net                                       *
 *                                                                         *
 *   Licensed under GPL.                                                   *
 ***************************************************************************/

#include "app.h"
#include "akregator.h"
#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>

static const char description[] =
    I18N_NOOP("A KDE RSS Aggregator");

static const char version[] = "1.0-beta2 \"Beineri\"";

static KCmdLineOptions options[] =
{
    { "+[URL]", I18N_NOOP( "Document to open." ), 0 },
    KCmdLineLastOption
};

int main(int argc, char **argv)
{
    KAboutData about("akregator", I18N_NOOP("aKregator"), version, description,
                     KAboutData::License_GPL, "(C) 2004 Stanislav Karchebny", 0,
                     "http://akregator.upnet.ru/");
    about.addAuthor( "Stanislav Karchebny", I18N_NOOP("Author, Developer, Maintainer"), "Stanislav.Karchebny@kdemail.net" );
    about.addAuthor( "Sashmit Bhaduri", I18N_NOOP("Developer"), "smt@vfemail.net" );
    about.addAuthor( "Teemu Rytilahti", I18N_NOOP("Contributor"), "teemu.rytilahti @kde-fi.org" );
    about.addAuthor( "Stephan Binner", I18N_NOOP("Contributor"), "binner@kde.org" );
    about.addAuthor( "Frank Osterfeld", I18N_NOOP("Contributor"), "f_osterf@informatik.uni-kl.de" );
    about.addAuthor( "Gary Cramblitt", I18N_NOOP("Contributor"), "garycramblitt@comcast.net");
    about.addCredit( "Pierre Habouzit", I18N_NOOP("Debian Packages"), "pierre.habouzit@m4x.org" );
    about.addCredit( "Philipp Droessler", I18N_NOOP("Gentoo Ebuild"), "kingmob@albert-unser.net");
    about.addCredit( "Frerich Raabe", I18N_NOOP("Author of librss"), "raabe@kde.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineArgs::addCmdLineOptions( options );
    aKregatorApp app;

    // see if we are starting with session management
    if (app.isRestored())
    {
        RESTORE(aKregator);
    }
    else
    {
        aKregator *widget;
        // no session.. just start up normally
        KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

        if ( args->count() == 0 )
        {
            widget = new aKregator;
            if(!widget->loadPart()) return 1;
            widget->loadLastOpenFile();
            app.setHaveWindowLoaded(true);
            widget->show();
        }
        else
        {
            int i = 0;
            for (; i < args->count(); i++ )
            {
                widget = new aKregator;
                if(!widget->loadPart()) return 1;
                app.setHaveWindowLoaded(true);
                widget->show();
                widget->load( args->url( i ) );
            }
        }
        args->clear();
    }

    return app.exec();
}
<commit_msg>Fixed my e-mail and added settings_general.[h|cpp] into .cvsignore<commit_after>/***************************************************************************
 *   Copyright (C) 2004 by Stanislav Karchebny                             *
 *   Stanislav.Karchebny@kdemail.net                                       *
 *                                                                         *
 *   Licensed under GPL.                                                   *
 ***************************************************************************/

#include "app.h"
#include "akregator.h"
#include <kapplication.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <klocale.h>

static const char description[] =
    I18N_NOOP("A KDE RSS Aggregator");

static const char version[] = "1.0-beta2 \"Beineri\"";

static KCmdLineOptions options[] =
{
    { "+[URL]", I18N_NOOP( "Document to open." ), 0 },
    KCmdLineLastOption
};

int main(int argc, char **argv)
{
    KAboutData about("akregator", I18N_NOOP("aKregator"), version, description,
                     KAboutData::License_GPL, "(C) 2004 Stanislav Karchebny", 0,
                     "http://akregator.upnet.ru/");
    about.addAuthor( "Stanislav Karchebny", I18N_NOOP("Author, Developer, Maintainer"), "Stanislav.Karchebny@kdemail.net" );
    about.addAuthor( "Sashmit Bhaduri", I18N_NOOP("Developer"), "smt@vfemail.net" );
    about.addAuthor( "Teemu Rytilahti", I18N_NOOP("Contributor"), "teemu.rytilahti@kde-fi.org" );
    about.addAuthor( "Stephan Binner", I18N_NOOP("Contributor"), "binner@kde.org" );
    about.addAuthor( "Frank Osterfeld", I18N_NOOP("Contributor"), "f_osterf@informatik.uni-kl.de" );
    about.addAuthor( "Gary Cramblitt", I18N_NOOP("Contributor"), "garycramblitt@comcast.net");
    about.addCredit( "Pierre Habouzit", I18N_NOOP("Debian Packages"), "pierre.habouzit@m4x.org" );
    about.addCredit( "Philipp Droessler", I18N_NOOP("Gentoo Ebuild"), "kingmob@albert-unser.net");
    about.addCredit( "Frerich Raabe", I18N_NOOP("Author of librss"), "raabe@kde.org" );
    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineArgs::addCmdLineOptions( options );
    aKregatorApp app;

    // see if we are starting with session management
    if (app.isRestored())
    {
        RESTORE(aKregator);
    }
    else
    {
        aKregator *widget;
        // no session.. just start up normally
        KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

        if ( args->count() == 0 )
        {
            widget = new aKregator;
            if(!widget->loadPart()) return 1;
            widget->loadLastOpenFile();
            app.setHaveWindowLoaded(true);
            widget->show();
        }
        else
        {
            int i = 0;
            for (; i < args->count(); i++ )
            {
                widget = new aKregator;
                if(!widget->loadPart()) return 1;
                app.setHaveWindowLoaded(true);
                widget->show();
                widget->load( args->url( i ) );
            }
        }
        args->clear();
    }

    return app.exec();
}
<|endoftext|>


<commit_before>/*
    This file is part of Akregator.

    Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>

    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.

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

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "aboutdata.h"
#include "mainwindow.h"
#include "akregator_options.h"

#include <kcmdlineargs.h>
#include <klocale.h>
#include <kuniqueapplication.h>
#include <QtDBus>
#include <QStringList>

namespace Akregator {

class Application : public KUniqueApplication {
  public:
    Application() : mMainWindow( ) {}
    ~Application() {}

    int newInstance();

  private:
    Akregator::MainWindow *mMainWindow;
};

int Application::newInstance()
{
  if (!isSessionRestored())
  {
    QDBusInterface akr("org.kde.akregator", "/Akregator", "org.kde.akregator.part");

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

    if ( !mMainWindow ) {
      mMainWindow = new Akregator::MainWindow();
      setMainWidget( mMainWindow );
      mMainWindow->loadPart();
      mMainWindow->setupProgressWidgets();
      if (!args->isSet("hide-mainwindow"))
        mMainWindow->show();
      akr.call( "openStandardFeedList");
    }

    QString addFeedGroup = !args->getOption("group").isEmpty() ?
         args->getOption("group")
         : i18n("Imported Folder");

    QStringList feeds = args->getOptionList("addfeed");
    QStringList feedsToAdd;
    QStringList::ConstIterator end( feeds.end() );
    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
        feedsToAdd.append(*it);

    if (feedsToAdd.isEmpty() && args->count() > 0) {
        QString url = args->url(0).url();
        if(!url.isEmpty())
            feedsToAdd.append(url);
    }

    if (!feedsToAdd.isEmpty())
        akr.call("addFeedsToGroup", feedsToAdd, addFeedGroup );

    args->clear();
  }
  return KUniqueApplication::newInstance();
}

} // namespace Akregator

int main(int argc, char **argv)
{
    Akregator::AboutData about;
    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineArgs::addCmdLineOptions( Akregator::akregator_options() );
    KUniqueApplication::addCmdLineOptions();

    Akregator::Application app;

    // start knotifyclient if not already started. makes it work for people who doesn't use full kde, according to kmail devels
    //KNotifyClient::startDaemon();

    // see if we are starting with session management
    if (app.isSessionRestored())
    {
#undef RESTORE
#define RESTORE(type) { int n = 1;\
    while (KMainWindow::canBeRestored(n)){\
        (new type)->restore(n, false);\
            n++;}}

        RESTORE(Akregator::MainWindow);
    }

    return app.exec();
}

<commit_msg>deprecated--<commit_after>/*
    This file is part of Akregator.

    Copyright (C) 2004 Stanislav Karchebny <Stanislav.Karchebny@kdemail.net>

    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.

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

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

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include "aboutdata.h"
#include "mainwindow.h"
#include "akregator_options.h"

#include <kcmdlineargs.h>
#include <klocale.h>
#include <kuniqueapplication.h>
#include <QtDBus>
#include <QStringList>

namespace Akregator {

class Application : public KUniqueApplication {
  public:
    Application() : mMainWindow( ) {}
    ~Application() {}

    int newInstance();

  private:
    Akregator::MainWindow *mMainWindow;
};

int Application::newInstance()
{
  if (!isSessionRestored())
  {
    QDBusInterface akr("org.kde.akregator", "/Akregator", "org.kde.akregator.part");

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();

    if ( !mMainWindow ) {
      mMainWindow = new Akregator::MainWindow();
      mMainWindow->loadPart();
      mMainWindow->setupProgressWidgets();
      if (!args->isSet("hide-mainwindow"))
        mMainWindow->show();
      akr.call( "openStandardFeedList");
    }

    QString addFeedGroup = !args->getOption("group").isEmpty() ?
         args->getOption("group")
         : i18n("Imported Folder");

    QStringList feeds = args->getOptionList("addfeed");
    QStringList feedsToAdd;
    QStringList::ConstIterator end( feeds.end() );
    for (QStringList::ConstIterator it = feeds.begin(); it != end; ++it)
        feedsToAdd.append(*it);

    if (feedsToAdd.isEmpty() && args->count() > 0) {
        QString url = args->url(0).url();
        if(!url.isEmpty())
            feedsToAdd.append(url);
    }

    if (!feedsToAdd.isEmpty())
        akr.call("addFeedsToGroup", feedsToAdd, addFeedGroup );

    args->clear();
  }
  return KUniqueApplication::newInstance();
}

} // namespace Akregator

int main(int argc, char **argv)
{
    Akregator::AboutData about;
    KCmdLineArgs::init(argc, argv, &about);
    KCmdLineArgs::addCmdLineOptions( Akregator::akregator_options() );
    KUniqueApplication::addCmdLineOptions();

    Akregator::Application app;

    // start knotifyclient if not already started. makes it work for people who doesn't use full kde, according to kmail devels
    //KNotifyClient::startDaemon();

    // see if we are starting with session management
    if (app.isSessionRestored())
    {
#undef RESTORE
#define RESTORE(type) { int n = 1;\
    while (KMainWindow::canBeRestored(n)){\
        (new type)->restore(n, false);\
            n++;}}

        RESTORE(Akregator::MainWindow);
    }

    return app.exec();
}

<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "waylandsurfaceitem.h"
#include "waylandsurface.h"
#include "waylandcompositor.h"
#include "waylandinput.h"

#include "wlsurface.h"
#include "wlextendedsurface.h"

#include <QtGui/QKeyEvent>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>

#include <QtQuick/QSGSimpleTextureNode>
#include <QtQuick/QSGSimpleRectNode>
#include <QtQuick/QQuickCanvas>

class WaylandSurfaceTextureProvider : public QSGTextureProvider
{
public:
    WaylandSurfaceTextureProvider() : t(0) { }

    QSGTexture *texture() const {
        if (t)
            t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest);
        return t;
    }

    QSGTexture *t;
    bool smooth;
};

WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
    : QQuickItem(parent)
    , m_surface(0)
    , m_texture(0)
    , m_provider(0)
    , m_paintEnabled(true)
    , m_useTextureAlpha(false)
    , m_clientRenderingEnabled(false)
    , m_touchEventsEnabled(false)
{
}

WaylandSurfaceItem::WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent)
    : QQuickItem(parent)
    , m_surface(0)
    , m_texture(0)
    , m_provider(0)
    , m_paintEnabled(true)
    , m_useTextureAlpha(false)
    , m_clientRenderingEnabled(false)
    , m_touchEventsEnabled(false)
{
    init(surface);
}

void WaylandSurfaceItem::init(WaylandSurface *surface)
{
    if (!surface)
        return;

    if (m_surface) {
        m_surface->setSurfaceItem(0);
    }

    m_surface = surface;
    m_surface->setSurfaceItem(this);
    if (m_clientRenderingEnabled) {
        m_surface->sendOnScreenVisibilityChange(m_clientRenderingEnabled);
    }

    setWidth(surface->size().width());
    setHeight(surface->size().height());

    setSmooth(true);
    setFlag(ItemHasContents);
    setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
    setAcceptHoverEvents(true);
    connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
    connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
    connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
    connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
    connect(surface, SIGNAL(parentChanged(WaylandSurface*,WaylandSurface*)),
            this, SLOT(parentChanged(WaylandSurface*,WaylandSurface*)));
    connect(surface, SIGNAL(sizeChanged()), this, SLOT(updateSize()));
    connect(surface, SIGNAL(posChanged()), this, SLOT(updatePosition()));

    m_damaged = false;
    m_yInverted = surface ? surface->isYInverted() : true;
}

WaylandSurfaceItem::~WaylandSurfaceItem()
{
    if (m_surface) {
        m_surface->setSurfaceItem(0);
    }
    m_texture->deleteLater();
}

void WaylandSurfaceItem::setSurface(WaylandSurface *surface)
{
    if (surface == m_surface)
        return;

    init(surface);
    emit surfaceChanged();
}

bool WaylandSurfaceItem::isYInverted() const
{
    return m_yInverted;
}

QSGTextureProvider *WaylandSurfaceItem::textureProvider() const
{
    if (!m_provider)
        m_provider = new WaylandSurfaceTextureProvider();
    return m_provider;
}

void WaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
{
    if (m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        if (inputDevice->mouseFocus() != m_surface)
            inputDevice->setMouseFocus(m_surface, event->pos(), event->globalPos());
        inputDevice->sendMousePressEvent(event->button(), toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
{
    if (m_surface){
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendMouseMoveEvent(m_surface, toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_surface){
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendMouseReleaseEvent(event->button(), toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
{
    if (m_surface && hasFocus()) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendKeyPressEvent(event->nativeScanCode());
    }
}

void WaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
{
    if (m_surface && hasFocus()) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendKeyReleaseEvent(event->nativeScanCode());
    }
}

void WaylandSurfaceItem::touchEvent(QTouchEvent *event)
{
    if (m_touchEventsEnabled && m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        event->accept();
        if (inputDevice->mouseFocus() != m_surface) {
            QPoint pointPos;
            QList<QTouchEvent::TouchPoint> points = event->touchPoints();
            if (!points.isEmpty())
                pointPos = points.at(0).pos().toPoint();
            inputDevice->setMouseFocus(m_surface, pointPos, pointPos);
        }
        inputDevice->sendFullTouchEvent(event);
    } else {
        event->ignore();
    }
}

void WaylandSurfaceItem::takeFocus()
{
    setFocus(true);

    if (m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->setKeyboardFocus(m_surface);
    }
}

QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const
{
    return pos.toPoint();
}

void WaylandSurfaceItem::surfaceMapped()
{
    setPaintEnabled(true);
}

void WaylandSurfaceItem::surfaceUnmapped()
{
    setPaintEnabled(false);
}

void WaylandSurfaceItem::surfaceDestroyed(QObject *)
{
    m_surface = 0;
}

void WaylandSurfaceItem::setDamagedFlag(bool on)
{
    m_damaged = on;
}

void WaylandSurfaceItem::surfaceDamaged(const QRect &)
{
    m_damaged = true;
    if (m_surface) {
        bool inverted = m_surface->isYInverted();
        if (inverted  != m_yInverted) {
            m_yInverted = inverted;
            emit yInvertedChanged();
        }
    }
    emit textureChanged();
    update();
}

void WaylandSurfaceItem::parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent)
{
    Q_UNUSED(oldParent);

    WaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
    setParentItem(item);

    if (newParent) {
        setPaintEnabled(true);
        setVisible(true);
        setOpacity(1);
        setEnabled(true);
    }
}

void WaylandSurfaceItem::updateSize()
{
    setSize(m_surface->size());
}

void WaylandSurfaceItem::updatePosition()
{
    setPos(m_surface->pos());
}

bool WaylandSurfaceItem::paintEnabled() const
{
    return m_paintEnabled;
}

void WaylandSurfaceItem::setPaintEnabled(bool enabled)
{
    m_paintEnabled = enabled;
    update();
}

class WaylandSurfaceNode : public QSGSimpleTextureNode
{
public:
    WaylandSurfaceNode(WaylandSurfaceItem *item) : m_item(item) {
        setFlag(UsePreprocess,true);
    }
    void preprocess() {
        if (m_item->m_damaged) {
            m_item->updateTexture();
            m_item->updateNodeTexture(this);
        }
    }
private:
    WaylandSurfaceItem *m_item;
};

void WaylandSurfaceItem::updateTexture()
{
    if (m_damaged) {
        QSGTexture *oldTexture = m_texture;
        if (m_surface->type() == WaylandSurface::Texture) {
            QOpenGLContext *context = QOpenGLContext::currentContext();

            QQuickCanvas::CreateTextureOptions opt = useTextureAlpha() ? QQuickCanvas::TextureHasAlphaChannel : QQuickCanvas::CreateTextureOptions(0);
            m_texture = canvas()->createTextureFromId(m_surface->texture(context),
                                                                          m_surface->size(),
                                                                          opt);
        } else {
            m_texture = canvas()->createTextureFromImage(m_surface->image());
        }

        delete oldTexture;
        m_damaged = false;
    }

    if (m_provider) {
        m_provider->t = m_texture;
        m_provider->smooth = smooth();
    }
}

void WaylandSurfaceItem::updateNodeTexture(WaylandSurfaceNode *node)
{
    node->setTexture(m_texture);
    node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
}

QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (!m_surface) {
        delete oldNode;
        return 0;
    }

    updateTexture();
    if (!m_texture || !m_paintEnabled) {
        delete oldNode;
        return 0;
    }

    WaylandSurfaceNode *node = static_cast<WaylandSurfaceNode *>(oldNode);

    if (!node) {
        node = new WaylandSurfaceNode(this);
    }

    updateNodeTexture(node);

    if (surface()->isYInverted()) {
        node->setRect(0, height(), width(), -height());
    } else {
        node->setRect(0, 0, width(), height());
    }

    return node;
}

void WaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha)
{
    m_useTextureAlpha = useTextureAlpha;

    if ((flags() & ItemHasContents) != 0) {
        update();
    }
}

void WaylandSurfaceItem::setClientRenderingEnabled(bool enabled)
{
    if (m_clientRenderingEnabled != enabled) {
        m_clientRenderingEnabled = enabled;

        if (m_surface) {
            m_surface->sendOnScreenVisibilityChange(enabled);
        }

        emit clientRenderingEnabledChanged();
    }
}

void WaylandSurfaceItem::setTouchEventsEnabled(bool enabled)
{
    if (m_touchEventsEnabled != enabled) {
        m_touchEventsEnabled = enabled;
        emit touchEventsEnabledChanged();
    }
}
<commit_msg>Avoid race condition<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the Qt Compositor.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "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 Nokia Corporation and its Subsidiary(-ies) 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."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "waylandsurfaceitem.h"
#include "waylandsurface.h"
#include "waylandcompositor.h"
#include "waylandinput.h"

#include "wlsurface.h"
#include "wlextendedsurface.h"

#include <QtGui/QKeyEvent>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>

#include <QtQuick/QSGSimpleTextureNode>
#include <QtQuick/QSGSimpleRectNode>
#include <QtQuick/QQuickCanvas>

class WaylandSurfaceTextureProvider : public QSGTextureProvider
{
public:
    WaylandSurfaceTextureProvider() : t(0) { }

    QSGTexture *texture() const {
        if (t)
            t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest);
        return t;
    }

    QSGTexture *t;
    bool smooth;
};

WaylandSurfaceItem::WaylandSurfaceItem(QQuickItem *parent)
    : QQuickItem(parent)
    , m_surface(0)
    , m_texture(0)
    , m_provider(0)
    , m_paintEnabled(true)
    , m_useTextureAlpha(false)
    , m_clientRenderingEnabled(false)
    , m_touchEventsEnabled(false)
{
}

WaylandSurfaceItem::WaylandSurfaceItem(WaylandSurface *surface, QQuickItem *parent)
    : QQuickItem(parent)
    , m_surface(0)
    , m_texture(0)
    , m_provider(0)
    , m_paintEnabled(true)
    , m_useTextureAlpha(false)
    , m_clientRenderingEnabled(false)
    , m_touchEventsEnabled(false)
{
    init(surface);
}

void WaylandSurfaceItem::init(WaylandSurface *surface)
{
    if (!surface)
        return;

    if (m_surface) {
        m_surface->setSurfaceItem(0);
    }

    m_surface = surface;
    m_surface->setSurfaceItem(this);
    if (m_clientRenderingEnabled) {
        m_surface->sendOnScreenVisibilityChange(m_clientRenderingEnabled);
    }

    setWidth(surface->size().width());
    setHeight(surface->size().height());

    setSmooth(true);
    setFlag(ItemHasContents);
    setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
    setAcceptHoverEvents(true);
    connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
    connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
    connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
    connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
    connect(surface, SIGNAL(parentChanged(WaylandSurface*,WaylandSurface*)),
            this, SLOT(parentChanged(WaylandSurface*,WaylandSurface*)));
    connect(surface, SIGNAL(sizeChanged()), this, SLOT(updateSize()));
    connect(surface, SIGNAL(posChanged()), this, SLOT(updatePosition()));

    m_damaged = false;
    m_yInverted = surface ? surface->isYInverted() : true;
}

WaylandSurfaceItem::~WaylandSurfaceItem()
{
    if (m_surface) {
        m_surface->setSurfaceItem(0);
    }
    m_texture->deleteLater();
}

void WaylandSurfaceItem::setSurface(WaylandSurface *surface)
{
    if (surface == m_surface)
        return;

    init(surface);
    emit surfaceChanged();
}

bool WaylandSurfaceItem::isYInverted() const
{
    return m_yInverted;
}

QSGTextureProvider *WaylandSurfaceItem::textureProvider() const
{
    if (!m_provider)
        m_provider = new WaylandSurfaceTextureProvider();
    return m_provider;
}

void WaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
{
    if (m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        if (inputDevice->mouseFocus() != m_surface)
            inputDevice->setMouseFocus(m_surface, event->pos(), event->globalPos());
        inputDevice->sendMousePressEvent(event->button(), toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::mouseMoveEvent(QMouseEvent *event)
{
    if (m_surface){
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendMouseMoveEvent(m_surface, toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_surface){
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendMouseReleaseEvent(event->button(), toSurface(event->pos()));
    }
}

void WaylandSurfaceItem::keyPressEvent(QKeyEvent *event)
{
    if (m_surface && hasFocus()) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendKeyPressEvent(event->nativeScanCode());
    }
}

void WaylandSurfaceItem::keyReleaseEvent(QKeyEvent *event)
{
    if (m_surface && hasFocus()) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->sendKeyReleaseEvent(event->nativeScanCode());
    }
}

void WaylandSurfaceItem::touchEvent(QTouchEvent *event)
{
    if (m_touchEventsEnabled && m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        event->accept();
        if (inputDevice->mouseFocus() != m_surface) {
            QPoint pointPos;
            QList<QTouchEvent::TouchPoint> points = event->touchPoints();
            if (!points.isEmpty())
                pointPos = points.at(0).pos().toPoint();
            inputDevice->setMouseFocus(m_surface, pointPos, pointPos);
        }
        inputDevice->sendFullTouchEvent(event);
    } else {
        event->ignore();
    }
}

void WaylandSurfaceItem::takeFocus()
{
    setFocus(true);

    if (m_surface) {
        WaylandInputDevice *inputDevice = m_surface->compositor()->defaultInputDevice();
        inputDevice->setKeyboardFocus(m_surface);
    }
}

QPoint WaylandSurfaceItem::toSurface(const QPointF &pos) const
{
    return pos.toPoint();
}

void WaylandSurfaceItem::surfaceMapped()
{
    setPaintEnabled(true);
}

void WaylandSurfaceItem::surfaceUnmapped()
{
    setPaintEnabled(false);
}

void WaylandSurfaceItem::surfaceDestroyed(QObject *)
{
    m_surface = 0;
}

void WaylandSurfaceItem::setDamagedFlag(bool on)
{
    m_damaged = on;
}

void WaylandSurfaceItem::surfaceDamaged(const QRect &)
{
    m_damaged = true;
    if (m_surface) {
        bool inverted = m_surface->isYInverted();
        if (inverted  != m_yInverted) {
            m_yInverted = inverted;
            emit yInvertedChanged();
        }
    }
    emit textureChanged();
    update();
}

void WaylandSurfaceItem::parentChanged(WaylandSurface *newParent, WaylandSurface *oldParent)
{
    Q_UNUSED(oldParent);

    WaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
    setParentItem(item);

    if (newParent) {
        setPaintEnabled(true);
        setVisible(true);
        setOpacity(1);
        setEnabled(true);
    }
}

void WaylandSurfaceItem::updateSize()
{
    setSize(m_surface->size());
}

void WaylandSurfaceItem::updatePosition()
{
    setPos(m_surface->pos());
}

bool WaylandSurfaceItem::paintEnabled() const
{
    return m_paintEnabled;
}

void WaylandSurfaceItem::setPaintEnabled(bool enabled)
{
    m_paintEnabled = enabled;
    update();
}

class WaylandSurfaceNode : public QSGSimpleTextureNode
{
public:
    WaylandSurfaceNode(WaylandSurfaceItem *item) : m_item(item) {
        setFlag(UsePreprocess,true);
    }
    void preprocess() {
        if (m_item->m_damaged) {
            m_item->updateTexture();
            m_item->updateNodeTexture(this);
        }
    }
private:
    WaylandSurfaceItem *m_item;
};

void WaylandSurfaceItem::updateTexture()
{
    if (m_damaged) {
        m_damaged = false;
        QSGTexture *oldTexture = m_texture;
        if (m_surface->type() == WaylandSurface::Texture) {
            QOpenGLContext *context = QOpenGLContext::currentContext();

            QQuickCanvas::CreateTextureOptions opt = useTextureAlpha() ? QQuickCanvas::TextureHasAlphaChannel : QQuickCanvas::CreateTextureOptions(0);
            m_texture = canvas()->createTextureFromId(m_surface->texture(context),
                                                                          m_surface->size(),
                                                                          opt);
        } else {
            m_texture = canvas()->createTextureFromImage(m_surface->image());
        }

        delete oldTexture;
    }

    if (m_provider) {
        m_provider->t = m_texture;
        m_provider->smooth = smooth();
    }
}

void WaylandSurfaceItem::updateNodeTexture(WaylandSurfaceNode *node)
{
    node->setTexture(m_texture);
    node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
}

QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
    if (!m_surface) {
        delete oldNode;
        return 0;
    }

    updateTexture();
    if (!m_texture || !m_paintEnabled) {
        delete oldNode;
        return 0;
    }

    WaylandSurfaceNode *node = static_cast<WaylandSurfaceNode *>(oldNode);

    if (!node) {
        node = new WaylandSurfaceNode(this);
    }

    updateNodeTexture(node);

    if (surface()->isYInverted()) {
        node->setRect(0, height(), width(), -height());
    } else {
        node->setRect(0, 0, width(), height());
    }

    return node;
}

void WaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha)
{
    m_useTextureAlpha = useTextureAlpha;

    if ((flags() & ItemHasContents) != 0) {
        update();
    }
}

void WaylandSurfaceItem::setClientRenderingEnabled(bool enabled)
{
    if (m_clientRenderingEnabled != enabled) {
        m_clientRenderingEnabled = enabled;

        if (m_surface) {
            m_surface->sendOnScreenVisibilityChange(enabled);
        }

        emit clientRenderingEnabledChanged();
    }
}

void WaylandSurfaceItem::setTouchEventsEnabled(bool enabled)
{
    if (m_touchEventsEnabled != enabled) {
        m_touchEventsEnabled = enabled;
        emit touchEventsEnabledChanged();
    }
}
<|endoftext|>


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

#include "src/core/ext/filters/client_channel/backup_poller.h"

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/sync.h>

#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/completion_queue.h"

#define DEFAULT_POLL_INTERVAL_MS 5000

namespace {
struct backup_poller {
  grpc_timer polling_timer;
  grpc_closure run_poller_closure;
  grpc_closure shutdown_closure;
  gpr_mu* pollset_mu;
  grpc_pollset* pollset;  // guarded by pollset_mu
  bool shutting_down;     // guarded by pollset_mu
  gpr_refcount refs;
  gpr_refcount shutdown_refs;
};
}  // namespace

static gpr_once g_once = GPR_ONCE_INIT;
static gpr_mu g_poller_mu;
static backup_poller* g_poller = nullptr;  // guarded by g_poller_mu
// g_poll_interval_ms is set only once at the first time
// grpc_client_channel_start_backup_polling() is called, after that it is
// treated as const.
static int g_poll_interval_ms = DEFAULT_POLL_INTERVAL_MS;

GPR_GLOBAL_CONFIG_DEFINE_INT32(
    grpc_client_channel_backup_poll_interval_ms, DEFAULT_POLL_INTERVAL_MS,
    "Declares the interval in ms between two backup polls on client channels. "
    "These polls are run in the timer thread so that gRPC can process "
    "connection failures while there is no active polling thread. "
    "They help reconnect disconnected client channels (mostly due to "
    "idleness), so that the next RPC on this channel won't fail. Set to 0 to "
    "turn off the backup polls.");

void grpc_client_channel_global_init_backup_polling() {
  gpr_once_init(&g_once, [] { gpr_mu_init(&g_poller_mu); });
  int32_t poll_interval_ms =
      GPR_GLOBAL_CONFIG_GET(grpc_client_channel_backup_poll_interval_ms);
  if (poll_interval_ms < 0) {
    gpr_log(GPR_ERROR,
            "Invalid GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS: %d, "
            "default value %d will be used.",
            poll_interval_ms, g_poll_interval_ms);
  } else {
    g_poll_interval_ms = poll_interval_ms;
  }
}

static void backup_poller_shutdown_unref(backup_poller* p) {
  if (gpr_unref(&p->shutdown_refs)) {
    grpc_pollset_destroy(p->pollset);
    gpr_free(p->pollset);
    gpr_free(p);
  }
}

static void done_poller(void* arg, grpc_error* error) {
  backup_poller_shutdown_unref(static_cast<backup_poller*>(arg));
}

static void g_poller_unref() {
  gpr_mu_lock(&g_poller_mu);
  if (gpr_unref(&g_poller->refs)) {
    backup_poller* p = g_poller;
    g_poller = nullptr;
    gpr_mu_unlock(&g_poller_mu);
    gpr_mu_lock(p->pollset_mu);
    p->shutting_down = true;
    grpc_pollset_shutdown(
        p->pollset, GRPC_CLOSURE_INIT(&p->shutdown_closure, done_poller, p,
                                      grpc_schedule_on_exec_ctx));
    gpr_mu_unlock(p->pollset_mu);
    grpc_timer_cancel(&p->polling_timer);
  } else {
    gpr_mu_unlock(&g_poller_mu);
  }
}

static void run_poller(void* arg, grpc_error* error) {
  backup_poller* p = static_cast<backup_poller*>(arg);
  if (error != GRPC_ERROR_NONE) {
    if (error != GRPC_ERROR_CANCELLED) {
      GRPC_LOG_IF_ERROR("run_poller", GRPC_ERROR_REF(error));
    }
    backup_poller_shutdown_unref(p);
    return;
  }
  gpr_mu_lock(p->pollset_mu);
  if (p->shutting_down) {
    gpr_mu_unlock(p->pollset_mu);
    backup_poller_shutdown_unref(p);
    return;
  }
  grpc_error* err =
      grpc_pollset_work(p->pollset, nullptr, grpc_core::ExecCtx::Get()->Now());
  gpr_mu_unlock(p->pollset_mu);
  GRPC_LOG_IF_ERROR("Run client channel backup poller", err);
  grpc_timer_init(&p->polling_timer,
                  grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
                  &p->run_poller_closure);
}

static void g_poller_init_locked() {
  if (g_poller == nullptr) {
    g_poller = static_cast<backup_poller*>(gpr_zalloc(sizeof(backup_poller)));
    g_poller->pollset =
        static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
    g_poller->shutting_down = false;
    grpc_pollset_init(g_poller->pollset, &g_poller->pollset_mu);
    gpr_ref_init(&g_poller->refs, 0);
    // one for timer cancellation, one for pollset shutdown
    gpr_ref_init(&g_poller->shutdown_refs, 2);
    GRPC_CLOSURE_INIT(&g_poller->run_poller_closure, run_poller, g_poller,
                      grpc_schedule_on_exec_ctx);
    grpc_timer_init(&g_poller->polling_timer,
                    grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
                    &g_poller->run_poller_closure);
  }
}

void grpc_client_channel_start_backup_polling(
    grpc_pollset_set* interested_parties) {
  if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
    return;
  }
  gpr_mu_lock(&g_poller_mu);
  g_poller_init_locked();
  gpr_ref(&g_poller->refs);
  /* Get a reference to g_poller->pollset before releasing g_poller_mu to make
   * TSAN happy. Otherwise, reading from g_poller (i.e g_poller->pollset) after
   * releasing the lock and setting g_poller to NULL in g_poller_unref() is
   * being flagged as a data-race by TSAN */
  grpc_pollset* pollset = g_poller->pollset;
  gpr_mu_unlock(&g_poller_mu);

  grpc_pollset_set_add_pollset(interested_parties, pollset);
}

void grpc_client_channel_stop_backup_polling(
    grpc_pollset_set* interested_parties) {
  if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
    return;
  }
  grpc_pollset_set_del_pollset(interested_parties, g_poller->pollset);
  g_poller_unref();
}
<commit_msg>Revert the previous clang-format changes to pass the clang format check on github.<commit_after>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/ext/filters/client_channel/backup_poller.h"

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/ext/filters/client_channel/client_channel.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/global_config.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/completion_queue.h"

#define DEFAULT_POLL_INTERVAL_MS 5000

namespace {
struct backup_poller {
  grpc_timer polling_timer;
  grpc_closure run_poller_closure;
  grpc_closure shutdown_closure;
  gpr_mu* pollset_mu;
  grpc_pollset* pollset;  // guarded by pollset_mu
  bool shutting_down;     // guarded by pollset_mu
  gpr_refcount refs;
  gpr_refcount shutdown_refs;
};
}  // namespace

static gpr_once g_once = GPR_ONCE_INIT;
static gpr_mu g_poller_mu;
static backup_poller* g_poller = nullptr;  // guarded by g_poller_mu
// g_poll_interval_ms is set only once at the first time
// grpc_client_channel_start_backup_polling() is called, after that it is
// treated as const.
static int g_poll_interval_ms = DEFAULT_POLL_INTERVAL_MS;

GPR_GLOBAL_CONFIG_DEFINE_INT32(
    grpc_client_channel_backup_poll_interval_ms, DEFAULT_POLL_INTERVAL_MS,
    "Declares the interval in ms between two backup polls on client channels. "
    "These polls are run in the timer thread so that gRPC can process "
    "connection failures while there is no active polling thread. "
    "They help reconnect disconnected client channels (mostly due to "
    "idleness), so that the next RPC on this channel won't fail. Set to 0 to "
    "turn off the backup polls.");

void grpc_client_channel_global_init_backup_polling() {
  gpr_once_init(&g_once, [] { gpr_mu_init(&g_poller_mu); });
  int32_t poll_interval_ms =
      GPR_GLOBAL_CONFIG_GET(grpc_client_channel_backup_poll_interval_ms);
  if (poll_interval_ms < 0) {
    gpr_log(GPR_ERROR,
            "Invalid GRPC_CLIENT_CHANNEL_BACKUP_POLL_INTERVAL_MS: %d, "
            "default value %d will be used.",
            poll_interval_ms, g_poll_interval_ms);
  } else {
    g_poll_interval_ms = poll_interval_ms;
  }
}

static void backup_poller_shutdown_unref(backup_poller* p) {
  if (gpr_unref(&p->shutdown_refs)) {
    grpc_pollset_destroy(p->pollset);
    gpr_free(p->pollset);
    gpr_free(p);
  }
}

static void done_poller(void* arg, grpc_error* error) {
  backup_poller_shutdown_unref(static_cast<backup_poller*>(arg));
}

static void g_poller_unref() {
  gpr_mu_lock(&g_poller_mu);
  if (gpr_unref(&g_poller->refs)) {
    backup_poller* p = g_poller;
    g_poller = nullptr;
    gpr_mu_unlock(&g_poller_mu);
    gpr_mu_lock(p->pollset_mu);
    p->shutting_down = true;
    grpc_pollset_shutdown(
        p->pollset, GRPC_CLOSURE_INIT(&p->shutdown_closure, done_poller, p,
                                      grpc_schedule_on_exec_ctx));
    gpr_mu_unlock(p->pollset_mu);
    grpc_timer_cancel(&p->polling_timer);
  } else {
    gpr_mu_unlock(&g_poller_mu);
  }
}

static void run_poller(void* arg, grpc_error* error) {
  backup_poller* p = static_cast<backup_poller*>(arg);
  if (error != GRPC_ERROR_NONE) {
    if (error != GRPC_ERROR_CANCELLED) {
      GRPC_LOG_IF_ERROR("run_poller", GRPC_ERROR_REF(error));
    }
    backup_poller_shutdown_unref(p);
    return;
  }
  gpr_mu_lock(p->pollset_mu);
  if (p->shutting_down) {
    gpr_mu_unlock(p->pollset_mu);
    backup_poller_shutdown_unref(p);
    return;
  }
  grpc_error* err =
      grpc_pollset_work(p->pollset, nullptr, grpc_core::ExecCtx::Get()->Now());
  gpr_mu_unlock(p->pollset_mu);
  GRPC_LOG_IF_ERROR("Run client channel backup poller", err);
  grpc_timer_init(&p->polling_timer,
                  grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
                  &p->run_poller_closure);
}

static void g_poller_init_locked() {
  if (g_poller == nullptr) {
    g_poller = static_cast<backup_poller*>(gpr_zalloc(sizeof(backup_poller)));
    g_poller->pollset =
        static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
    g_poller->shutting_down = false;
    grpc_pollset_init(g_poller->pollset, &g_poller->pollset_mu);
    gpr_ref_init(&g_poller->refs, 0);
    // one for timer cancellation, one for pollset shutdown
    gpr_ref_init(&g_poller->shutdown_refs, 2);
    GRPC_CLOSURE_INIT(&g_poller->run_poller_closure, run_poller, g_poller,
                      grpc_schedule_on_exec_ctx);
    grpc_timer_init(&g_poller->polling_timer,
                    grpc_core::ExecCtx::Get()->Now() + g_poll_interval_ms,
                    &g_poller->run_poller_closure);
  }
}

void grpc_client_channel_start_backup_polling(
    grpc_pollset_set* interested_parties) {
  if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
    return;
  }
  gpr_mu_lock(&g_poller_mu);
  g_poller_init_locked();
  gpr_ref(&g_poller->refs);
  /* Get a reference to g_poller->pollset before releasing g_poller_mu to make
   * TSAN happy. Otherwise, reading from g_poller (i.e g_poller->pollset) after
   * releasing the lock and setting g_poller to NULL in g_poller_unref() is
   * being flagged as a data-race by TSAN */
  grpc_pollset* pollset = g_poller->pollset;
  gpr_mu_unlock(&g_poller_mu);

  grpc_pollset_set_add_pollset(interested_parties, pollset);
}

void grpc_client_channel_stop_backup_polling(
    grpc_pollset_set* interested_parties) {
  if (g_poll_interval_ms == 0 || grpc_iomgr_run_in_background()) {
    return;
  }
  grpc_pollset_set_del_pollset(interested_parties, g_poller->pollset);
  g_poller_unref();
}
<|endoftext|>


<commit_before>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
//

#include <assert.h>
#include <stdint.h>
#include <map>
#include <unicode/uchar.h>
#include <unicode/ucol.h>
#include <unicode/usearch.h>
#include <unicode/utf16.h>

const int32_t CompareOptionsIgnoreCase = 1;
// const int32_t CompareOptionsIgnoreNonSpace = 2;
// const int32_t CompareOptionsIgnoreSymbols = 4;
// const int32_t CompareOptionsIgnoreKanaType = 8;
// const int32_t CompareOptionsIgnoreWidth = 0x10;
// const int32_t CompareOptionsStringSort = 0x20000000;

typedef std::map<int32_t, UCollator*> TCollatorMap;
typedef std::pair<int32_t, UCollator*> TCollatorMapPair;

/*
 * For increased performance, we cache the UCollator objects for a locale and
 * share them across threads. This is safe (and supported in ICU) if we ensure
 * multiple threads are only ever dealing with const UCollators.
 */
typedef struct _sort_handle
{
    UCollator* regular;
    TCollatorMap collatorsPerOption;

    _sort_handle() : regular(nullptr)
    {
    }

} SortHandle;

/*
 * To collator returned by this function is owned by the callee and must be
 * closed when this method returns with a U_SUCCESS UErrorCode.
 *
 * On error, the return value is undefined.
 */
UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, UErrorCode* pErr)
{
    UCollator* pClonedCollator = ucol_safeClone(pCollator, nullptr, nullptr, pErr);

    if ((options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase)
    {
        ucol_setAttribute(pClonedCollator, UCOL_STRENGTH, UCOL_SECONDARY, pErr);
    }

    return pClonedCollator;
}

extern "C" SortHandle* GetSortHandle(const char* lpLocaleName)
{
    SortHandle* pSortHandle = new SortHandle();

    UErrorCode err = U_ZERO_ERROR;

    pSortHandle->regular = ucol_open(lpLocaleName, &err);

    if (U_FAILURE(err))
    {
        if (pSortHandle->regular != nullptr)
              ucol_close(pSortHandle->regular);

        delete pSortHandle;
        pSortHandle = nullptr;
    }

    return pSortHandle;
}

extern "C" void CloseSortHandle(SortHandle* pSortHandle)
{
    ucol_close(pSortHandle->regular);
    pSortHandle->regular = nullptr;

    TCollatorMap::iterator it;
    for (it = pSortHandle->collatorsPerOption.begin(); it != pSortHandle->collatorsPerOption.end(); it++)
    {
        ucol_close(it->second);
    }

    delete pSortHandle;
}

const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t options, UErrorCode* pErr)
{
    UCollator* pCollator;
    if (options == 0)
    {
        pCollator = pSortHandle->regular;
    }
    else
    {
        TCollatorMap::iterator entry = pSortHandle->collatorsPerOption.find(options);
        if (entry == pSortHandle->collatorsPerOption.end())
        {
            pCollator = CloneCollatorWithOptions(pSortHandle->regular, options, pErr);
            pSortHandle->collatorsPerOption[options] = pCollator;
        }
        else
        {
            pCollator = entry->second;
        }
    }

    return pCollator;
}

/*
Function:
CompareString
*/
extern "C" int32_t CompareString(SortHandle* pSortHandle,
                                 const UChar* lpStr1,
                                 int32_t cwStr1Length,
                                 const UChar* lpStr2,
                                 int32_t cwStr2Length,
                                 int32_t options)
{
    static_assert(UCOL_EQUAL == 0, "managed side requires 0 for equal strings");
    static_assert(UCOL_LESS < 0, "managed side requires less than zero for a < b");
    static_assert(UCOL_GREATER > 0, "managed side requires greater than zero for a > b");

    UCollationResult result = UCOL_EQUAL;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        result = ucol_strcoll(pColl, lpStr1, cwStr1Length, lpStr2, cwStr2Length);
    }

    return result;
}

/*
Function:
IndexOf
*/
extern "C" int32_t
IndexOf(SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");

    int32_t result = USEARCH_DONE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);

        if (U_SUCCESS(err))
        {
            result = usearch_first(pSearch, &err);
            usearch_close(pSearch);
        }
    }

    return result;
}

/*
Function:
LastIndexOf
*/
extern "C" int32_t LastIndexOf(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");

    int32_t result = USEARCH_DONE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);

        if (U_SUCCESS(err))
        {
            result = usearch_last(pSearch, &err);
            usearch_close(pSearch);
        }
    }

    return result;
}

/*
Static Function:
AreEqualOrdinalIgnoreCase
*/
static bool AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two)
{
    // Return whether the two characters are identical or would be identical if they were upper-cased.

    if (one == two)
    {
        return true;
    }

    if (one == 0x0131 || two == 0x0131)
    {
        // On Windows with InvariantCulture, the LATIN SMALL LETTER DOTLESS I (U+0131)
        // capitalizes to itself, whereas with ICU it capitalizes to LATIN CAPITAL LETTER I (U+0049).
        // We special case it to match the Windows invariant behavior.
        return false;
    }

    return u_toupper(one) == u_toupper(two);
}

/*
Function:
IndexOfOrdinalIgnoreCase
*/
extern "C" int32_t
IndexOfOrdinalIgnoreCase(
    const UChar* lpTarget, int32_t cwTargetLength,
    const UChar* lpSource, int32_t cwSourceLength,
    int32_t findLast)
{
    int32_t result = -1;

    int32_t endIndex = cwSourceLength - cwTargetLength;
    assert(endIndex >= 0);

    int32_t i = 0;
    while (i <= endIndex)
    {
        int32_t srcIdx = i, trgIdx = 0;
        const UChar *src = lpSource, *trg = lpTarget;
        UChar32 srcCodepoint, trgCodepoint;

        bool match = true;
        while (trgIdx < cwTargetLength)
        {
            U16_NEXT(src, srcIdx, cwSourceLength, srcCodepoint);
            U16_NEXT(trg, trgIdx, cwTargetLength, trgCodepoint);
            if (!AreEqualOrdinalIgnoreCase(srcCodepoint, trgCodepoint))
            {
                match = false;
                break;
            }
        }

        if (match)
        {
            result = i;
            if (!findLast)
            {
                break;
            }
        }

        U16_FWD_1(lpSource, i, cwSourceLength);
    }

    return result;
}

/*
 Return value is a "Win32 BOOL" (1 = true, 0 = false)
 */
extern "C" int32_t StartsWith(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    int32_t result = FALSE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);
        int32_t idx = USEARCH_DONE;

        if (U_SUCCESS(err))
        {
            idx = usearch_first(pSearch, &err);
            if (idx != USEARCH_DONE)
            {
                if (idx == 0)
                {
                    result = TRUE;
                }
                else
                {
                    UCollationElements* pCollElem = ucol_openElements(pColl, lpSource, idx, &err);

                    if (U_SUCCESS(err))
                    {
                        int32_t curCollElem = UCOL_NULLORDER;

                        result = TRUE;

                        while ((curCollElem = ucol_next(pCollElem, &err)) != UCOL_NULLORDER)
                        {
                            if (curCollElem != 0)
                            {
                                // Non ignorable collation element found between start of the
                                // string and the first match for lpTarget.
                                result = FALSE;
                                break;
                            }
                        }

                        if (U_FAILURE(err))
                        {
                            result = FALSE;
                        }

                        ucol_closeElements(pCollElem);
                    }
                }
            }

            usearch_close(pSearch);
        }
    }

    return result;
}

/*
 Return value is a "Win32 BOOL" (1 = true, 0 = false)
 */
extern "C" int32_t EndsWith(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    int32_t result = FALSE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);
        int32_t idx = USEARCH_DONE;

        if (U_SUCCESS(err))
        {
            idx = usearch_last(pSearch, &err);

            if (idx != USEARCH_DONE)
            {
                if ((idx + usearch_getMatchedLength(pSearch)) == cwSourceLength)
                {
                    result = TRUE;
                }

                // TODO (dotnet/corefx#3467): We should do something similar to what
                // StartsWith does where we can ignore
                // some collation elements at the end of the string if they are zero.
            }

            usearch_close(pSearch);
        }
    }

    return result;
}

extern "C" int32_t GetSortKey(SortHandle* pSortHandle,
                              const UChar* lpStr,
                              int32_t cwStrLength,
                              uint8_t* sortKey,
                              int32_t cbSortKeyLength,
                              int32_t options)
{
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);
    int32_t result = 0;

    if (U_SUCCESS(err))
    {
        result = ucol_getSortKey(pColl, lpStr, cwStrLength, sortKey, cbSortKeyLength);
    }

    return result;
}

extern "C" int32_t
CompareStringOrdinalIgnoreCase(const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length)
{
    assert(lpStr1 != nullptr);
    assert(cwStr1Length >= 0);
    assert(lpStr2 != nullptr);
    assert(cwStr2Length >= 0);

    int32_t str1Idx = 0;
    int32_t str2Idx = 0;

    while (str1Idx < cwStr1Length && str2Idx < cwStr2Length)
    {
        UChar32 str1Codepoint;
        UChar32 str2Codepoint;

        U16_NEXT(lpStr1, str1Idx, cwStr1Length, str1Codepoint);
        U16_NEXT(lpStr2, str2Idx, cwStr2Length, str2Codepoint);

        if (str1Codepoint != str2Codepoint && u_toupper(str1Codepoint) != u_toupper(str2Codepoint))
        {
            return str1Codepoint < str2Codepoint ? -1 : 1;
        }
    }

    if (cwStr1Length < cwStr2Length)
    {
        return -1;
    }

    if (cwStr2Length < cwStr1Length)
    {
        return 1;
    }

    return 0;
}
<commit_msg>Adding support for String CompareOptions IgnoreNonSpace and IgnoreSymbols.<commit_after>//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full
// license information.
//

#include <assert.h>
#include <stdint.h>
#include <map>
#include <unicode/uchar.h>
#include <unicode/ucol.h>
#include <unicode/usearch.h>
#include <unicode/utf16.h>

const int32_t CompareOptionsIgnoreCase = 1;
const int32_t CompareOptionsIgnoreNonSpace = 2;
const int32_t CompareOptionsIgnoreSymbols = 4;
// const int32_t CompareOptionsIgnoreKanaType = 8;
// const int32_t CompareOptionsIgnoreWidth = 0x10;
// const int32_t CompareOptionsStringSort = 0x20000000;

typedef std::map<int32_t, UCollator*> TCollatorMap;
typedef std::pair<int32_t, UCollator*> TCollatorMapPair;

/*
 * For increased performance, we cache the UCollator objects for a locale and
 * share them across threads. This is safe (and supported in ICU) if we ensure
 * multiple threads are only ever dealing with const UCollators.
 */
typedef struct _sort_handle
{
    UCollator* regular;
    TCollatorMap collatorsPerOption;

    _sort_handle() : regular(nullptr)
    {
    }

} SortHandle;

/*
 * The collator returned by this function is owned by the callee and must be
 * closed when this method returns with a U_SUCCESS UErrorCode.
 *
 * On error, the return value is undefined.
 */
UCollator* CloneCollatorWithOptions(const UCollator* pCollator, int32_t options, UErrorCode* pErr)
{
    UColAttributeValue strength = UCOL_DEFAULT;

    bool isIgnoreCase = (options & CompareOptionsIgnoreCase) == CompareOptionsIgnoreCase;
    bool isIgnoreNonSpace = (options & CompareOptionsIgnoreNonSpace) == CompareOptionsIgnoreNonSpace;
    bool isIgnoreSymbols = (options & CompareOptionsIgnoreSymbols) == CompareOptionsIgnoreSymbols;

    if (isIgnoreCase)
    {
        strength = UCOL_SECONDARY;
    }

    if (isIgnoreNonSpace)
    {
        strength = UCOL_PRIMARY;
    }

    UCollator* pClonedCollator = ucol_safeClone(pCollator, nullptr, nullptr, pErr);

    if (isIgnoreSymbols)
    {
        ucol_setAttribute(pClonedCollator, UCOL_ALTERNATE_HANDLING, UCOL_SHIFTED, pErr);
    }

    if (strength != UCOL_DEFAULT)
    {
        ucol_setAttribute(pClonedCollator, UCOL_STRENGTH, strength, pErr);

        // casing differs at the tertiary level.
        // if strength is less than tertiary, but we are not ignoring case, then we need to flip CASE_LEVEL On
        if (strength < UCOL_TERTIARY && !isIgnoreCase)
        {
            ucol_setAttribute(pClonedCollator, UCOL_CASE_LEVEL, UCOL_ON, pErr);
        }
    }

    return pClonedCollator;
}

extern "C" SortHandle* GetSortHandle(const char* lpLocaleName)
{
    SortHandle* pSortHandle = new SortHandle();

    UErrorCode err = U_ZERO_ERROR;

    pSortHandle->regular = ucol_open(lpLocaleName, &err);

    if (U_FAILURE(err))
    {
        if (pSortHandle->regular != nullptr)
              ucol_close(pSortHandle->regular);

        delete pSortHandle;
        pSortHandle = nullptr;
    }

    return pSortHandle;
}

extern "C" void CloseSortHandle(SortHandle* pSortHandle)
{
    ucol_close(pSortHandle->regular);
    pSortHandle->regular = nullptr;

    TCollatorMap::iterator it;
    for (it = pSortHandle->collatorsPerOption.begin(); it != pSortHandle->collatorsPerOption.end(); it++)
    {
        ucol_close(it->second);
    }

    delete pSortHandle;
}

const UCollator* GetCollatorFromSortHandle(SortHandle* pSortHandle, int32_t options, UErrorCode* pErr)
{
    UCollator* pCollator;
    if (options == 0)
    {
        pCollator = pSortHandle->regular;
    }
    else
    {
        TCollatorMap::iterator entry = pSortHandle->collatorsPerOption.find(options);
        if (entry == pSortHandle->collatorsPerOption.end())
        {
            pCollator = CloneCollatorWithOptions(pSortHandle->regular, options, pErr);
            pSortHandle->collatorsPerOption[options] = pCollator;
        }
        else
        {
            pCollator = entry->second;
        }
    }

    return pCollator;
}

/*
Function:
CompareString
*/
extern "C" int32_t CompareString(SortHandle* pSortHandle,
                                 const UChar* lpStr1,
                                 int32_t cwStr1Length,
                                 const UChar* lpStr2,
                                 int32_t cwStr2Length,
                                 int32_t options)
{
    static_assert(UCOL_EQUAL == 0, "managed side requires 0 for equal strings");
    static_assert(UCOL_LESS < 0, "managed side requires less than zero for a < b");
    static_assert(UCOL_GREATER > 0, "managed side requires greater than zero for a > b");

    UCollationResult result = UCOL_EQUAL;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        result = ucol_strcoll(pColl, lpStr1, cwStr1Length, lpStr2, cwStr2Length);
    }

    return result;
}

/*
Function:
IndexOf
*/
extern "C" int32_t
IndexOf(SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");

    int32_t result = USEARCH_DONE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);

        if (U_SUCCESS(err))
        {
            result = usearch_first(pSearch, &err);
            usearch_close(pSearch);
        }
    }

    return result;
}

/*
Function:
LastIndexOf
*/
extern "C" int32_t LastIndexOf(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    static_assert(USEARCH_DONE == -1, "managed side requires -1 for not found");

    int32_t result = USEARCH_DONE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);

        if (U_SUCCESS(err))
        {
            result = usearch_last(pSearch, &err);
            usearch_close(pSearch);
        }
    }

    return result;
}

/*
Static Function:
AreEqualOrdinalIgnoreCase
*/
static bool AreEqualOrdinalIgnoreCase(UChar32 one, UChar32 two)
{
    // Return whether the two characters are identical or would be identical if they were upper-cased.

    if (one == two)
    {
        return true;
    }

    if (one == 0x0131 || two == 0x0131)
    {
        // On Windows with InvariantCulture, the LATIN SMALL LETTER DOTLESS I (U+0131)
        // capitalizes to itself, whereas with ICU it capitalizes to LATIN CAPITAL LETTER I (U+0049).
        // We special case it to match the Windows invariant behavior.
        return false;
    }

    return u_toupper(one) == u_toupper(two);
}

/*
Function:
IndexOfOrdinalIgnoreCase
*/
extern "C" int32_t
IndexOfOrdinalIgnoreCase(
    const UChar* lpTarget, int32_t cwTargetLength,
    const UChar* lpSource, int32_t cwSourceLength,
    int32_t findLast)
{
    int32_t result = -1;

    int32_t endIndex = cwSourceLength - cwTargetLength;
    assert(endIndex >= 0);

    int32_t i = 0;
    while (i <= endIndex)
    {
        int32_t srcIdx = i, trgIdx = 0;
        const UChar *src = lpSource, *trg = lpTarget;
        UChar32 srcCodepoint, trgCodepoint;

        bool match = true;
        while (trgIdx < cwTargetLength)
        {
            U16_NEXT(src, srcIdx, cwSourceLength, srcCodepoint);
            U16_NEXT(trg, trgIdx, cwTargetLength, trgCodepoint);
            if (!AreEqualOrdinalIgnoreCase(srcCodepoint, trgCodepoint))
            {
                match = false;
                break;
            }
        }

        if (match)
        {
            result = i;
            if (!findLast)
            {
                break;
            }
        }

        U16_FWD_1(lpSource, i, cwSourceLength);
    }

    return result;
}

/*
 Return value is a "Win32 BOOL" (1 = true, 0 = false)
 */
extern "C" int32_t StartsWith(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    int32_t result = FALSE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);
        int32_t idx = USEARCH_DONE;

        if (U_SUCCESS(err))
        {
            idx = usearch_first(pSearch, &err);
            if (idx != USEARCH_DONE)
            {
                if (idx == 0)
                {
                    result = TRUE;
                }
                else
                {
                    UCollationElements* pCollElem = ucol_openElements(pColl, lpSource, idx, &err);

                    if (U_SUCCESS(err))
                    {
                        int32_t curCollElem = UCOL_NULLORDER;

                        result = TRUE;

                        while ((curCollElem = ucol_next(pCollElem, &err)) != UCOL_NULLORDER)
                        {
                            if (curCollElem != 0)
                            {
                                // Non ignorable collation element found between start of the
                                // string and the first match for lpTarget.
                                result = FALSE;
                                break;
                            }
                        }

                        if (U_FAILURE(err))
                        {
                            result = FALSE;
                        }

                        ucol_closeElements(pCollElem);
                    }
                }
            }

            usearch_close(pSearch);
        }
    }

    return result;
}

/*
 Return value is a "Win32 BOOL" (1 = true, 0 = false)
 */
extern "C" int32_t EndsWith(
    SortHandle* pSortHandle, const UChar* lpTarget, int32_t cwTargetLength, const UChar* lpSource, int32_t cwSourceLength, int32_t options)
{
    int32_t result = FALSE;
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);

    if (U_SUCCESS(err))
    {
        UStringSearch* pSearch = usearch_openFromCollator(lpTarget, cwTargetLength, lpSource, cwSourceLength, pColl, nullptr, &err);
        int32_t idx = USEARCH_DONE;

        if (U_SUCCESS(err))
        {
            idx = usearch_last(pSearch, &err);

            if (idx != USEARCH_DONE)
            {
                if ((idx + usearch_getMatchedLength(pSearch)) == cwSourceLength)
                {
                    result = TRUE;
                }

                // TODO (dotnet/corefx#3467): We should do something similar to what
                // StartsWith does where we can ignore
                // some collation elements at the end of the string if they are zero.
            }

            usearch_close(pSearch);
        }
    }

    return result;
}

extern "C" int32_t GetSortKey(SortHandle* pSortHandle,
                              const UChar* lpStr,
                              int32_t cwStrLength,
                              uint8_t* sortKey,
                              int32_t cbSortKeyLength,
                              int32_t options)
{
    UErrorCode err = U_ZERO_ERROR;
    const UCollator* pColl = GetCollatorFromSortHandle(pSortHandle, options, &err);
    int32_t result = 0;

    if (U_SUCCESS(err))
    {
        result = ucol_getSortKey(pColl, lpStr, cwStrLength, sortKey, cbSortKeyLength);
    }

    return result;
}

extern "C" int32_t
CompareStringOrdinalIgnoreCase(const UChar* lpStr1, int32_t cwStr1Length, const UChar* lpStr2, int32_t cwStr2Length)
{
    assert(lpStr1 != nullptr);
    assert(cwStr1Length >= 0);
    assert(lpStr2 != nullptr);
    assert(cwStr2Length >= 0);

    int32_t str1Idx = 0;
    int32_t str2Idx = 0;

    while (str1Idx < cwStr1Length && str2Idx < cwStr2Length)
    {
        UChar32 str1Codepoint;
        UChar32 str2Codepoint;

        U16_NEXT(lpStr1, str1Idx, cwStr1Length, str1Codepoint);
        U16_NEXT(lpStr2, str2Idx, cwStr2Length, str2Codepoint);

        if (str1Codepoint != str2Codepoint && u_toupper(str1Codepoint) != u_toupper(str2Codepoint))
        {
            return str1Codepoint < str2Codepoint ? -1 : 1;
        }
    }

    if (cwStr1Length < cwStr2Length)
    {
        return -1;
    }

    if (cwStr2Length < cwStr1Length)
    {
        return 1;
    }

    return 0;
}
<|endoftext|>