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

  Program: DICOM for VTK

  Copyright (c) 2012-2013 David Gobbi
  All rights reserved.
  See Copyright.txt or http://www.cognitive-antics.net/bsd3.txt for details.

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

=========================================================================*/

#include "vtkDICOMMetaData.h"
#include "vtkDICOMSorter.h"
#include "vtkDICOMReader.h"
#include "vtkDICOMToRAS.h"
#include "vtkNIFTIWriter.h"
#include "vtkMatrix4x4.h"
#include "vtkStringArray.h"
#include "vtkIntArray.h"

#include <vtkSmartPointer.h>

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

// The help for the application
void dicomtonifti_usage(const char *command_name)
{
  const char *cp = command_name + strlen(command_name);
  while (cp != command_name && cp[-1] != '\\' && cp[-1] != '/') { --cp; }

  fprintf(stderr,
    "usage: %s -o file.nii file1.dcm [file2.dcm ...]\n", cp);
  fprintf(stderr,
    "       %s -o directory --batch file1.dcm [file2.dcm ...]\n", cp);
  fprintf(stderr,
    "options:\n"
    "  -o <output.nii[.gz]>    The output file.\n"
    "  --no-slice-reordering   Never reorder the slices.\n"
    "  --no-row-reordering     Never reorder the rows.\n"
    "  --no-column-reordering  Never reorder the columns.\n"
    "  --no-qform              Don't include a qform in the NIFTI file.\n"
    "  --no-sform              Don't include an sform in the NIFTI file.\n"
    "  --batch                 Do multiple series at once.\n"
  );
  fprintf(stderr,
    "\n");
  fprintf(stderr,
    "This program will convert a DICOM series into a NIfTI file.\n"
    "\n"
    "It reads the DICOM Position and Orientation metadata, and uses this\n"
    "information to generate qform and sform entries for the NIfTI header,\n"
    "after doing a conversion from the DICOM coordinate system to the NIfTI\n"
    "coordinate system.\n"
    "\n"
    "By default, it will also reorder the columns of the image so that\n"
    "columns with higher indices are further to the patient\'s right (or\n"
    "in the case of sagittal images, further anterior).  Likewise, rows\n"
    "will be rearranged so that rows with higher indices are superior (or\n"
    "anterior for axial images).  Finally, it will reorder the slices\n"
    "so that the column direction, row direction, and slice direction\n"
    "follow the right-hand rule.\n"
    "\n"
    "If batch mode is enabled, then the filenames will automatically be\n"
    "generated from the series description in the DICOM meta data.\n"
  );
}

// Simple structure for command-line options
struct dicomtonifti_options
{
  bool no_slice_reordering;
  bool no_row_reordering;
  bool no_column_reordering;
  bool no_qform;
  bool no_sform;
  bool batch;
  const char *output;
};

// This program will convert DICOM to NIFTI
int main(int argc, char *argv[])
{
  int rval = 0;

  struct dicomtonifti_options options;
  options.no_slice_reordering = false;
  options.no_row_reordering = false;
  options.no_column_reordering = false;
  options.no_qform = false;
  options.no_sform = false;
  options.batch = false;
  options.output = 0;

  // for the list of input DICOM files
  vtkSmartPointer<vtkStringArray> files =
    vtkSmartPointer<vtkStringArray>::New();

  // read the options from the command line
  int argi = 1;
  while (argi < argc)
    {
    const char *arg = argv[argi++];
    if (arg[0] == '-')
      {
      if (strcmp(arg, "--") == 0)
        {
        // stop processing switches
        break;
        }
      else if (strcmp(arg, "--no-slice-reordering") == 0)
        {
        options.no_slice_reordering = true;
        }
      else if (strcmp(arg, "--no-row-reordering") == 0)
        {
        options.no_row_reordering = true;
        }
      else if (strcmp(arg, "--no-column-reordering") == 0)
        {
        options.no_column_reordering = true;
        }
      else if (strcmp(arg, "--no-qform") == 0)
        {
        options.no_qform = true;
        }
      else if (strcmp(arg, "--no-sform") == 0)
        {
        options.no_sform = true;
        }
      else if (strcmp(arg, "--batch") == 0)
        {
        options.batch = true;
        }
      else if (strncmp(arg, "-o", 2) == 0)
        {
        if (arg[2] != '\0')
          {
          arg += 2;
          }
        else
          {
          if (argi + 1 >= argc)
            {
            fprintf(stderr, "A file must follow the \'-o\' flag\n");
            dicomtonifti_usage(argv[0]);
            exit(1);
            }
          arg = argv[argi++];
          }
        options.output = arg;
        }
      }
    else
      {
      files->InsertNextValue(arg);
      }
    }

  while (argi < argc)
    {
    files->InsertNextValue(argv[argi++]);
    }

  // the output (NIFTI file or directory)
  const char *outfile = options.output;
  if (!outfile)
    {
    fprintf(stderr, "No output file was specified (\'-o\' <filename>).\n");
    dicomtonifti_usage(argv[0]);
    exit(1);
    }

  // make sure that input files were provided
  if (files->GetNumberOfValues() == 0)
    {
    fprintf(stderr, "No input files were specified.\n");
    dicomtonifti_usage(argv[0]);
    exit(1);
    }

  // sort the files by study and series
  vtkSmartPointer<vtkDICOMSorter> sorter =
    vtkSmartPointer<vtkDICOMSorter>::New();
  sorter->SetInputFileNames(files);
  sorter->Update();
  vtkStringArray *a = sorter->GetOutputFileNames();

  // read the files
  vtkSmartPointer<vtkDICOMReader> reader =
    vtkSmartPointer<vtkDICOMReader>::New();
  reader->SetMemoryRowOrderToFileNative();
  reader->SetFileNames(a);

  // check if slices were reordered by the reader
  vtkIntArray *fileIndices = reader->GetFileIndexArray();
  vtkIdType maxId = fileIndices->GetMaxId() + 1;
  bool slicesReordered = (maxId > 0 &&
    fileIndices->GetValue(0) > fileIndices->GetValue(maxId));

  // convert to NIFTI coordinate system
  vtkSmartPointer<vtkDICOMToRAS> converter =
    vtkSmartPointer<vtkDICOMToRAS>::New();
  converter->SetInputConnection(reader->GetOutputPort());
  converter->SetPatientMatrix(reader->GetPatientMatrix());
  converter->SetAllowRowReordering(!options.no_row_reordering);
  converter->SetAllowColumnReordering(!options.no_column_reordering);
  converter->UpdateMatrix();

  // check if slices have been reordered by vtkDICOMToRAS
  vtkSmartPointer<vtkMatrix4x4> checkMatrix =
    vtkSmartPointer<vtkMatrix4x4>::New();
  checkMatrix->DeepCopy(reader->GetPatientMatrix());
  // undo the DICOM to NIFTI x = -x, y = -y conversion in check matrix
  for (int j = 0; j < 4; j++)
    {
    checkMatrix->Element[0][j] = -checkMatrix->Element[0][j];
    checkMatrix->Element[1][j] = -checkMatrix->Element[1][j];
    }
  checkMatrix->Invert();
  // checkMatrix = PatientMatrix^(-1) * RASMatrix
  vtkMatrix4x4::Multiply4x4(
    checkMatrix, converter->GetRASMatrix(), checkMatrix);
  // if z is negative, slices were reordered by vtkDIOCOMToRAS
  slicesReordered ^= (checkMatrix->GetElement(2, 2) < -0.1);

  // prepare the writer to write the image
  vtkSmartPointer<vtkNIFTIWriter> writer =
    vtkSmartPointer<vtkNIFTIWriter>::New();
  writer->SetFileName(outfile);
  if (options.no_slice_reordering && slicesReordered)
    {
    // force NIFTI file to store images in original DICOM order
    writer->SetQFac(-1.0);
    }
  if (!options.no_qform)
    {
    writer->SetQFormMatrix(converter->GetRASMatrix());
    }
  if (!options.no_sform)
    {
    writer->SetSFormMatrix(converter->GetRASMatrix());
    }
  writer->SetInputConnection(converter->GetOutputPort());
  writer->Write();

  return rval;
}
<commit_msg>Improve error reporting by dicomtonifti.<commit_after>/*=========================================================================

  Program: DICOM for VTK

  Copyright (c) 2012-2013 David Gobbi
  All rights reserved.
  See Copyright.txt or http://www.cognitive-antics.net/bsd3.txt for details.

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

=========================================================================*/

#include "vtkDICOMMetaData.h"
#include "vtkDICOMSorter.h"
#include "vtkDICOMReader.h"
#include "vtkDICOMToRAS.h"
#include "vtkNIFTIWriter.h"

#include <vtkMatrix4x4.h>
#include <vtkStringArray.h>
#include <vtkIntArray.h>
#include <vtkErrorCode.h>
#include <vtkSmartPointer.h>

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

// The help for the application
void dicomtonifti_usage(const char *command_name)
{
  const char *cp = command_name + strlen(command_name);
  while (cp != command_name && cp[-1] != '\\' && cp[-1] != '/') { --cp; }

  fprintf(stderr,
    "usage: %s -o file.nii file1.dcm [file2.dcm ...]\n", cp);
  fprintf(stderr,
    "       %s -o directory --batch file1.dcm [file2.dcm ...]\n", cp);
  fprintf(stderr,
    "options:\n"
    "  -o <output.nii[.gz]>    The output file.\n"
    "  --no-slice-reordering   Never reorder the slices.\n"
    "  --no-row-reordering     Never reorder the rows.\n"
    "  --no-column-reordering  Never reorder the columns.\n"
    "  --no-qform              Don't include a qform in the NIFTI file.\n"
    "  --no-sform              Don't include an sform in the NIFTI file.\n"
    "  --batch                 Do multiple series at once.\n"
    "  --verbose               Verbose error reporting.\n"
  );
  fprintf(stderr,
    "\n");
  fprintf(stderr,
    "This program will convert a DICOM series into a NIfTI file.\n"
    "\n"
    "It reads the DICOM Position and Orientation metadata, and uses this\n"
    "information to generate qform and sform entries for the NIfTI header,\n"
    "after doing a conversion from the DICOM coordinate system to the NIfTI\n"
    "coordinate system.\n"
    "\n"
    "By default, it will also reorder the columns of the image so that\n"
    "columns with higher indices are further to the patient\'s right (or\n"
    "in the case of sagittal images, further anterior).  Likewise, rows\n"
    "will be rearranged so that rows with higher indices are superior (or\n"
    "anterior for axial images).  Finally, it will reorder the slices\n"
    "so that the column direction, row direction, and slice direction\n"
    "follow the right-hand rule.\n"
    "\n"
    "If batch mode is enabled, then the filenames will automatically be\n"
    "generated from the series description in the DICOM meta data.\n"
  );
}

// Print error
void dicomtonifti_check_error(vtkObject *o)
{
  vtkDICOMReader *reader = vtkDICOMReader::SafeDownCast(o);
  vtkDICOMSorter *sorter = vtkDICOMSorter::SafeDownCast(o);
  vtkNIFTIWriter *writer = vtkNIFTIWriter::SafeDownCast(o);
  const char *filename = 0;
  unsigned long errorcode = 0;
  if (writer)
    {
    filename = writer->GetFileName();
    errorcode = writer->GetErrorCode();
    }
  else if (reader)
    {
    filename = reader->GetInternalFileName();
    errorcode = reader->GetErrorCode();
    }
  else if (sorter)
    {
    filename = sorter->GetInternalFileName();
    errorcode = sorter->GetErrorCode();
    }
  if (!filename)
    {
    filename = "";
    }

  switch(errorcode)
    {
    case vtkErrorCode::NoError:
      return;
    case vtkErrorCode::FileNotFoundError:
      fprintf(stderr, "File not found: %s\n", filename);
      break;
    case vtkErrorCode::CannotOpenFileError:
      fprintf(stderr, "Cannot open file: %s\n", filename);
      break;
    case vtkErrorCode::UnrecognizedFileTypeError:
      fprintf(stderr, "Unrecognized file type: %s\n", filename);
      break;
    case vtkErrorCode::PrematureEndOfFileError:
      fprintf(stderr, "File is truncated: %s\n", filename);
      break;
    case vtkErrorCode::FileFormatError:
      fprintf(stderr, "Bad DICOM file: %s\n", filename);
      break;
    case vtkErrorCode::NoFileNameError:
      fprintf(stderr, "Output filename could not be used: %s\n", filename);
      break;
    case vtkErrorCode::OutOfDiskSpaceError:
      fprintf(stderr, "Out of disk space while writing file: %s\n", filename);
      break;
    default:
      fprintf(stderr, "An unknown error occurred.\n");
      break;
    }

  exit(1);
}

// Simple structure for command-line options
struct dicomtonifti_options
{
  bool no_slice_reordering;
  bool no_row_reordering;
  bool no_column_reordering;
  bool no_qform;
  bool no_sform;
  bool batch;
  bool verbose;
  const char *output;
};

// This program will convert DICOM to NIFTI
int main(int argc, char *argv[])
{
  int rval = 0;

  struct dicomtonifti_options options;
  options.no_slice_reordering = false;
  options.no_row_reordering = false;
  options.no_column_reordering = false;
  options.no_qform = false;
  options.no_sform = false;
  options.batch = false;
  options.verbose = false;
  options.output = 0;

  // for the list of input DICOM files
  vtkSmartPointer<vtkStringArray> files =
    vtkSmartPointer<vtkStringArray>::New();

  // read the options from the command line
  int argi = 1;
  while (argi < argc)
    {
    const char *arg = argv[argi++];
    if (arg[0] == '-')
      {
      if (strcmp(arg, "--") == 0)
        {
        // stop processing switches
        break;
        }
      else if (strcmp(arg, "--no-slice-reordering") == 0)
        {
        options.no_slice_reordering = true;
        }
      else if (strcmp(arg, "--no-row-reordering") == 0)
        {
        options.no_row_reordering = true;
        }
      else if (strcmp(arg, "--no-column-reordering") == 0)
        {
        options.no_column_reordering = true;
        }
      else if (strcmp(arg, "--no-qform") == 0)
        {
        options.no_qform = true;
        }
      else if (strcmp(arg, "--no-sform") == 0)
        {
        options.no_sform = true;
        }
      else if (strcmp(arg, "--batch") == 0)
        {
        options.batch = true;
        }
      else if (strcmp(arg, "--verbose") == 0)
        {
        options.verbose = true;
        }
      else if (strncmp(arg, "-o", 2) == 0)
        {
        if (arg[2] != '\0')
          {
          arg += 2;
          }
        else
          {
          if (argi + 1 >= argc)
            {
            fprintf(stderr, "A file must follow the \'-o\' flag\n");
            dicomtonifti_usage(argv[0]);
            exit(1);
            }
          arg = argv[argi++];
          }
        options.output = arg;
        }
      }
    else
      {
      files->InsertNextValue(arg);
      }
    }

  while (argi < argc)
    {
    files->InsertNextValue(argv[argi++]);
    }

  // silence VTK errors (we generate our own)
  vtkObject::SetGlobalWarningDisplay(options.verbose);

  // the output (NIFTI file or directory)
  const char *outfile = options.output;
  if (!outfile)
    {
    fprintf(stderr, "No output file was specified (\'-o\' <filename>).\n");
    dicomtonifti_usage(argv[0]);
    exit(1);
    }

  // make sure that input files were provided
  if (files->GetNumberOfValues() == 0)
    {
    fprintf(stderr, "No input files were specified.\n");
    dicomtonifti_usage(argv[0]);
    exit(1);
    }

  // sort the files by study and series
  vtkSmartPointer<vtkDICOMSorter> sorter =
    vtkSmartPointer<vtkDICOMSorter>::New();
  sorter->SetInputFileNames(files);
  sorter->Update();
  dicomtonifti_check_error(sorter);
  vtkStringArray *a = sorter->GetOutputFileNames();

  // read the files
  vtkSmartPointer<vtkDICOMReader> reader =
    vtkSmartPointer<vtkDICOMReader>::New();
  reader->SetMemoryRowOrderToFileNative();
  reader->SetFileNames(a);
  reader->Update();
  dicomtonifti_check_error(reader);

  // check if slices were reordered by the reader
  vtkIntArray *fileIndices = reader->GetFileIndexArray();
  vtkIdType maxId = fileIndices->GetMaxId() + 1;
  bool slicesReordered = (maxId > 0 &&
    fileIndices->GetValue(0) > fileIndices->GetValue(maxId));

  // convert to NIFTI coordinate system
  vtkSmartPointer<vtkDICOMToRAS> converter =
    vtkSmartPointer<vtkDICOMToRAS>::New();
  converter->SetInputConnection(reader->GetOutputPort());
  converter->SetPatientMatrix(reader->GetPatientMatrix());
  converter->SetAllowRowReordering(!options.no_row_reordering);
  converter->SetAllowColumnReordering(!options.no_column_reordering);
  converter->UpdateMatrix();

  // check if slices have been reordered by vtkDICOMToRAS
  vtkSmartPointer<vtkMatrix4x4> checkMatrix =
    vtkSmartPointer<vtkMatrix4x4>::New();
  checkMatrix->DeepCopy(reader->GetPatientMatrix());
  // undo the DICOM to NIFTI x = -x, y = -y conversion in check matrix
  for (int j = 0; j < 4; j++)
    {
    checkMatrix->Element[0][j] = -checkMatrix->Element[0][j];
    checkMatrix->Element[1][j] = -checkMatrix->Element[1][j];
    }
  checkMatrix->Invert();
  // checkMatrix = PatientMatrix^(-1) * RASMatrix
  vtkMatrix4x4::Multiply4x4(
    checkMatrix, converter->GetRASMatrix(), checkMatrix);
  // if z is negative, slices were reordered by vtkDIOCOMToRAS
  slicesReordered ^= (checkMatrix->GetElement(2, 2) < -0.1);

  // prepare the writer to write the image
  vtkSmartPointer<vtkNIFTIWriter> writer =
    vtkSmartPointer<vtkNIFTIWriter>::New();
  writer->SetFileName(outfile);
  if (options.no_slice_reordering && slicesReordered)
    {
    // force NIFTI file to store images in original DICOM order
    writer->SetQFac(-1.0);
    }
  if (!options.no_qform)
    {
    writer->SetQFormMatrix(converter->GetRASMatrix());
    }
  if (!options.no_sform)
    {
    writer->SetSFormMatrix(converter->GetRASMatrix());
    }
  writer->SetInputConnection(converter->GetOutputPort());
  writer->Write();
  dicomtonifti_check_error(writer);

  return rval;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
#include <string>
#include <vector>
#include <Chaos/IO/ColorIO.h>
#include "../../base/netops.h"

void run_client(void) {
}
<commit_msg>:sparkles: feat(echo): add select client for echo<commit_after>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions 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 materialsprovided with the
//    distribution.
//
// 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 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <unistd.h>
#include <iostream>
#include <string>
#include <vector>
#include "../../base/netops.h"

void run_client(void) {
  int sockfd = net::socket::open(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  struct sockaddr_in addr{};
  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  addr.sin_family = AF_INET;
  addr.sin_port = htons(5555);
  net::socket::connect(sockfd, (const struct sockaddr*)&addr);

  fd_set rset;
  FD_ZERO(&rset);
  for (;;) {
    int readfd = ::fileno(stdin);
    FD_SET(readfd, &rset);
    FD_SET(sockfd, &rset);
    auto maxfd = std::max(readfd, sockfd) + 1;

    if (net::io::select(maxfd, &rset, nullptr, nullptr, nullptr) < 0)
      break;

    if (FD_ISSET(sockfd, &rset)) {
      std::vector<char> buf(1024);
      if (net::socket::read(sockfd, buf.size(), buf.data()) < 0)
        break;

      std::cout << "from{127.0.0.1:5555} read: " << buf.data() << std::endl;
    }
    if (FD_ISSET(readfd, &rset)) {
      std::string buf;
      if (std::getline(std::cin, buf)) {
        if (buf == "exit")
          break;
        net::socket::write(sockfd, buf.data(), buf.size());
      }
      else {
        break;
      }
    }
  }
  net::socket::close(sockfd);
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "chrome/browser/debugger/devtools_http_protocol_handler.h"

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
#include "base/thread.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/debugger/devtools_client_host.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/devtools_messages.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "googleurl/src/gurl.h"
#include "net/base/io_buffer.h"
#include "net/base/listen_socket.h"
#include "net/server/http_server_request_info.h"
#include "net/url_request/url_request_context.h"

const int kBufferSize = 16 * 1024;

namespace {

// An internal implementation of DevToolsClientHost that delegates
// messages sent for DevToolsClient to a DebuggerShell instance.
class DevToolsClientHostImpl : public DevToolsClientHost {
 public:
  explicit DevToolsClientHostImpl(HttpListenSocket* socket)
      : socket_(socket) {}
  ~DevToolsClientHostImpl() {}

  // DevToolsClientHost interface
  virtual void InspectedTabClosing() {
    BrowserThread::PostTask(
        BrowserThread::IO,
        FROM_HERE,
        NewRunnableMethod(socket_,
                          &HttpListenSocket::Close));
  }

  virtual void SendMessageToClient(const IPC::Message& msg) {
    IPC_BEGIN_MESSAGE_MAP(DevToolsClientHostImpl, msg)
      IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
                          OnDispatchOnInspectorFrontend);
      IPC_MESSAGE_UNHANDLED_ERROR()
    IPC_END_MESSAGE_MAP()
  }

  void NotifyCloseListener() {
    DevToolsClientHost::NotifyCloseListener();
  }
 private:
  // Message handling routines
  void OnDispatchOnInspectorFrontend(const std::string& data) {
    socket_->SendOverWebSocket(data);
  }
  HttpListenSocket* socket_;
};

}

DevToolsHttpProtocolHandler::~DevToolsHttpProtocolHandler() {
  // Stop() must be called prior to this being called
  DCHECK(server_.get() == NULL);
}

void DevToolsHttpProtocolHandler::Start() {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Init));
}

void DevToolsHttpProtocolHandler::Stop() {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Teardown));
}

void DevToolsHttpProtocolHandler::OnHttpRequest(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& info) {
  if (info.path == "" || info.path == "/") {
    // Pages discovery request.
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        NewRunnableMethod(this,
                          &DevToolsHttpProtocolHandler::OnHttpRequestUI,
                          socket,
                          info));
    return;
  }

  size_t pos = info.path.find("/devtools/");
  if (pos != 0) {
    socket->Send404();
    return;
  }

  // Proxy static files from chrome://devtools/*.
  URLRequest* request = new URLRequest(GURL("chrome:/" + info.path), this);
  Bind(request, socket);
  request->set_context(
      Profile::GetDefaultRequestContext()->GetURLRequestContext());
  request->Start();
}

void DevToolsHttpProtocolHandler::OnWebSocketRequest(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnWebSocketRequestUI,
          socket,
          request));
}

void DevToolsHttpProtocolHandler::OnWebSocketMessage(HttpListenSocket* socket,
                                                     const std::string& data) {
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnWebSocketMessageUI,
          socket,
          data));
}

void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
  if (it != socket_to_requests_io_.end()) {
    // Dispose delegating socket.
    for (std::set<URLRequest*>::iterator it2 = it->second.begin();
         it2 != it->second.end(); ++it2) {
      URLRequest* request = *it2;
      request->Cancel();
      request_to_socket_io_.erase(request);
      request_to_buffer_io_.erase(request);
      delete request;
    }
    socket_to_requests_io_.erase(socket);
  }

  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnCloseUI,
          socket));
}

void DevToolsHttpProtocolHandler::OnHttpRequestUI(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& info) {
  std::string response = "";
  for (BrowserList::const_iterator it = BrowserList::begin(),
       end = BrowserList::end(); it != end; ++it) {
    TabStripModel* model = (*it)->tabstrip_model();
    for (int i = 0, size = model->count(); i < size; ++i) {
      TabContents* tab_contents = model->GetTabContentsAt(i);
      NavigationController& controller = tab_contents->controller();
      NavigationEntry* entry = controller.GetActiveEntry();
      if (entry == NULL)
        continue;

      if (!entry->url().is_valid())
        continue;

      DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
          GetDevToolsClientHostFor(tab_contents->render_view_host());
      if (!client_host) {
        response += StringPrintf(
            "%s (%s)
",
            controller.session_id().id(),
            UTF16ToUTF8(entry->title()).c_str(),
            entry->url().spec().c_str());
      } else {
        response += StringPrintf(
            "%s (%s)
",
            UTF16ToUTF8(entry->title()).c_str(),
            entry->url().spec().c_str());
      }
    }
  }
  response += "";
  Send200(socket, response, "text/html; charset=UTF-8");
}

void DevToolsHttpProtocolHandler::OnWebSocketRequestUI(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  std::string prefix = "/devtools/page/";
  size_t pos = request.path.find(prefix);
  if (pos != 0) {
    Send404(socket);
    return;
  }
  std::string page_id = request.path.substr(prefix.length());
  int id = 0;
  if (!base::StringToInt(page_id, &id)) {
    Send500(socket, "Invalid page id: " + page_id);
    return;
  }

  TabContents* tab_contents = GetTabContents(id);
  if (tab_contents == NULL) {
    Send500(socket, "No such page id: " + page_id);
    return;
  }

  DevToolsManager* manager = DevToolsManager::GetInstance();
  if (manager->GetDevToolsClientHostFor(tab_contents->render_view_host())) {
    Send500(socket, "Page with given id is being inspected: " + page_id);
    return;
  }

  DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl(socket);
  socket_to_client_host_ui_[socket] = client_host;

  manager->RegisterDevToolsClientHostFor(
      tab_contents->render_view_host(),
      client_host);
  AcceptWebSocket(socket, request);
}

void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
    HttpListenSocket* socket,
    const std::string& data) {
  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
  if (it == socket_to_client_host_ui_.end())
    return;

  DevToolsManager* manager = DevToolsManager::GetInstance();

  if (data == "loaded") {
    manager->ForwardToDevToolsAgent(
        it->second,
        DevToolsAgentMsg_FrontendLoaded());
    return;
  }

  manager->ForwardToDevToolsAgent(
      it->second,
      DevToolsAgentMsg_DispatchOnInspectorBackend(data));
}

void DevToolsHttpProtocolHandler::OnCloseUI(HttpListenSocket* socket) {
  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
  if (it == socket_to_client_host_ui_.end())
    return;
  DevToolsClientHostImpl* client_host =
      static_cast<DevToolsClientHostImpl*>(it->second);
  client_host->NotifyCloseListener();
  delete client_host;
  socket_to_client_host_ui_.erase(socket);
}

void DevToolsHttpProtocolHandler::OnResponseStarted(URLRequest* request) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;

  int expected_size = static_cast<int>(request->GetExpectedContentSize());

  std::string content_type;
  request->GetMimeType(&content_type);

  if (request->status().is_success()) {
    socket->Send(StringPrintf("HTTP/1.1 200 OK\r\n"
                              "Content-Type:%s\r\n"
                              "Content-Length:%d\r\n"
                              "\r\n",
                              content_type.c_str(),
                              expected_size));
  } else {
    socket->Send404();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  net::IOBuffer* buffer = request_to_buffer_io_[request].get();
  if (request->status().is_success())
    request->Read(buffer, kBufferSize, &bytes_read);
  OnReadCompleted(request, bytes_read);
}

void DevToolsHttpProtocolHandler::OnReadCompleted(URLRequest* request,
                                                  int bytes_read) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;

  net::IOBuffer* buffer = request_to_buffer_io_[request].get();
  do {
    if (!request->status().is_success() || bytes_read <= 0)
      break;
    socket->Send(buffer->data(), bytes_read);
  } while (request->Read(buffer, kBufferSize, &bytes_read));

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request->status().is_io_pending())
    RequestCompleted(request);
}

DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(int port)
    : port_(port),
      server_(NULL) {
}

void DevToolsHttpProtocolHandler::Init() {
  server_ = HttpListenSocket::Listen("127.0.0.1", port_, this);
}

// Run on I/O thread
void DevToolsHttpProtocolHandler::Teardown() {
  server_ = NULL;
}

void DevToolsHttpProtocolHandler::Bind(URLRequest* request,
                                       HttpListenSocket* socket) {
  request_to_socket_io_[request] = socket;
  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
  if (it == socket_to_requests_io_.end()) {
    std::pair<HttpListenSocket*, std::set<URLRequest*> > value(
        socket,
        std::set<URLRequest*>());
    it = socket_to_requests_io_.insert(value).first;
  }
  it->second.insert(request);
  request_to_buffer_io_[request] = new net::IOBuffer(kBufferSize);
}

void DevToolsHttpProtocolHandler::RequestCompleted(URLRequest* request) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;
  request_to_socket_io_.erase(request);
  SocketToRequestsMap::iterator it2 = socket_to_requests_io_.find(socket);
  it2->second.erase(request);
  request_to_buffer_io_.erase(request);
  delete request;
}

void DevToolsHttpProtocolHandler::Send200(HttpListenSocket* socket,
                                          const std::string& data,
                                          const std::string& mime_type) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send200,
                        data,
                        mime_type));
}

void DevToolsHttpProtocolHandler::Send404(HttpListenSocket* socket) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send404));
}

void DevToolsHttpProtocolHandler::Send500(HttpListenSocket* socket,
                                          const std::string& message) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send500,
                        message));
}

void DevToolsHttpProtocolHandler::AcceptWebSocket(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::AcceptWebSocket,
                        request));
}

TabContents* DevToolsHttpProtocolHandler::GetTabContents(int session_id) {
  for (BrowserList::const_iterator it = BrowserList::begin(),
       end = BrowserList::end(); it != end; ++it) {
    TabStripModel* model = (*it)->tabstrip_model();
    for (int i = 0, size = model->count(); i < size; ++i) {
      NavigationController& controller =
          model->GetTabContentsAt(i)->controller();
      if (controller.session_id().id() == session_id)
        return controller.tab_contents();
    }
  }
  return NULL;
}
<commit_msg>Use scoped_refptr for refcounted parameters in devtools.<commit_after>// Copyright (c) 2010 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 "chrome/browser/debugger/devtools_http_protocol_handler.h"

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
#include "base/thread.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/debugger/devtools_client_host.h"
#include "chrome/browser/debugger/devtools_manager.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/common/devtools_messages.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "googleurl/src/gurl.h"
#include "net/base/io_buffer.h"
#include "net/base/listen_socket.h"
#include "net/server/http_server_request_info.h"
#include "net/url_request/url_request_context.h"

const int kBufferSize = 16 * 1024;

namespace {

// An internal implementation of DevToolsClientHost that delegates
// messages sent for DevToolsClient to a DebuggerShell instance.
class DevToolsClientHostImpl : public DevToolsClientHost {
 public:
  explicit DevToolsClientHostImpl(HttpListenSocket* socket)
      : socket_(socket) {}
  ~DevToolsClientHostImpl() {}

  // DevToolsClientHost interface
  virtual void InspectedTabClosing() {
    BrowserThread::PostTask(
        BrowserThread::IO,
        FROM_HERE,
        NewRunnableMethod(socket_,
                          &HttpListenSocket::Close));
  }

  virtual void SendMessageToClient(const IPC::Message& msg) {
    IPC_BEGIN_MESSAGE_MAP(DevToolsClientHostImpl, msg)
      IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
                          OnDispatchOnInspectorFrontend);
      IPC_MESSAGE_UNHANDLED_ERROR()
    IPC_END_MESSAGE_MAP()
  }

  void NotifyCloseListener() {
    DevToolsClientHost::NotifyCloseListener();
  }
 private:
  // Message handling routines
  void OnDispatchOnInspectorFrontend(const std::string& data) {
    socket_->SendOverWebSocket(data);
  }
  HttpListenSocket* socket_;
};

}

DevToolsHttpProtocolHandler::~DevToolsHttpProtocolHandler() {
  // Stop() must be called prior to this being called
  DCHECK(server_.get() == NULL);
}

void DevToolsHttpProtocolHandler::Start() {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Init));
}

void DevToolsHttpProtocolHandler::Stop() {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(this, &DevToolsHttpProtocolHandler::Teardown));
}

void DevToolsHttpProtocolHandler::OnHttpRequest(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& info) {
  if (info.path == "" || info.path == "/") {
    // Pages discovery request.
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        NewRunnableMethod(this,
                          &DevToolsHttpProtocolHandler::OnHttpRequestUI,
                          make_scoped_refptr(socket),
                          info));
    return;
  }

  size_t pos = info.path.find("/devtools/");
  if (pos != 0) {
    socket->Send404();
    return;
  }

  // Proxy static files from chrome://devtools/*.
  URLRequest* request = new URLRequest(GURL("chrome:/" + info.path), this);
  Bind(request, socket);
  request->set_context(
      Profile::GetDefaultRequestContext()->GetURLRequestContext());
  request->Start();
}

void DevToolsHttpProtocolHandler::OnWebSocketRequest(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnWebSocketRequestUI,
          make_scoped_refptr(socket),
          request));
}

void DevToolsHttpProtocolHandler::OnWebSocketMessage(HttpListenSocket* socket,
                                                     const std::string& data) {
  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnWebSocketMessageUI,
          make_scoped_refptr(socket),
          data));
}

void DevToolsHttpProtocolHandler::OnClose(HttpListenSocket* socket) {
  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
  if (it != socket_to_requests_io_.end()) {
    // Dispose delegating socket.
    for (std::set<URLRequest*>::iterator it2 = it->second.begin();
         it2 != it->second.end(); ++it2) {
      URLRequest* request = *it2;
      request->Cancel();
      request_to_socket_io_.erase(request);
      request_to_buffer_io_.erase(request);
      delete request;
    }
    socket_to_requests_io_.erase(socket);
  }

  BrowserThread::PostTask(
      BrowserThread::UI,
      FROM_HERE,
      NewRunnableMethod(
          this,
          &DevToolsHttpProtocolHandler::OnCloseUI,
          make_scoped_refptr(socket)));
}

void DevToolsHttpProtocolHandler::OnHttpRequestUI(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& info) {
  std::string response = "";
  for (BrowserList::const_iterator it = BrowserList::begin(),
       end = BrowserList::end(); it != end; ++it) {
    TabStripModel* model = (*it)->tabstrip_model();
    for (int i = 0, size = model->count(); i < size; ++i) {
      TabContents* tab_contents = model->GetTabContentsAt(i);
      NavigationController& controller = tab_contents->controller();
      NavigationEntry* entry = controller.GetActiveEntry();
      if (entry == NULL)
        continue;

      if (!entry->url().is_valid())
        continue;

      DevToolsClientHost* client_host = DevToolsManager::GetInstance()->
          GetDevToolsClientHostFor(tab_contents->render_view_host());
      if (!client_host) {
        response += StringPrintf(
            "%s (%s)
",
            controller.session_id().id(),
            UTF16ToUTF8(entry->title()).c_str(),
            entry->url().spec().c_str());
      } else {
        response += StringPrintf(
            "%s (%s)
",
            UTF16ToUTF8(entry->title()).c_str(),
            entry->url().spec().c_str());
      }
    }
  }
  response += "";
  Send200(socket, response, "text/html; charset=UTF-8");
}

void DevToolsHttpProtocolHandler::OnWebSocketRequestUI(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  std::string prefix = "/devtools/page/";
  size_t pos = request.path.find(prefix);
  if (pos != 0) {
    Send404(socket);
    return;
  }
  std::string page_id = request.path.substr(prefix.length());
  int id = 0;
  if (!base::StringToInt(page_id, &id)) {
    Send500(socket, "Invalid page id: " + page_id);
    return;
  }

  TabContents* tab_contents = GetTabContents(id);
  if (tab_contents == NULL) {
    Send500(socket, "No such page id: " + page_id);
    return;
  }

  DevToolsManager* manager = DevToolsManager::GetInstance();
  if (manager->GetDevToolsClientHostFor(tab_contents->render_view_host())) {
    Send500(socket, "Page with given id is being inspected: " + page_id);
    return;
  }

  DevToolsClientHostImpl* client_host = new DevToolsClientHostImpl(socket);
  socket_to_client_host_ui_[socket] = client_host;

  manager->RegisterDevToolsClientHostFor(
      tab_contents->render_view_host(),
      client_host);
  AcceptWebSocket(socket, request);
}

void DevToolsHttpProtocolHandler::OnWebSocketMessageUI(
    HttpListenSocket* socket,
    const std::string& data) {
  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
  if (it == socket_to_client_host_ui_.end())
    return;

  DevToolsManager* manager = DevToolsManager::GetInstance();

  if (data == "loaded") {
    manager->ForwardToDevToolsAgent(
        it->second,
        DevToolsAgentMsg_FrontendLoaded());
    return;
  }

  manager->ForwardToDevToolsAgent(
      it->second,
      DevToolsAgentMsg_DispatchOnInspectorBackend(data));
}

void DevToolsHttpProtocolHandler::OnCloseUI(HttpListenSocket* socket) {
  SocketToClientHostMap::iterator it = socket_to_client_host_ui_.find(socket);
  if (it == socket_to_client_host_ui_.end())
    return;
  DevToolsClientHostImpl* client_host =
      static_cast<DevToolsClientHostImpl*>(it->second);
  client_host->NotifyCloseListener();
  delete client_host;
  socket_to_client_host_ui_.erase(socket);
}

void DevToolsHttpProtocolHandler::OnResponseStarted(URLRequest* request) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;

  int expected_size = static_cast<int>(request->GetExpectedContentSize());

  std::string content_type;
  request->GetMimeType(&content_type);

  if (request->status().is_success()) {
    socket->Send(StringPrintf("HTTP/1.1 200 OK\r\n"
                              "Content-Type:%s\r\n"
                              "Content-Length:%d\r\n"
                              "\r\n",
                              content_type.c_str(),
                              expected_size));
  } else {
    socket->Send404();
  }

  int bytes_read = 0;
  // Some servers may treat HEAD requests as GET requests.  To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  net::IOBuffer* buffer = request_to_buffer_io_[request].get();
  if (request->status().is_success())
    request->Read(buffer, kBufferSize, &bytes_read);
  OnReadCompleted(request, bytes_read);
}

void DevToolsHttpProtocolHandler::OnReadCompleted(URLRequest* request,
                                                  int bytes_read) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;

  net::IOBuffer* buffer = request_to_buffer_io_[request].get();
  do {
    if (!request->status().is_success() || bytes_read <= 0)
      break;
    socket->Send(buffer->data(), bytes_read);
  } while (request->Read(buffer, kBufferSize, &bytes_read));

  // See comments re: HEAD requests in OnResponseStarted().
  if (!request->status().is_io_pending())
    RequestCompleted(request);
}

DevToolsHttpProtocolHandler::DevToolsHttpProtocolHandler(int port)
    : port_(port),
      server_(NULL) {
}

void DevToolsHttpProtocolHandler::Init() {
  server_ = HttpListenSocket::Listen("127.0.0.1", port_, this);
}

// Run on I/O thread
void DevToolsHttpProtocolHandler::Teardown() {
  server_ = NULL;
}

void DevToolsHttpProtocolHandler::Bind(URLRequest* request,
                                       HttpListenSocket* socket) {
  request_to_socket_io_[request] = socket;
  SocketToRequestsMap::iterator it = socket_to_requests_io_.find(socket);
  if (it == socket_to_requests_io_.end()) {
    std::pair<HttpListenSocket*, std::set<URLRequest*> > value(
        socket,
        std::set<URLRequest*>());
    it = socket_to_requests_io_.insert(value).first;
  }
  it->second.insert(request);
  request_to_buffer_io_[request] = new net::IOBuffer(kBufferSize);
}

void DevToolsHttpProtocolHandler::RequestCompleted(URLRequest* request) {
  RequestToSocketMap::iterator it = request_to_socket_io_.find(request);
  if (it == request_to_socket_io_.end())
    return;

  HttpListenSocket* socket = it->second;
  request_to_socket_io_.erase(request);
  SocketToRequestsMap::iterator it2 = socket_to_requests_io_.find(socket);
  it2->second.erase(request);
  request_to_buffer_io_.erase(request);
  delete request;
}

void DevToolsHttpProtocolHandler::Send200(HttpListenSocket* socket,
                                          const std::string& data,
                                          const std::string& mime_type) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send200,
                        data,
                        mime_type));
}

void DevToolsHttpProtocolHandler::Send404(HttpListenSocket* socket) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send404));
}

void DevToolsHttpProtocolHandler::Send500(HttpListenSocket* socket,
                                          const std::string& message) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::Send500,
                        message));
}

void DevToolsHttpProtocolHandler::AcceptWebSocket(
    HttpListenSocket* socket,
    const HttpServerRequestInfo& request) {
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableMethod(socket,
                        &HttpListenSocket::AcceptWebSocket,
                        request));
}

TabContents* DevToolsHttpProtocolHandler::GetTabContents(int session_id) {
  for (BrowserList::const_iterator it = BrowserList::begin(),
       end = BrowserList::end(); it != end; ++it) {
    TabStripModel* model = (*it)->tabstrip_model();
    for (int i = 0, size = model->count(); i < size; ++i) {
      NavigationController& controller =
          model->GetTabContentsAt(i)->controller();
      if (controller.session_id().id() == session_id)
        return controller.tab_contents();
    }
  }
  return NULL;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 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 "chrome/browser/extensions/extension_install_ui_default.h"

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(USE_ASH)
#include "ash/shell.h"
#endif

using content::BrowserThread;
using content::WebContents;
using extensions::Extension;

namespace {

bool disable_failure_ui_for_tests = false;

// Helper class to put up an infobar when installation fails.
class ErrorInfobarDelegate : public ConfirmInfoBarDelegate {
 public:
  ErrorInfobarDelegate(InfoBarTabHelper* infobar_helper,
                       Browser* browser,
                       const extensions::CrxInstallerError& error)
      : ConfirmInfoBarDelegate(infobar_helper),
        browser_(browser),
        error_(error) {
  }

 private:
  virtual string16 GetMessageText() const OVERRIDE {
    return error_.message();
  }

  virtual int GetButtons() const OVERRIDE {
    return BUTTON_OK;
  }

  virtual string16 GetLinkText() const OVERRIDE {
    return error_.type() == extensions::CrxInstallerError::ERROR_OFF_STORE ?
        l10n_util::GetStringUTF16(IDS_LEARN_MORE) : ASCIIToUTF16("");
  }

  virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE {
    chrome::NavigateParams params(
        browser_,
        GURL("http://support.google.com/chrome_webstore/?p=crx_warning"),
        content::PAGE_TRANSITION_LINK);
    params.disposition = NEW_FOREGROUND_TAB;
    chrome::Navigate(&params);
    return false;
  }

  Browser* browser_;
  extensions::CrxInstallerError error_;
};

}  // namespace

ExtensionInstallUIDefault::ExtensionInstallUIDefault(Profile* profile)
    : skip_post_install_ui_(false),
      previous_using_native_theme_(false),
      use_app_installed_bubble_(false) {
  profile_ = profile;

  // |profile_| can be NULL during tests.
  if (profile_) {
    // Remember the current theme in case the user presses undo.
    const Extension* previous_theme =
        ThemeServiceFactory::GetThemeForProfile(profile);
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();
    previous_using_native_theme_ =
        ThemeServiceFactory::GetForProfile(profile)->UsingNativeTheme();
  }
}

ExtensionInstallUIDefault::~ExtensionInstallUIDefault() {
}

void ExtensionInstallUIDefault::OnInstallSuccess(const Extension* extension,
                                                 SkBitmap* icon) {
  if (skip_post_install_ui_)
    return;

  if (extension->is_theme()) {
    ShowThemeInfoBar(previous_theme_id_, previous_using_native_theme_,
                     extension, profile_);
    return;
  }

  // Extensions aren't enabled by default in incognito so we confirm
  // the install in a normal window.
  Profile* current_profile = profile_->GetOriginalProfile();
  Browser* browser = browser::FindOrCreateTabbedBrowser(current_profile);
  if (browser->tab_count() == 0)
    chrome::AddBlankTab(browser, true);
  browser->window()->Show();

  bool use_bubble_for_apps = false;

#if defined(TOOLKIT_VIEWS)
  CommandLine* cmdline = CommandLine::ForCurrentProcess();
  use_bubble_for_apps = (use_app_installed_bubble_ ||
                         cmdline->HasSwitch(switches::kAppsNewInstallBubble));
#endif

  if (extension->is_app() && !use_bubble_for_apps) {
    ExtensionInstallUI::OpenAppInstalledUI(browser, extension->id());
    return;
  }

  chrome::ShowExtensionInstalledBubble(extension, browser, *icon);
}

void ExtensionInstallUIDefault::OnInstallFailure(
    const extensions::CrxInstallerError& error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (disable_failure_ui_for_tests || skip_post_install_ui_)
    return;

  Browser* browser = browser::FindLastActiveWithProfile(profile_);
  WebContents* web_contents = chrome::GetActiveWebContents(browser);
  if (!web_contents)
    return;
  InfoBarTabHelper* infobar_helper =
      InfoBarTabHelper::FromWebContents(web_contents);
  infobar_helper->AddInfoBar(
      new ErrorInfobarDelegate(infobar_helper, browser, error));
}

void ExtensionInstallUIDefault::SetSkipPostInstallUI(bool skip_ui) {
  skip_post_install_ui_ = skip_ui;
}

void ExtensionInstallUIDefault::SetUseAppInstalledBubble(bool use_bubble) {
  use_app_installed_bubble_ = use_bubble;
}

// static
void ExtensionInstallUIDefault::ShowThemeInfoBar(
    const std::string& previous_theme_id, bool previous_using_native_theme,
    const Extension* new_theme, Profile* profile) {
  if (!new_theme->is_theme())
    return;

  // Get last active tabbed browser of profile.
  Browser* browser = browser::FindTabbedBrowserDeprecated(profile, true);
  if (!browser)
    return;

  WebContents* web_contents = chrome::GetActiveWebContents(browser);
  if (!web_contents)
    return;
  InfoBarTabHelper* infobar_helper =
      InfoBarTabHelper::FromWebContents(web_contents);

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (size_t i = 0; i < infobar_helper->GetInfoBarCount(); ++i) {
    InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i);
    ThemeInstalledInfoBarDelegate* theme_infobar =
        delegate->AsThemePreviewInfobarDelegate();
    if (theme_infobar) {
      // If the user installed the same theme twice, ignore the second install
      // and keep the first install info bar, so that they can easily undo to
      // get back the previous theme.
      if (theme_infobar->MatchesTheme(new_theme))
        return;
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate(
      web_contents, new_theme, previous_theme_id, previous_using_native_theme);

  if (old_delegate)
    infobar_helper->ReplaceInfoBar(old_delegate, new_delegate);
  else
    infobar_helper->AddInfoBar(new_delegate);
}

InfoBarDelegate* ExtensionInstallUIDefault::GetNewThemeInstalledInfoBarDelegate(
    WebContents* web_contents,
    const Extension* new_theme,
    const std::string& previous_theme_id,
    bool previous_using_native_theme) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  return new ThemeInstalledInfoBarDelegate(
      InfoBarTabHelper::FromWebContents(web_contents),
      profile->GetExtensionService(),
      ThemeServiceFactory::GetForProfile(profile),
      new_theme,
      previous_theme_id,
      previous_using_native_theme);
}

// static
ExtensionInstallUI* ExtensionInstallUI::Create(Profile* profile) {
  return new ExtensionInstallUIDefault(profile);
}

// static
void ExtensionInstallUI::OpenAppInstalledUI(Browser* browser,
                                            const std::string& app_id) {
  if (NewTabUI::ShouldShowApps()) {
    chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
        browser, GURL(chrome::kChromeUINewTabURL)));
    chrome::Navigate(&params);

    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
        content::Source<WebContents>(params.target_contents->web_contents()),
        content::Details<const std::string>(&app_id));
  } else {
#if defined(USE_ASH)
    ash::Shell::GetInstance()->ToggleAppList();

    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST,
        content::Source<Profile>(browser->profile()),
        content::Details<const std::string>(&app_id));
#else
    NOTREACHED();
#endif
  }
}

// static
void ExtensionInstallUI::DisableFailureUIForTests() {
  disable_failure_ui_for_tests = true;
}

// static
ExtensionInstallPrompt* ExtensionInstallUI::CreateInstallPromptWithBrowser(
    Browser* browser) {
  content::WebContents* web_contents = NULL;
  if (browser)
    web_contents = browser->tab_strip_model()->GetActiveWebContents();
  return new ExtensionInstallPrompt(web_contents);
}

// static
ExtensionInstallPrompt* ExtensionInstallUI::CreateInstallPromptWithProfile(
    Profile* profile) {
  Browser* browser = browser::FindLastActiveWithProfile(profile);
  return CreateInstallPromptWithBrowser(browser);
}
<commit_msg>Crash fix in ExtensionInstallUIDefault::OnInstallSuccess().<commit_after>// Copyright (c) 2012 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 "chrome/browser/extensions/extension_install_ui_default.h"

#include "base/command_line.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(USE_ASH)
#include "ash/shell.h"
#endif

using content::BrowserThread;
using content::WebContents;
using extensions::Extension;

namespace {

bool disable_failure_ui_for_tests = false;

// Helper class to put up an infobar when installation fails.
class ErrorInfobarDelegate : public ConfirmInfoBarDelegate {
 public:
  ErrorInfobarDelegate(InfoBarTabHelper* infobar_helper,
                       Browser* browser,
                       const extensions::CrxInstallerError& error)
      : ConfirmInfoBarDelegate(infobar_helper),
        browser_(browser),
        error_(error) {
  }

 private:
  virtual string16 GetMessageText() const OVERRIDE {
    return error_.message();
  }

  virtual int GetButtons() const OVERRIDE {
    return BUTTON_OK;
  }

  virtual string16 GetLinkText() const OVERRIDE {
    return error_.type() == extensions::CrxInstallerError::ERROR_OFF_STORE ?
        l10n_util::GetStringUTF16(IDS_LEARN_MORE) : ASCIIToUTF16("");
  }

  virtual bool LinkClicked(WindowOpenDisposition disposition) OVERRIDE {
    chrome::NavigateParams params(
        browser_,
        GURL("http://support.google.com/chrome_webstore/?p=crx_warning"),
        content::PAGE_TRANSITION_LINK);
    params.disposition = NEW_FOREGROUND_TAB;
    chrome::Navigate(&params);
    return false;
  }

  Browser* browser_;
  extensions::CrxInstallerError error_;
};

}  // namespace

ExtensionInstallUIDefault::ExtensionInstallUIDefault(Profile* profile)
    : skip_post_install_ui_(false),
      previous_using_native_theme_(false),
      use_app_installed_bubble_(false) {
  profile_ = profile;

  // |profile_| can be NULL during tests.
  if (profile_) {
    // Remember the current theme in case the user presses undo.
    const Extension* previous_theme =
        ThemeServiceFactory::GetThemeForProfile(profile);
    if (previous_theme)
      previous_theme_id_ = previous_theme->id();
    previous_using_native_theme_ =
        ThemeServiceFactory::GetForProfile(profile)->UsingNativeTheme();
  }
}

ExtensionInstallUIDefault::~ExtensionInstallUIDefault() {
}

void ExtensionInstallUIDefault::OnInstallSuccess(const Extension* extension,
                                                 SkBitmap* icon) {
  if (skip_post_install_ui_)
    return;

  if (!profile_) {
    // TODO(zelidrag): Figure out what exact conditions cause crash
    // http://crbug.com/159437 and write browser test to cover it.
    NOTREACHED();
    return;
  }

  if (extension->is_theme()) {
    ShowThemeInfoBar(previous_theme_id_, previous_using_native_theme_,
                     extension, profile_);
    return;
  }

  // Extensions aren't enabled by default in incognito so we confirm
  // the install in a normal window.
  Profile* current_profile = profile_->GetOriginalProfile();
  Browser* browser = browser::FindOrCreateTabbedBrowser(current_profile);
  if (browser->tab_count() == 0)
    chrome::AddBlankTab(browser, true);
  browser->window()->Show();

  bool use_bubble_for_apps = false;

#if defined(TOOLKIT_VIEWS)
  CommandLine* cmdline = CommandLine::ForCurrentProcess();
  use_bubble_for_apps = (use_app_installed_bubble_ ||
                         cmdline->HasSwitch(switches::kAppsNewInstallBubble));
#endif

  if (extension->is_app() && !use_bubble_for_apps) {
    ExtensionInstallUI::OpenAppInstalledUI(browser, extension->id());
    return;
  }

  chrome::ShowExtensionInstalledBubble(extension, browser, *icon);
}

void ExtensionInstallUIDefault::OnInstallFailure(
    const extensions::CrxInstallerError& error) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (disable_failure_ui_for_tests || skip_post_install_ui_)
    return;

  Browser* browser = browser::FindLastActiveWithProfile(profile_);
  WebContents* web_contents = chrome::GetActiveWebContents(browser);
  if (!web_contents)
    return;
  InfoBarTabHelper* infobar_helper =
      InfoBarTabHelper::FromWebContents(web_contents);
  infobar_helper->AddInfoBar(
      new ErrorInfobarDelegate(infobar_helper, browser, error));
}

void ExtensionInstallUIDefault::SetSkipPostInstallUI(bool skip_ui) {
  skip_post_install_ui_ = skip_ui;
}

void ExtensionInstallUIDefault::SetUseAppInstalledBubble(bool use_bubble) {
  use_app_installed_bubble_ = use_bubble;
}

// static
void ExtensionInstallUIDefault::ShowThemeInfoBar(
    const std::string& previous_theme_id, bool previous_using_native_theme,
    const Extension* new_theme, Profile* profile) {
  if (!new_theme->is_theme())
    return;

  // Get last active tabbed browser of profile.
  Browser* browser = browser::FindTabbedBrowserDeprecated(profile, true);
  if (!browser)
    return;

  WebContents* web_contents = chrome::GetActiveWebContents(browser);
  if (!web_contents)
    return;
  InfoBarTabHelper* infobar_helper =
      InfoBarTabHelper::FromWebContents(web_contents);

  // First find any previous theme preview infobars.
  InfoBarDelegate* old_delegate = NULL;
  for (size_t i = 0; i < infobar_helper->GetInfoBarCount(); ++i) {
    InfoBarDelegate* delegate = infobar_helper->GetInfoBarDelegateAt(i);
    ThemeInstalledInfoBarDelegate* theme_infobar =
        delegate->AsThemePreviewInfobarDelegate();
    if (theme_infobar) {
      // If the user installed the same theme twice, ignore the second install
      // and keep the first install info bar, so that they can easily undo to
      // get back the previous theme.
      if (theme_infobar->MatchesTheme(new_theme))
        return;
      old_delegate = delegate;
      break;
    }
  }

  // Then either replace that old one or add a new one.
  InfoBarDelegate* new_delegate = GetNewThemeInstalledInfoBarDelegate(
      web_contents, new_theme, previous_theme_id, previous_using_native_theme);

  if (old_delegate)
    infobar_helper->ReplaceInfoBar(old_delegate, new_delegate);
  else
    infobar_helper->AddInfoBar(new_delegate);
}

InfoBarDelegate* ExtensionInstallUIDefault::GetNewThemeInstalledInfoBarDelegate(
    WebContents* web_contents,
    const Extension* new_theme,
    const std::string& previous_theme_id,
    bool previous_using_native_theme) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  return new ThemeInstalledInfoBarDelegate(
      InfoBarTabHelper::FromWebContents(web_contents),
      profile->GetExtensionService(),
      ThemeServiceFactory::GetForProfile(profile),
      new_theme,
      previous_theme_id,
      previous_using_native_theme);
}

// static
ExtensionInstallUI* ExtensionInstallUI::Create(Profile* profile) {
  return new ExtensionInstallUIDefault(profile);
}

// static
void ExtensionInstallUI::OpenAppInstalledUI(Browser* browser,
                                            const std::string& app_id) {
  if (NewTabUI::ShouldShowApps()) {
    chrome::NavigateParams params(chrome::GetSingletonTabNavigateParams(
        browser, GURL(chrome::kChromeUINewTabURL)));
    chrome::Navigate(&params);

    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_APP_INSTALLED_TO_NTP,
        content::Source<WebContents>(params.target_contents->web_contents()),
        content::Details<const std::string>(&app_id));
  } else {
#if defined(USE_ASH)
    ash::Shell::GetInstance()->ToggleAppList();

    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_APP_INSTALLED_TO_APPLIST,
        content::Source<Profile>(browser->profile()),
        content::Details<const std::string>(&app_id));
#else
    NOTREACHED();
#endif
  }
}

// static
void ExtensionInstallUI::DisableFailureUIForTests() {
  disable_failure_ui_for_tests = true;
}

// static
ExtensionInstallPrompt* ExtensionInstallUI::CreateInstallPromptWithBrowser(
    Browser* browser) {
  content::WebContents* web_contents = NULL;
  if (browser)
    web_contents = browser->tab_strip_model()->GetActiveWebContents();
  return new ExtensionInstallPrompt(web_contents);
}

// static
ExtensionInstallPrompt* ExtensionInstallUI::CreateInstallPromptWithProfile(
    Profile* profile) {
  Browser* browser = browser::FindLastActiveWithProfile(profile);
  return CreateInstallPromptWithBrowser(browser);
}
<|endoftext|>


<commit_before>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground
 Mat acfg_t(256, 256, CV_8UC3, Scalar(0));
// accumulated foreground threshold

/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 100, 1, THRESH_BINARY_INV);
  dilate(gr_m, gr_m, ellipticKernel(43));
  gr_m = 1 - gr_m;
// change code later so we don't have to do this

//  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
  imshow("acbgm", acbg_m*255);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
// this completely doesn't work since acbg is wrong
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  threshold(fl_m, fl_m, 150, 1, THRESH_BINARY);
  int t1 = tracker1 + 1 - (tracker1%2);
  if (t1<3) t1 = 3;
  if (t1>90) t1 = 91;
  dilate(fl_m, fl_m, ellipticKernel(35));
  erode(fl_m, fl_m, ellipticKernel(51));

  imshow("flow mask", gray_256.mul(1-fl_m));
  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
// maybe just use fl_m? it's surprisingly good!
  bitwise_or(gr_m, bg_m, bg_m);
// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
  acbg = acbg.mul(1-bg_m3) + ((acbg+img_256)/2).mul(bg_m3);
  imshow("acbg", acbg);

  imshow("bg mask", gray_256.mul(1-bg_m));

/*
 // do some stuff with foreground and so on here

  Mat haar_m;
// bitwise_and(1 - bg_m, fg_m, haar_m);
  haar_m = 1 - bg_m;

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat thingy;
  resize(gray, thingy, Size(width/scale, height/scale));
  equalizeHist(thingy, thingy);
///////////////////
// need to change this after foreground stuff gets written

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  bitwise_and(haar_m, thingy, thingy);
/////////////////

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rect_image(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   rect_image += new_rect;
  }

  double min_val, max_val;
  minMaxLoc(rect_image, &min_val, &max_val);

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

  Mat rect_thresh;
  threshold(rect_image, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<commit_msg>hacking<commit_after>#include "webcam.hpp"
#include <chrono>

using namespace cv;
using namespace std;

Mat ellipticKernel(int width, int height = -1) {
 if (height==-1) {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,width), Point(width/2, width/2));
 } else {
  return getStructuringElement(MORPH_ELLIPSE,Size(width,height), Point(width/2, height/2));
 }
}

unsigned long long getMilliseconds() {
 return chrono::system_clock::now().time_since_epoch()/chrono::milliseconds(1);
}

int main (int argc, char** argv) {

/*****
 begin camera setup
*****/

 CvCapture* capture = 0;
 int width, height;

 capture = cvCaptureFromCAM(0);

 if (!capture) {
  printf("No camera detected!");
  return -1;
 }

 ifstream config_file (".config");

 if (config_file.is_open()) {
// does not support corrupted .config

  string line;
  getline(config_file, line);
  istringstream(line)>>width;
  getline(config_file, line);
  istringstream(line)>>height;
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, width);
  cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, height);

  config_file.close();

 } else {

  initResolutions();

  for (int i=36; i<150; i++) {
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, resolutions[i].width);
   cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, resolutions[i].height);
  }

  width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
  height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);

  ofstream config_file_out(".config");
  config_file_out << width;
  config_file_out << "\n";
  config_file_out << height;
  config_file_out << "\n";
  config_file_out.close();
 }

 for (int i = 0; i < 30; i++) {
  // capture some frames so exposure correction takes place
  cvQueryFrame(capture);
 }

/*****
 end camera setup
*****/

/*****
 filter setup
*****/

 Mat acbg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated background
 Mat acbg_m(256, 256, CV_8UC1, Scalar(0));
// accumulated background mask

 Mat acfg(256, 256, CV_8UC3, Scalar(0,0,0));
// accumulated foreground
 Mat acfg_t(256, 256, CV_8UC3, Scalar(0));
// accumulated foreground threshold

/*****
 end filter setup
*****/

/*****
 misc
*****/

 unsigned long long times[100];
 for (int i=0; i<100; i++)
  times[i] = 0;

 int tracker1, tracker2, tracker3;
 namedWindow("s",1);
 createTrackbar("1","s",&tracker1,100);
 createTrackbar("2","s",&tracker2,100);
 createTrackbar("3","s",&tracker3,100);

 unsigned long long timenow = getMilliseconds();

 bool keep_going = true;

 CascadeClassifier mouth_cascade;
 mouth_cascade.load("Mouth.xml");

/*****
 begin filter loop
*****/

 while (keep_going) {

  Mat image(cvQueryFrame(capture));
//  imshow("webcam", image);
// at some point preprocess by rotating according to OVR roll
// right now really annoying because of state variables

  Mat gray, img_256, gray_256;
  resize(image, img_256, Size(256, 256));
  cvtColor(image, gray, CV_RGB2GRAY);
  cvtColor(img_256, gray_256, CV_RGB2GRAY);

// this mask gets anything kind of dark (DK2) and dilates
// should work *great*
  Mat gr_m;
// gray mask
  equalizeHist(gray_256, gr_m);
  threshold(gr_m, gr_m, 100, 1, THRESH_BINARY_INV);
  dilate(gr_m, gr_m, ellipticKernel(43));
  int t1 = tracker1 + 1 - (tracker1%2);
  if (t1<3) t1 = 3;
  if (t1>90) t1 = 91;
  erode(gr_m, gr_m, ellipticKernel(t1));
  gr_m = 1 - gr_m;
// change code later so we don't have to do this

  imshow("gray mask", gray_256.mul(1-gr_m));

  bitwise_or(acbg_m, gr_m, acbg_m);
  imshow("acbgm", acbg_m*255);
//  imshow("accumulated bg mask", gray_256.mul(1-acbg_m));

// this mask watches for flow against accumulated bg
// this completely doesn't work since acbg is wrong
  Mat fl_m;
// flow mask
  absdiff(img_256, acbg, fl_m);
  cvtColor(fl_m, fl_m, CV_BGR2GRAY);
  fl_m = fl_m.mul(acbg_m);
  threshold(fl_m, fl_m, 150, 1, THRESH_BINARY);
//  dilate(fl_m, fl_m, ellipticKernel(35));
//  erode(fl_m, fl_m, ellipticKernel(51));

  imshow("flow mask", gray_256.mul(1-fl_m));
  Mat bg_m;
  bitwise_and(acbg_m, fl_m, bg_m);
  bitwise_or(gr_m, bg_m, bg_m);
// maybe do some morphological operations on bg_m?
// previously combined bg_m with its opening

// ugly way to compute:
// acbg = [acbg'.(1-bg_m)]+[((acbg'+img_256)/2).bg_m]
// find a nicer way later
// problem is masks are 1 channel while images are 3 channel

  Mat bg_m3;
  Mat tmp0[3];
  tmp0[0] = tmp0[1] = tmp0[2] = bg_m;
  merge(tmp0, 3, bg_m3);
  imshow("bg_m3", bg_m3);
  acbg = acbg.mul(1-bg_m3) + ((acbg+img_256)/2).mul(bg_m3);
  imshow("acbg", acbg);

  imshow("bg mask", gray_256.mul(1-bg_m));

/*
 // do some stuff with foreground and so on here

  Mat haar_m;
// bitwise_and(1 - bg_m, fg_m, haar_m);
  haar_m = 1 - bg_m;

// run haar classifier
  int scale = width/300;
  if (scale < 1)
   scale = 1;
// can't use 256x256 since haar isn't stretch invariant

  Mat thingy;
  resize(gray, thingy, Size(width/scale, height/scale));
  equalizeHist(thingy, thingy);
///////////////////
// need to change this after foreground stuff gets written

  vector<Rect> mouth_rects;
  resize(haar_m, haar_m, Size(width/scale, height/scale));

  bitwise_and(haar_m, thingy, thingy);
/////////////////

  mouth_cascade.detectMultiScale(thingy, mouth_rects, 1.1, 0, CV_HAAR_SCALE_IMAGE);
  Mat rect_image(height, width, CV_8UC1, Scalar(0));

  for (size_t i=0; i<mouth_rects.size(); i++) {
   Rect scaled(mouth_rects[i].x*scale, mouth_rects[i].y*scale, mouth_rects[i].width*scale,mouth_rects[i].height*scale);
   Mat new_rect(height, width, CV_8UC1, Scalar(0));
   rectangle(new_rect, scaled, Scalar(1), CV_FILLED);
   rect_image += new_rect;
  }

  double min_val, max_val;
  minMaxLoc(rect_image, &min_val, &max_val);

// or maybe equalize? this whole thing needs to be rewritten
// with the new fg and temporal coherence ideas

  Mat rect_thresh;
  threshold(rect_image, rect_thresh, max_val*0.9, 1, THRESH_BINARY);
  imshow("mouth", rect_thresh.mul(gray));

/*
  Moments m = moments(rect_thresh, 1);
  circle(image, Point(m.m10/m.m00,m.m01/m.m00),20,Scalar(128),30);
  imshow("centroid", image);
*/

  keep_going = (waitKey(1)<0);

 }

 cvReleaseCapture(&capture);

 return 0;
}

<|endoftext|>


<commit_before>// xmlhelp.cc
// support routines for XML reading/writing

#include "xmlhelp.h"            // this module
#include <stdlib.h>             // atof, atol
#include <ctype.h>              // isprint, isdigit, isxdigit
#include <stdio.h>              // sprintf
#include "strtokp.h"            // StrtokParse
#include "exc.h"                // xformat

string toXml_bool(bool b) {
  if (b) return "true";
  else return "false";
}

void fromXml_bool(bool &b, rostring str) {
  b = streq(str, "true");
}

string toXml_int(int i) {
  return stringc << i;
}

void fromXml_int(int &i, rostring str) {
  long i0 = strtol(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_long(long i) {
  return stringc << i;
}

void fromXml_long(long &i, rostring str) {
  long i0 = strtol(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_unsigned_int(unsigned int i) {
  return stringc << i;
}

void fromXml_unsigned_int(unsigned int &i, rostring str) {
  unsigned long i0 = strtoul(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_unsigned_long(unsigned long i) {
  return stringc << i;
}

void fromXml_unsigned_long(unsigned long &i, rostring str) {
  unsigned long i0 = strtoul(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_double(double x) {
  return stringc << x;
}

void fromXml_double(double &x, rostring str) {
  x = atof(str.c_str());
}

string toXml_SourceLoc(SourceLoc loc) {
  // NOTE: the nohashline here is very important; never change it
  return sourceLocManager->getString_nohashline(loc);
}

void fromXml_SourceLoc(SourceLoc &loc, rostring str) {
  // the file format is filename:line:column
  StrtokParse tok(str, ":");
  if ((int)tok != 3) {
    // FIX: this is a parsing error but I don't want to throw an
    // exception out of this library function
    loc = SL_UNKNOWN;
    return;
  }
  char const *file = tok[0];
  if (streq(file, "<noloc>")) {
    loc = SL_UNKNOWN;
    return;
  }
  if (streq(file, "<init>")) {
    loc = SL_INIT;
    return;
  }
  int line = atoi(tok[1]);
  int col  = atoi(tok[2]);
  loc = sourceLocManager->encodeLineCol(file, line, col);
}

//  void xmlPrintPointer(ostream &os, char const *label, void const *p)
//  {
//    if (!p) {
//      // sm: previously, the code for this function just inserted 'p'
//      // as a 'void const *', but that is nonportable, as gcc-3 inserts
//      // "0" while gcc-2 emits "(nil)"
//      os << label << "0";
//    }
//    else {
//      // sm: I question whether this is portable, but it may not matter
//      // since null pointers are the only ones that are treated
//      // specially (as far as I can tell)
//      os << label << p;
//    }
//  }

string xmlPrintPointer(char const *label, void const *p)
{
  stringBuilder sb;
  if (!p) {
    // sm: previously, the code for this function just inserted 'p'
    // as a 'void const *', but that is nonportable, as gcc-3 inserts
    // "0" while gcc-2 emits "(nil)"
    sb << label << "0";
  }
  else {
    // sm: I question whether this is portable, but it may not matter
    // since null pointers are the only ones that are treated
    // specially (as far as I can tell)
    sb << label;
    sb << stringBuilder::Hex(reinterpret_cast<long unsigned>(p));
  }
  return sb;
}

// named escape codes
#define lt_CODE "lt;"
#define gt_CODE "gt;"
#define amp_CODE "amp;"
#define quot_CODE "quot;"
int const lt_codelen   = strlen(lt_CODE);
int const gt_codelen   = strlen(gt_CODE);
int const amp_codelen  = strlen(amp_CODE);
int const quot_codelen = strlen(quot_CODE);

string xmlAttrQuote(rostring src) {
  return stringc << "\""
                 << xmlAttrEncode(src)
                 << "\"";
}

string xmlAttrEncode(rostring src) {
  return xmlAttrEncode(toCStr(src), strlen(src));
}

string xmlAttrEncode(char const *p, int len) {
  stringBuilder sb;

  for(int i=0; i<len; ++i) {
    unsigned char c = p[i];

    // escape those special to xml attributes;
    // http://www.w3.org/TR/2004/REC-xml-20040204/#NT-AttValue
    switch (c) {
    default: break;             // try below
    case '<': sb << "&" lt_CODE;   continue;
    case '>': sb << "&" gt_CODE;   continue; // this one not strictly required here
    case '&': sb << "&" amp_CODE;  continue;
    case '"': sb << "&" quot_CODE; continue;
    }

    // try itself
    if (isprint(c)) {
      sb << c;
      continue;
    }

    // use the most general notation
    char tmp[7];
    // dsw: the sillyness of XML knows no bounds: it is actually more
    // efficient to use the decimal encoding since sometimes you only
    // need 4 or 5 characters, whereas with hex you are guaranteed to
    // need 6, however the uniformity makes it easier to decode hex.
    // Why not make the shorter encoding also the default so that it
    // really is shorter in the big picture?
    sprintf(tmp, "&#x%02X;", c);
    sb << tmp;
  }

  return sb;
}

// dsw: based on smbase/strutil.cc/parseQuotedString();
string xmlAttrDeQuote(rostring text) {
  if (!( text[0] == '"' &&
         text[strlen(text)-1] == '"' )) {
    xformat(stringc << "quoted string is missing quotes: " << text);
  }

  // strip the quotes
  string noQuotes = substring(toCStr(text)+1, strlen(text)-2);

  // decode escapes
  ArrayStack<char> buf;
  xmlAttrDecode(buf, noQuotes, '"');
  buf.push(0 /*NUL*/);

  // return string contents up to first NUL, which isn't necessarily
  // the same as the one just pushed; by invoking this function, the
  // caller is accepting responsibility for this condition
  return string(buf.getArray());
}

void xmlAttrDecode(ArrayStack<char> &dest, rostring origSrc, char delim)
{
  char const *src = toCStr(origSrc);
  xmlAttrDecode(dest, src, delim);
}

void xmlAttrDecode(ArrayStack<char> &dest, char const *src, char delim)
{
  while (*src != '\0') {
    // check for newlines
    if (*src == '\n') {
      xformat("unescaped newline (unterminated string)");
    }

    // check for the delimiter
    if (*src == delim) {
      xformat(stringc << "unescaped delimiter (" << delim << ")");
    }

    // check for normal characters
    if (*src != '&') {
      // normal character
      dest.push(*src);
      src++;
      continue;
    }
    src++;                      // advance past amperstand

    // checked for named escape codes
#define DO_ESCAPE(NAME, CHAR) \
    if (strncmp(NAME ##_CODE, src, NAME ##_codelen) == 0) { \
      dest.push(CHAR); \
      src += NAME ##_codelen; \
      continue; \
    }
    DO_ESCAPE(lt,   '<');
    DO_ESCAPE(gt,   '>');
    DO_ESCAPE(amp,  '&');
    DO_ESCAPE(quot, '"');
#undef DO_ESCAPE

    // check for numerical escapes
    if (*src != '#') {
      xformat(stringc << "use of an unimplemented or illegal amperstand escape (" << *src << ")");
    }
    ++src;

    // process decimal and hex escapes: decimal '&#DDD;' where D is a
    // decimal digit or hexadecimal '&#xHH;' where H is a hex digit.
    if (!(*src == 'x' || isdigit(*src))) {
      xformat(stringc << "illegal charcter after '&#' (" << *src << ")");
    }

    // are we doing hex or decimal processing?
    //
    // http://www.w3.org/TR/2004/REC-xml-20040204/#NT-CharRef "If the
    // character reference begins with "&#x", the digits and letters
    // up to the terminating ; provide a hexadecimal representation of
    // the character's code point in ISO/IEC 10646. If it begins just
    // with "&#", the digits up to the terminating ; provide a decimal
    // representation of the character's code point."
    bool hex = (*src == 'x');
    if (hex) {
      src++;

      // strtoul is willing to skip leading whitespace, so I need
      // to catch it myself
      if (!isxdigit(*src)) {
        // dsw: NOTE: in the non-hex case, the leading digit has
        // already been seen
        xformat("non-hex digit following '&#x' escape");
      }
      xassert(isxdigit(*src));
    } else {
      xassert(isdigit(*src));
    }

    // parse the digit
    char const *endptr;
    unsigned long val = strtoul(src, (char**)&endptr, hex? 16 : 10);
    if (src == endptr) {
      // this can't happen with the octal escapes because
      // there is always at least one valid digit
      xformat("invalid '&#' escape");
    }

    // keep it
    dest.push((char)(unsigned char)val);    // possible truncation..
    src = endptr;
  }
}
<commit_msg>deleted some dead code<commit_after>// xmlhelp.cc
// support routines for XML reading/writing

#include "xmlhelp.h"            // this module
#include <stdlib.h>             // atof, atol
#include <ctype.h>              // isprint, isdigit, isxdigit
#include <stdio.h>              // sprintf
#include "strtokp.h"            // StrtokParse
#include "exc.h"                // xformat

string toXml_bool(bool b) {
  if (b) return "true";
  else return "false";
}

void fromXml_bool(bool &b, rostring str) {
  b = streq(str, "true");
}

string toXml_int(int i) {
  return stringc << i;
}

void fromXml_int(int &i, rostring str) {
  long i0 = strtol(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_long(long i) {
  return stringc << i;
}

void fromXml_long(long &i, rostring str) {
  long i0 = strtol(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_unsigned_int(unsigned int i) {
  return stringc << i;
}

void fromXml_unsigned_int(unsigned int &i, rostring str) {
  unsigned long i0 = strtoul(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_unsigned_long(unsigned long i) {
  return stringc << i;
}

void fromXml_unsigned_long(unsigned long &i, rostring str) {
  unsigned long i0 = strtoul(str.c_str(), NULL, 10);
  i = i0;
}

string toXml_double(double x) {
  return stringc << x;
}

void fromXml_double(double &x, rostring str) {
  x = atof(str.c_str());
}

string toXml_SourceLoc(SourceLoc loc) {
  // NOTE: the nohashline here is very important; never change it
  return sourceLocManager->getString_nohashline(loc);
}

void fromXml_SourceLoc(SourceLoc &loc, rostring str) {
  // the file format is filename:line:column
  StrtokParse tok(str, ":");
  if ((int)tok != 3) {
    // FIX: this is a parsing error but I don't want to throw an
    // exception out of this library function
    loc = SL_UNKNOWN;
    return;
  }
  char const *file = tok[0];
  if (streq(file, "<noloc>")) {
    loc = SL_UNKNOWN;
    return;
  }
  if (streq(file, "<init>")) {
    loc = SL_INIT;
    return;
  }
  int line = atoi(tok[1]);
  int col  = atoi(tok[2]);
  loc = sourceLocManager->encodeLineCol(file, line, col);
}

string xmlPrintPointer(char const *label, void const *p)
{
  stringBuilder sb;
  if (!p) {
    // sm: previously, the code for this function just inserted 'p'
    // as a 'void const *', but that is nonportable, as gcc-3 inserts
    // "0" while gcc-2 emits "(nil)"
    sb << label << "0";
  }
  else {
    // sm: I question whether this is portable, but it may not matter
    // since null pointers are the only ones that are treated
    // specially (as far as I can tell)
    sb << label;
    sb << stringBuilder::Hex(reinterpret_cast<long unsigned>(p));
  }
  return sb;
}

// named escape codes
#define lt_CODE "lt;"
#define gt_CODE "gt;"
#define amp_CODE "amp;"
#define quot_CODE "quot;"
int const lt_codelen   = strlen(lt_CODE);
int const gt_codelen   = strlen(gt_CODE);
int const amp_codelen  = strlen(amp_CODE);
int const quot_codelen = strlen(quot_CODE);

string xmlAttrQuote(rostring src) {
  return stringc << "\""
                 << xmlAttrEncode(src)
                 << "\"";
}

string xmlAttrEncode(rostring src) {
  return xmlAttrEncode(toCStr(src), strlen(src));
}

string xmlAttrEncode(char const *p, int len) {
  stringBuilder sb;

  for(int i=0; i<len; ++i) {
    unsigned char c = p[i];

    // escape those special to xml attributes;
    // http://www.w3.org/TR/2004/REC-xml-20040204/#NT-AttValue
    switch (c) {
    default: break;             // try below
    case '<': sb << "&" lt_CODE;   continue;
    case '>': sb << "&" gt_CODE;   continue; // this one not strictly required here
    case '&': sb << "&" amp_CODE;  continue;
    case '"': sb << "&" quot_CODE; continue;
    }

    // try itself
    if (isprint(c)) {
      sb << c;
      continue;
    }

    // use the most general notation
    char tmp[7];
    // dsw: the sillyness of XML knows no bounds: it is actually more
    // efficient to use the decimal encoding since sometimes you only
    // need 4 or 5 characters, whereas with hex you are guaranteed to
    // need 6, however the uniformity makes it easier to decode hex.
    // Why not make the shorter encoding also the default so that it
    // really is shorter in the big picture?
    sprintf(tmp, "&#x%02X;", c);
    sb << tmp;
  }

  return sb;
}

// dsw: based on smbase/strutil.cc/parseQuotedString();
string xmlAttrDeQuote(rostring text) {
  if (!( text[0] == '"' &&
         text[strlen(text)-1] == '"' )) {
    xformat(stringc << "quoted string is missing quotes: " << text);
  }

  // strip the quotes
  string noQuotes = substring(toCStr(text)+1, strlen(text)-2);

  // decode escapes
  ArrayStack<char> buf;
  xmlAttrDecode(buf, noQuotes, '"');
  buf.push(0 /*NUL*/);

  // return string contents up to first NUL, which isn't necessarily
  // the same as the one just pushed; by invoking this function, the
  // caller is accepting responsibility for this condition
  return string(buf.getArray());
}

void xmlAttrDecode(ArrayStack<char> &dest, rostring origSrc, char delim)
{
  char const *src = toCStr(origSrc);
  xmlAttrDecode(dest, src, delim);
}

void xmlAttrDecode(ArrayStack<char> &dest, char const *src, char delim)
{
  while (*src != '\0') {
    // check for newlines
    if (*src == '\n') {
      xformat("unescaped newline (unterminated string)");
    }

    // check for the delimiter
    if (*src == delim) {
      xformat(stringc << "unescaped delimiter (" << delim << ")");
    }

    // check for normal characters
    if (*src != '&') {
      // normal character
      dest.push(*src);
      src++;
      continue;
    }
    src++;                      // advance past amperstand

    // checked for named escape codes
#define DO_ESCAPE(NAME, CHAR) \
    if (strncmp(NAME ##_CODE, src, NAME ##_codelen) == 0) { \
      dest.push(CHAR); \
      src += NAME ##_codelen; \
      continue; \
    }
    DO_ESCAPE(lt,   '<');
    DO_ESCAPE(gt,   '>');
    DO_ESCAPE(amp,  '&');
    DO_ESCAPE(quot, '"');
#undef DO_ESCAPE

    // check for numerical escapes
    if (*src != '#') {
      xformat(stringc << "use of an unimplemented or illegal amperstand escape (" << *src << ")");
    }
    ++src;

    // process decimal and hex escapes: decimal '&#DDD;' where D is a
    // decimal digit or hexadecimal '&#xHH;' where H is a hex digit.
    if (!(*src == 'x' || isdigit(*src))) {
      xformat(stringc << "illegal charcter after '&#' (" << *src << ")");
    }

    // are we doing hex or decimal processing?
    //
    // http://www.w3.org/TR/2004/REC-xml-20040204/#NT-CharRef "If the
    // character reference begins with "&#x", the digits and letters
    // up to the terminating ; provide a hexadecimal representation of
    // the character's code point in ISO/IEC 10646. If it begins just
    // with "&#", the digits up to the terminating ; provide a decimal
    // representation of the character's code point."
    bool hex = (*src == 'x');
    if (hex) {
      src++;

      // strtoul is willing to skip leading whitespace, so I need
      // to catch it myself
      if (!isxdigit(*src)) {
        // dsw: NOTE: in the non-hex case, the leading digit has
        // already been seen
        xformat("non-hex digit following '&#x' escape");
      }
      xassert(isxdigit(*src));
    } else {
      xassert(isdigit(*src));
    }

    // parse the digit
    char const *endptr;
    unsigned long val = strtoul(src, (char**)&endptr, hex? 16 : 10);
    if (src == endptr) {
      // this can't happen with the octal escapes because
      // there is always at least one valid digit
      xformat("invalid '&#' escape");
    }

    // keep it
    dest.push((char)(unsigned char)val);    // possible truncation..
    src = endptr;
  }
}
<|endoftext|>


<commit_before>#include "ReverseLinkedListII.hpp"

ListNode *ReverseLinkedListII::reverseBetween(ListNode *head, int m, int n) {
    ListNode *rprev = nullptr;
    ListNode *rhead = head;

    for (int i = 1; i < m; i++) {
        rprev = rhead;
        rhead = rhead->next;
    }

    ListNode *p1 = rhead, *p2 = rhead->next;

    for (int j = m; j <= n - 1; j++) {
        ListNode *tmp = p2->next;
        p2->next = p1;
        p1 = p2;
        p2 = tmp;
    }

    rhead->next = p2;

    if (rprev != nullptr)
        rprev->next = p1;
    else
        head = p1;

    return head;
}
<commit_msg>Refine Problem 92. Reverse Linked List II<commit_after>#include "ReverseLinkedListII.hpp"

ListNode *ReverseLinkedListII::reverseBetween(ListNode *head, int m, int n) {
    if (head == nullptr) return head;

    ListNode dummyHead(0);
    dummyHead.next = head;

    ListNode *prev = &dummyHead;
    for (int i = 0; i < m - 1; i++)
        prev = prev->next;

    ListNode *start = prev->next;
    ListNode *a = start;
    ListNode *b = a->next;

    for (int i = 0; i < n - m; i++) {
        ListNode *bnext = b->next;
        b->next = a;
        a = b;
        b = bnext;
    }

    prev->next = a;
    start->next = b;

    return dummyHead.next;
}
<|endoftext|>