<commit_before>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkTileGrid.h"
#include "SkTileGridPicture.h"
#include "Test.h"

enum Tile {
    kTopLeft_Tile = 0x1,
    kTopRight_Tile = 0x2,
    kBottomLeft_Tile = 0x4,
    kBottomRight_Tile = 0x8,

    kAll_Tile = kTopLeft_Tile | kTopRight_Tile | kBottomLeft_Tile | kBottomRight_Tile,
};

static void verifyTileHits(skiatest::Reporter* reporter, SkIRect rect,
                           uint32_t tileMask, int borderPixels = 0) {
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.set(borderPixels, borderPixels);
    info.fOffset.setZero();
    info.fTileInterval.set(10 - 2 * borderPixels, 10 - 2 * borderPixels);
    SkTileGrid grid(2, 2, info, NULL);
    grid.insert(NULL, rect, false);
    REPORTER_ASSERT(reporter, grid.tileCount(0, 0) ==
                    ((tileMask & kTopLeft_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(1, 0) ==
                    ((tileMask & kTopRight_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(0, 1) ==
                    ((tileMask & kBottomLeft_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(1, 1) ==
                    ((tileMask & kBottomRight_Tile)? 1 : 0));
}

static SkIRect query(float x, float y, float w, float h) {
    // inflate for the margin++ in tilegrid
    SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
    SkIRect r;
    bounds.roundOut(&r);
    r.outset(1, 1); // to counteract the inset in SkTileGrid::search
    return r;
}

DEF_TEST(TileGrid_UnalignedQuery, reporter) {
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.setEmpty();
    info.fOffset.setZero();
    info.fTileInterval.set(10, 10);
    SkIRect rect1 = SkIRect::MakeXYWH(0, 0, 8, 8);
    SkIRect rect2 = SkIRect::MakeXYWH(11, 11, 1, 1);
    SkTileGrid grid(2, 2, info, SkTileGridNextDatum<SkPictureStateTree::Draw>);
    grid.insert(&rect1, rect1, true);
    grid.insert(&rect2, rect2, true);

    // Test parts of top-left tile
    {
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(7.99f, 7.99f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
    }
    // Corner overlap
    {
        SkTDArray<void*> rects;
        grid.search(query(9.5f, 9.5f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
        REPORTER_ASSERT(reporter, &rect2 == rects[1]);
    }
    // Intersect bottom right tile, but does not overlap rect 2
    {
        SkTDArray<void*> rects;
        grid.search(query(16.0f, 16.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect2 == rects[0]);
    }
    // Out of bounds queries, snap to border tiles
    {
        SkTDArray<void*> rects;
        grid.search(query(-2.0f, 0.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(0.0f, -2.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(22.0f, 16.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect2 == rects[0]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(16.0f, 22.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect2 == rects[0]);
    }
}

DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
    // Use SkTileGridPicture to generate a SkTileGrid with a helper
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.set(1, 1);
    info.fOffset.set(-1, -1);
    info.fTileInterval.set(8, 8);

    // rect landing entirely in top left tile
    SkIRect rect1 = SkIRect::MakeXYWH(0, 0, 1, 1);
    // rect landing entirely in center tile
    SkIRect rect2 = SkIRect::MakeXYWH(12, 12, 1, 1);
    // rect landing entirely in bottomright tile
    SkIRect rect3 = SkIRect::MakeXYWH(19, 19, 1, 1);
    SkTileGrid grid(3, 3, info, SkTileGridNextDatum<SkPictureStateTree::Draw>);
    grid.insert(&rect1, rect1, true);
    grid.insert(&rect2, rect2, true);
    grid.insert(&rect3, rect3, true);

    // Test parts of top-left tile
    {
        // The offset should cancel the top and left borders of the top left tile
        // So a look-up at interval 0-10 should be grid aligned,
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
    }
    {
        // Encroaching border by one pixel
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 11.0f, 11.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
        REPORTER_ASSERT(reporter, &rect2 == rects[1]);
    }
    {
        // Tile stride is 8 (tileWidth - 2 * border pixels
        // so translating by 8, should make query grid-aligned
        // with middle tile.
        SkTDArray<void*> rects;
        grid.search(query(8.0f, 8.0f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, &rect2 == rects[0]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(7.9f, 7.9f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, &rect1 == rects[0]);
        REPORTER_ASSERT(reporter, &rect2 == rects[1]);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(8.1f, 8.1f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, &rect2 == rects[0]);
        REPORTER_ASSERT(reporter, &rect3 == rects[1]);
    }
    {
        // Regression test for crbug.com/234688
        // Once the 2x2 device region is inset by margin, it yields an empty
        // adjusted region, sitting right on top of the tile boundary.
        SkTDArray<void*> rects;
        grid.search(query(8.0f, 8.0f, 2.0f, 2.0f), &rects);
        // This test passes by not asserting. We do not validate the rects recorded
        // because the result is numerically unstable (floating point equality).
        // The content of any one of the four tiles of the tilegrid would be a valid
        // result since any bbox that covers the center point of the canvas will be
        // recorded in all four tiles.
    }
}

DEF_TEST(TileGrid, reporter) {
    // Out of bounds
    verifyTileHits(reporter, SkIRect::MakeXYWH(30, 0, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 30, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(-10, 0, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, -10, 1, 1),  0);

    // Dilation for AA consideration
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 9, 9),  kTopLeft_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 10, 10),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(9, 9, 1, 1),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(11, 11, 1, 1),  kBottomRight_Tile);

    // BorderPixels
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 6, 6),  kTopLeft_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 7, 7),  kAll_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(9, 9, 1, 1),  kAll_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1),  kBottomRight_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(17, 17, 1, 1),  kBottomRight_Tile, 1);

    // BBoxes that overlap tiles
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 1),  kTopLeft_Tile | kTopRight_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 1, 10),  kTopLeft_Tile |
                   kBottomLeft_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 10),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(-10, -10, 40, 40),  kAll_Tile);
}
<commit_msg>Fix result order reliance<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkBitmapDevice.h"
#include "SkCanvas.h"
#include "SkTileGrid.h"
#include "SkTileGridPicture.h"
#include "Test.h"

enum Tile {
    kTopLeft_Tile = 0x1,
    kTopRight_Tile = 0x2,
    kBottomLeft_Tile = 0x4,
    kBottomRight_Tile = 0x8,

    kAll_Tile = kTopLeft_Tile | kTopRight_Tile | kBottomLeft_Tile | kBottomRight_Tile,
};

static void verifyTileHits(skiatest::Reporter* reporter, SkIRect rect,
                           uint32_t tileMask, int borderPixels = 0) {
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.set(borderPixels, borderPixels);
    info.fOffset.setZero();
    info.fTileInterval.set(10 - 2 * borderPixels, 10 - 2 * borderPixels);
    SkTileGrid grid(2, 2, info, NULL);
    grid.insert(NULL, rect, false);
    REPORTER_ASSERT(reporter, grid.tileCount(0, 0) ==
                    ((tileMask & kTopLeft_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(1, 0) ==
                    ((tileMask & kTopRight_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(0, 1) ==
                    ((tileMask & kBottomLeft_Tile)? 1 : 0));
    REPORTER_ASSERT(reporter, grid.tileCount(1, 1) ==
                    ((tileMask & kBottomRight_Tile)? 1 : 0));
}

static SkIRect query(float x, float y, float w, float h) {
    // inflate for the margin++ in tilegrid
    SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
    SkIRect r;
    bounds.roundOut(&r);
    r.outset(1, 1); // to counteract the inset in SkTileGrid::search
    return r;
}

DEF_TEST(TileGrid_UnalignedQuery, reporter) {
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.setEmpty();
    info.fOffset.setZero();
    info.fTileInterval.set(10, 10);
    SkIRect rect1 = SkIRect::MakeXYWH(0, 0, 8, 8);
    SkIRect rect2 = SkIRect::MakeXYWH(11, 11, 1, 1);
    SkTileGrid grid(2, 2, info, SkTileGridNextDatum<SkPictureStateTree::Draw>);
    grid.insert(&rect1, rect1, true);
    grid.insert(&rect2, rect2, true);

    // Test parts of top-left tile
    {
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(7.99f, 7.99f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
    }
    // Corner overlap
    {
        SkTDArray<void*> rects;
        grid.search(query(9.5f, 9.5f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    // Intersect bottom right tile, but does not overlap rect 2
    {
        SkTDArray<void*> rects;
        grid.search(query(16.0f, 16.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    // Out of bounds queries, snap to border tiles
    {
        SkTDArray<void*> rects;
        grid.search(query(-2.0f, 0.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(0.0f, -2.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(22.0f, 16.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(16.0f, 22.0f, 1.0f, 1.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
}

DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
    // Use SkTileGridPicture to generate a SkTileGrid with a helper
    SkTileGridPicture::TileGridInfo info;
    info.fMargin.set(1, 1);
    info.fOffset.set(-1, -1);
    info.fTileInterval.set(8, 8);

    // rect landing entirely in top left tile
    SkIRect rect1 = SkIRect::MakeXYWH(0, 0, 1, 1);
    // rect landing entirely in center tile
    SkIRect rect2 = SkIRect::MakeXYWH(12, 12, 1, 1);
    // rect landing entirely in bottomright tile
    SkIRect rect3 = SkIRect::MakeXYWH(19, 19, 1, 1);
    SkTileGrid grid(3, 3, info, SkTileGridNextDatum<SkPictureStateTree::Draw>);
    grid.insert(&rect1, rect1, true);
    grid.insert(&rect2, rect2, true);
    grid.insert(&rect3, rect3, true);

    // Test parts of top-left tile
    {
        // The offset should cancel the top and left borders of the top left tile
        // So a look-up at interval 0-10 should be grid aligned,
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
    }
    {
        // Encroaching border by one pixel
        SkTDArray<void*> rects;
        grid.search(query(0.0f, 0.0f, 11.0f, 11.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    {
        // Tile stride is 8 (tileWidth - 2 * border pixels
        // so translating by 8, should make query grid-aligned
        // with middle tile.
        SkTDArray<void*> rects;
        grid.search(query(8.0f, 8.0f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 1 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(7.9f, 7.9f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect1) >= 0);
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
    }
    {
        SkTDArray<void*> rects;
        grid.search(query(8.1f, 8.1f, 10.0f, 10.0f), &rects);
        REPORTER_ASSERT(reporter, 2 == rects.count());
        REPORTER_ASSERT(reporter, rects.find(&rect2) >= 0);
        REPORTER_ASSERT(reporter, rects.find(&rect3) >= 0);
    }
    {
        // Regression test for crbug.com/234688
        // Once the 2x2 device region is inset by margin, it yields an empty
        // adjusted region, sitting right on top of the tile boundary.
        SkTDArray<void*> rects;
        grid.search(query(8.0f, 8.0f, 2.0f, 2.0f), &rects);
        // This test passes by not asserting. We do not validate the rects recorded
        // because the result is numerically unstable (floating point equality).
        // The content of any one of the four tiles of the tilegrid would be a valid
        // result since any bbox that covers the center point of the canvas will be
        // recorded in all four tiles.
    }
}

DEF_TEST(TileGrid, reporter) {
    // Out of bounds
    verifyTileHits(reporter, SkIRect::MakeXYWH(30, 0, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 30, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(-10, 0, 1, 1),  0);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, -10, 1, 1),  0);

    // Dilation for AA consideration
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 9, 9),  kTopLeft_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 10, 10),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(9, 9, 1, 1),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(11, 11, 1, 1),  kBottomRight_Tile);

    // BorderPixels
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 6, 6),  kTopLeft_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(0, 0, 7, 7),  kAll_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(9, 9, 1, 1),  kAll_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(10, 10, 1, 1),  kBottomRight_Tile, 1);
    verifyTileHits(reporter, SkIRect::MakeXYWH(17, 17, 1, 1),  kBottomRight_Tile, 1);

    // BBoxes that overlap tiles
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 1),  kTopLeft_Tile | kTopRight_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 1, 10),  kTopLeft_Tile |
                   kBottomLeft_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(5, 5, 10, 10),  kAll_Tile);
    verifyTileHits(reporter, SkIRect::MakeXYWH(-10, -10, 40, 40),  kAll_Tile);
}
<|endoftext|>


<commit_before>//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OrcLazyJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include <cstdio>
#include <system_error>

using namespace llvm;

namespace {

  enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
                        DumpModsToDisk };

  cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
                                cl::desc("Debug dumping for the orc-lazy JIT."),
                                cl::init(DumpKind::NoDump),
                                cl::values(
                                  clEnumValN(DumpKind::NoDump, "no-dump",
                                             "Don't dump anything."),
                                  clEnumValN(DumpKind::DumpFuncsToStdOut,
                                             "funcs-to-stdout",
                                             "Dump function names to stdout."),
                                  clEnumValN(DumpKind::DumpModsToStdErr,
                                             "mods-to-stderr",
                                             "Dump modules to stderr."),
                                  clEnumValN(DumpKind::DumpModsToDisk,
                                             "mods-to-disk",
                                             "Dump modules to the current "
                                             "working directory. (WARNING: "
                                             "will overwrite existing files)."),
                                  clEnumValEnd));
}

OrcLazyJIT::CallbackManagerBuilder
OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
  switch (T.getArch()) {
    default: return nullptr;

    case Triple::x86_64: {
      typedef orc::JITCompileCallbackManager<IRDumpLayerT,
                                             orc::OrcX86_64> CCMgrT;
      return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
                LLVMContext &Context) {
               return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
                                                64);
             };
    }
  }
}

OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {

  switch (OrcDumpKind) {
  case DumpKind::NoDump:
    return [](std::unique_ptr<Module> M) { return M; };

  case DumpKind::DumpFuncsToStdOut:
    return [](std::unique_ptr<Module> M) {
      printf("[ ");

      for (const auto &F : *M) {
        if (F.isDeclaration())
          continue;

        if (F.hasName()) {
          std::string Name(F.getName());
          printf("%s ", Name.c_str());
        } else
          printf("<anon> ");
      }

      printf("]\n");
      return M;
    };

  case DumpKind::DumpModsToStdErr:
    return [](std::unique_ptr<Module> M) {
             dbgs() << "----- Module Start -----\n" << *M
                    << "----- Module End -----\n";

             return M;
           };

  case DumpKind::DumpModsToDisk:
    return [](std::unique_ptr<Module> M) {
             std::error_code EC;
             raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
                                sys::fs::F_Text);
             if (EC) {
               errs() << "Couldn't open " << M->getModuleIdentifier()
                      << " for dumping.\nError:" << EC.message() << "\n";
               exit(1);
             }
             Out << *M;
             return M;
           };
  }
  llvm_unreachable("Unknown DumpKind");
}

// Defined in lli.cpp.
CodeGenOpt::Level getOptLevel();

int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
  // Add the program's symbols into the JIT's search space.
  if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
    errs() << "Error loading program symbols.\n";
    return 1;
  }

  // Grab a target machine and try to build a factory function for the
  // target-specific Orc callback manager.
  EngineBuilder EB;
  EB.setOptLevel(getOptLevel());
  auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
  auto &Context = getGlobalContext();
  auto CallbackMgrBuilder =
    OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));

  // If we couldn't build the factory function then there must not be a callback
  // manager for this target. Bail out.
  if (!CallbackMgrBuilder) {
    errs() << "No callback manager available for target '"
           << TM->getTargetTriple().str() << "'.\n";
    return 1;
  }

  // Everything looks good. Build the JIT.
  auto &DL = M->getDataLayout();
  OrcLazyJIT J(std::move(TM), DL, Context, CallbackMgrBuilder);

  // Add the module, look up main and run it.
  auto MainHandle = J.addModule(std::move(M));
  auto MainSym = J.findSymbolIn(MainHandle, "main");

  if (!MainSym) {
    errs() << "Could not find main function.\n";
    return 1;
  }

  typedef int (*MainFnPtr)(int, char*[]);
  auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
  return Main(ArgC, ArgV);
}
<commit_msg>Fix lli with OrcLazyJIT: the default DataLayout was used.<commit_after>//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "OrcLazyJIT.h"
#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DynamicLibrary.h"
#include <cstdio>
#include <system_error>

using namespace llvm;

namespace {

  enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
                        DumpModsToDisk };

  cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
                                cl::desc("Debug dumping for the orc-lazy JIT."),
                                cl::init(DumpKind::NoDump),
                                cl::values(
                                  clEnumValN(DumpKind::NoDump, "no-dump",
                                             "Don't dump anything."),
                                  clEnumValN(DumpKind::DumpFuncsToStdOut,
                                             "funcs-to-stdout",
                                             "Dump function names to stdout."),
                                  clEnumValN(DumpKind::DumpModsToStdErr,
                                             "mods-to-stderr",
                                             "Dump modules to stderr."),
                                  clEnumValN(DumpKind::DumpModsToDisk,
                                             "mods-to-disk",
                                             "Dump modules to the current "
                                             "working directory. (WARNING: "
                                             "will overwrite existing files)."),
                                  clEnumValEnd));
}

OrcLazyJIT::CallbackManagerBuilder
OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
  switch (T.getArch()) {
    default: return nullptr;

    case Triple::x86_64: {
      typedef orc::JITCompileCallbackManager<IRDumpLayerT,
                                             orc::OrcX86_64> CCMgrT;
      return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
                LLVMContext &Context) {
               return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
                                                64);
             };
    }
  }
}

OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {

  switch (OrcDumpKind) {
  case DumpKind::NoDump:
    return [](std::unique_ptr<Module> M) { return M; };

  case DumpKind::DumpFuncsToStdOut:
    return [](std::unique_ptr<Module> M) {
      printf("[ ");

      for (const auto &F : *M) {
        if (F.isDeclaration())
          continue;

        if (F.hasName()) {
          std::string Name(F.getName());
          printf("%s ", Name.c_str());
        } else
          printf("<anon> ");
      }

      printf("]\n");
      return M;
    };

  case DumpKind::DumpModsToStdErr:
    return [](std::unique_ptr<Module> M) {
             dbgs() << "----- Module Start -----\n" << *M
                    << "----- Module End -----\n";

             return M;
           };

  case DumpKind::DumpModsToDisk:
    return [](std::unique_ptr<Module> M) {
             std::error_code EC;
             raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
                                sys::fs::F_Text);
             if (EC) {
               errs() << "Couldn't open " << M->getModuleIdentifier()
                      << " for dumping.\nError:" << EC.message() << "\n";
               exit(1);
             }
             Out << *M;
             return M;
           };
  }
  llvm_unreachable("Unknown DumpKind");
}

// Defined in lli.cpp.
CodeGenOpt::Level getOptLevel();

int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
  // Add the program's symbols into the JIT's search space.
  if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
    errs() << "Error loading program symbols.\n";
    return 1;
  }

  // Grab a target machine and try to build a factory function for the
  // target-specific Orc callback manager.
  EngineBuilder EB;
  EB.setOptLevel(getOptLevel());
  auto TM = std::unique_ptr<TargetMachine>(EB.selectTarget());
  M->setDataLayout(TM->createDataLayout());
  auto &Context = getGlobalContext();
  auto CallbackMgrBuilder =
    OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));

  // If we couldn't build the factory function then there must not be a callback
  // manager for this target. Bail out.
  if (!CallbackMgrBuilder) {
    errs() << "No callback manager available for target '"
           << TM->getTargetTriple().str() << "'.\n";
    return 1;
  }

  // Everything looks good. Build the JIT.
  auto &DL = M->getDataLayout();
  OrcLazyJIT J(std::move(TM), DL, Context, CallbackMgrBuilder);

  // Add the module, look up main and run it.
  auto MainHandle = J.addModule(std::move(M));
  auto MainSym = J.findSymbolIn(MainHandle, "main");

  if (!MainSym) {
    errs() << "Could not find main function.\n";
    return 1;
  }

  typedef int (*MainFnPtr)(int, char*[]);
  auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
  return Main(ArgC, ArgV);
}
<|endoftext|>


<commit_before>#include <cassert>
#include <gtest/gtest.h>
#include <system.h>
#include <basecpu.h>

#define TEST_CLASS BaseCPUTest

class BaseTestCPU : public BaseCPU {
public:
    BaseTestCPU(int maxTicks, const System &sys) : maxTicks(maxTicks), ticks(0), resets(0), BaseCPU(sys) { }
    void reset() { resets++; }
    void tick() {
        assert(isRunning());
        ticks++;
        if(ticks>= maxTicks) {
            stop();
        }
    }

    int ticks;
    int resets;
    int maxTicks;
};

const int TEST_TICK_COUNT = 3;

class TEST_CLASS : public testing::Test {
protected:
    TEST_CLASS() : cpu(TEST_TICK_COUNT, dummySystem) { }
    BaseTestCPU cpu;
    System dummySystem;
};

TEST_F(TEST_CLASS, TestRunLoop) {
    ASSERT_FALSE(cpu.isRunning()) << "Incorrect initial CPU running state";
    ASSERT_EQ(cpu.ticks, 0) << "Incorrect initial CPU tick count";
    ASSERT_EQ(cpu.resets, 0) << "Incorrect initial CPU reset count";
    cpu.startup();
    ASSERT_FALSE(cpu.isRunning()) << "Incorrect final CPU running state";
    ASSERT_EQ(cpu.ticks, TEST_TICK_COUNT) << "Incorrect final CPU tick count";
    ASSERT_EQ(cpu.resets, 1) << "Incorrect initial CPU reset count";
}<commit_msg>Create tests for Interruptable<commit_after>#include <cassert>
#include <gtest/gtest.h>
#include <system.h>
#include <basecpu.h>

#define TEST_CLASS BaseCPUTest

class BaseTestCPU : public BaseCPU {
public:
    BaseTestCPU(int maxTicks, const System &sys) : maxTicks(maxTicks), ticks(0), resets(0), BaseCPU(sys) { }
    void reset() { resets++; }
    void tick() {
        assert(isRunning());
        ticks++;
        if(ticks>= maxTicks) {
            stop();
        }
    }

    int ticks;
    int resets;
    int maxTicks;
};

class TestInterruptable : public Interruptable {
public:
    virtual void serviceInterrupt(Interrupt interrupt) {
        serviced.push_back(interrupt);
    }

    bool _next() { return serviceNextInterrupt(); }

    std::vector<Interrupt> serviced;
};

const int TEST_TICK_COUNT = 3;

class TEST_CLASS : public testing::Test {
protected:
    TEST_CLASS() : cpu(TEST_TICK_COUNT, dummySystem) { }
    BaseTestCPU cpu;
    TestInterruptable server;
    System dummySystem;
};

TEST_F(TEST_CLASS, TestRunLoop) {
    ASSERT_FALSE(cpu.isRunning()) << "Incorrect initial CPU running state";
    ASSERT_EQ(cpu.ticks, 0) << "Incorrect initial CPU tick count";
    ASSERT_EQ(cpu.resets, 0) << "Incorrect initial CPU reset count";
    cpu.startup();
    ASSERT_FALSE(cpu.isRunning()) << "Incorrect final CPU running state";
    ASSERT_EQ(cpu.ticks, TEST_TICK_COUNT) << "Incorrect final CPU tick count";
    ASSERT_EQ(cpu.resets, 1) << "Incorrect initial CPU reset count";
}

TEST_F(TEST_CLASS, TestInterruptService) {
    ASSERT_FALSE(server._next()) << "Incorrect service of empty queue";
    server.signalInterrupt(3);
    server.signalInterrupt(5);
    ASSERT_TRUE(server._next()) << "Failed to service queue";
    ASSERT_EQ(server.serviced.size(), 1) << "Incorrect number of interrupts serviced";
    ASSERT_EQ(server.serviced.at(0), 3) << "Incorrect interrupt serviced";
    ASSERT_TRUE(server._next()) << "Failed to service queue";
    ASSERT_EQ(server.serviced.size(), 2) << "Incorrect number of interrupts serviced";
    ASSERT_EQ(server.serviced.at(1), 5) << "Incorrect interrupt serviced";
    ASSERT_FALSE(server._next()) << "Incorrect service of empty queue";
}<|endoftext|>


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

#include "fixtures.hpp"

#include <fstream>
#include <ios>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <utility>

using ews::internal::on_scope_exit;

namespace tests
{

#ifdef EWS_HAS_FILESYSTEM_HEADER
class GetItemRequestTest : public FakeServiceFixture
{
private:
    void SetUp()
    {
        FakeServiceFixture::SetUp();

        const auto assets = std::filesystem::path(
            ews::test::global_data::instance().assets_dir);
        const auto file_path = assets / "get_item_response_message.xml";
        std::ifstream ifstr(file_path.string(),
                            std::ifstream::in | std::ios::binary);
        if (!ifstr.is_open())
        {
            throw std::runtime_error("Could not open file for reading: " +
                                     file_path.string());
        }
        ifstr.unsetf(std::ios::skipws);
        ifstr.seekg(0, std::ios::end);
        const auto file_size = ifstr.tellg();
        ifstr.seekg(0, std::ios::beg);

        std::vector<char> buf;
        buf.reserve(file_size);
        buf.insert(begin(buf), std::istream_iterator<char>(ifstr),
                   std::istream_iterator<char>());
        ifstr.close();
        buf.push_back('\0');

        set_next_fake_response(std::move(buf));
    }
};

TEST_F(GetItemRequestTest, WithAdditionalProperties)
{
    auto& serv = service();
    auto fake_id = ews::item_id();

    auto additional_props = std::vector<ews::property_path>();
    additional_props.push_back(ews::item_property_path::body);
    ews::item_shape shape(std::move(additional_props));
    auto cal_item = serv.get_calendar_item(fake_id, shape);
    (void)cal_item;

    EXPECT_NE(get_last_request().request_string().find(
                  "<t:AdditionalProperties>"
                  "<t:FieldURI FieldURI=\"item:Body\"/>"
                  "</t:AdditionalProperties>"),
              std::string::npos);
}
#endif // EWS_HAS_FILESYSTEM_HEADER

class SoapHeader : public FakeServiceFixture
{
private:
    void SetUp()
    {
        FakeServiceFixture::SetUp();
        set_next_fake_response(
            "<s:Envelope "
            "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
            "    <s:Header>\n"
            "        <h:ServerVersionInfo MajorVersion=\"15\" "
            "MinorVersion=\"0\" MajorBuildNumber=\"847\" "
            "MinorBuildNumber=\"31\" Version=\"V2_8\" "
            "xmlns:h=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\" "
            "xmlns=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n"
            "    </s:Header>\n"
            "    <s:Body "
            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
            "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n"
            "        <m:CreateItemResponse "
            "xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/"
            "messages\" "
            "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\">\n"
            "            <m:ResponseMessages>\n"
            "                <m:CreateItemResponseMessage "
            "ResponseClass=\"Success\">\n"
            "                    <m:ResponseCode>NoError</m:ResponseCode>\n"
            "                    <m:Items>\n"
            "                        <t:Message>\n"
            "                            <t:ItemId "
            "Id="
            "\"AAMkAGRhYmQ5Njg0LTNhMjEtNDZkOS1hN2QyLTUzZTI3MjdhN2ZkYgBGAAAA"
            "AAC5LuzvcattTqJiAgNAfv18BwDKOL2xzF+"
            "1SL9YsnXMX2cZAAAAAAEQAADKOL2xzF+1SL9YsnXMX2cZAAADQIPPAAA=\" "
            "ChangeKey=\"CQAAABYAAADKOL2xzF+1SL9YsnXMX2cZAAADQKty\"/>\n"
            "                        </t:Message>\n"
            "                    </m:Items>\n"
            "                </m:CreateItemResponseMessage>\n"
            "            </m:ResponseMessages>\n"
            "        </m:CreateItemResponse>\n"
            "    </s:Body>\n"
            "</s:Envelope>\n");
    }
};

TEST_F(SoapHeader, SupportsExchange2007)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2007);
    auto task = ews::task();
    task.set_subject("Random To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2007\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2007_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2007_sp1);
    auto task = ews::task();
    task.set_subject("Another To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2007_SP1\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010);
    auto task = ews::task();
    task.set_subject("Yet another To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010_sp1);
    auto task = ews::task();
    task.set_subject("Feed the cat");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010_SP1\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010_SP2)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010_sp2);
    auto task = ews::task();
    task.set_subject("Do something about code duplication");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010_SP2\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2013)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2013);
    auto task = ews::task();
    task.set_subject("Buy new shoes");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2013\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2013_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2013_sp1);
    auto task = ews::task();
    task.set_subject("Get some milk from the store");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2013_SP1\"/>"));
}

TEST_F(SoapHeader, DefaultServerVersionIs2013_SP1)
{
    auto serv = service();
    EXPECT_EQ(serv.get_request_server_version(),
              ews::server_version::exchange_2013_sp1);
}

TEST_F(SoapHeader, ImpersonateAsAnotherUser)
{
    const auto someone = ews::connecting_sid(
        ews::connecting_sid::type::smtp_address, "batman@gothamcity.com");
    auto& serv = service();

    auto task = ews::task();
    task.set_subject("Random To-Do item");

    serv.impersonate(someone).create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:ExchangeImpersonation><t:ConnectingSID><t:SmtpAddress>batman@"
        "gothamcity.com</t:SmtpAddress></t:ConnectingSID></"
        "t:ExchangeImpersonation>"));

    serv.impersonate();
    serv.create_item(task);
    request = get_last_request();
    EXPECT_FALSE(request.header_contains(
        "<t:ExchangeImpersonation><t:ConnectingSID><t:SmtpAddress>batman@"
        "gothamcity.com</t:SmtpAddress></t:ConnectingSID></"
        "t:ExchangeImpersonation>"));
}

class ServiceTest : public ContactTest
{
};

TEST_F(ServiceTest, UpdateItemOfReadOnlyPropertyThrows)
{
    auto minnie = test_contact();
    ASSERT_FALSE(minnie.has_attachments());
    auto prop = ews::property(ews::item_property_path::has_attachments, true);
    EXPECT_THROW({ service().update_item(minnie.get_item_id(), prop); },
                 ews::exchange_error);
}

TEST_F(ServiceTest, UpdateItemOfReadOnlyPropertyThrowsWhatMessage)
{
    auto minnie = test_contact();
    ASSERT_FALSE(minnie.has_attachments());
    auto prop = ews::property(ews::item_property_path::has_attachments, true);
    try
    {
        service().update_item(minnie.get_item_id(), prop);
        FAIL() << "Expected exception to be thrown";
    }
    catch (ews::exchange_error& exc)
    {
        EXPECT_EQ(ews::response_code::error_invalid_property_set, exc.code());
    }
}

TEST_F(ServiceTest, UpdateItemWithSetItemField)
{
    // <SetItemField> is used whenever we want to replace an existing value.
    // If none exists yet, it is created

    auto minnie = test_contact();

    EXPECT_STREQ("Mickey", minnie.get_spouse_name().c_str());
    auto spouse_name_property =
        ews::property(ews::contact_property_path::spouse_name, "Mickey");
    auto new_id =
        service().update_item(minnie.get_item_id(), spouse_name_property,
                              ews::conflict_resolution::auto_resolve);
    minnie = service().get_contact(new_id, ews::base_shape::all_properties);
    EXPECT_STREQ("Mickey", minnie.get_spouse_name().c_str());

    spouse_name_property =
        ews::property(ews::contact_property_path::spouse_name, "Peg-Leg Pedro");
    new_id = service().update_item(minnie.get_item_id(), spouse_name_property,
                                   ews::conflict_resolution::auto_resolve);
    minnie = service().get_contact(new_id, ews::base_shape::all_properties);
    EXPECT_STREQ("Peg-Leg Pedro", minnie.get_spouse_name().c_str());
}

TEST_F(ServiceTest, UpdateItemWithDeleteItemField)
{
    // <DeleteItemField> is simply just a FieldURI to the property that we
    // want to delete. Not much to it. It is automatically deduced by
    // service::update_item if the user has not provided any value to the
    // property he wanted to update

    auto minnie = test_contact();
    ASSERT_FALSE(minnie.get_given_name().empty());
    auto prop = ews::property(ews::contact_property_path::given_name, "");
    auto update = ews::update(prop, ews::update::operation::delete_item_field);
    auto new_id = service().update_item(minnie.get_item_id(), update);
    minnie = service().get_contact(new_id);
    EXPECT_TRUE(minnie.get_given_name().empty());
}

TEST_F(ServiceTest, UpdateItemWithAppendToItemField)
{
    // <AppendToItemField> is automatically deduced by service::update_item
    // so user does not need to bother. It is only valid for following
    // properties (at least in EWS 2007 slang):
    //
    // - calendar:OptionalAttendees
    // - calendar:RequiredAttendees
    // - calendar:Resources
    // - item:Body
    // - message:ToRecipients
    // - message:CcRecipients
    // - message:BccRecipients
    // - message:ReplyTo

    auto message = ews::message();
    message.set_subject("You are hiding again, aren't you?");
    std::vector<ews::mailbox> recipients;
    recipients.push_back(ews::mailbox("darkwing.duck@duckburg.com"));
    message.set_to_recipients(recipients);
    auto item_id =
        service().create_item(message, ews::message_disposition::save_only);
    on_scope_exit delete_message(
        [&] { service().delete_message(std::move(message)); });
    message = service().get_message(item_id);
    recipients = message.get_to_recipients();
    EXPECT_EQ(1U, recipients.size());

    std::vector<ews::mailbox> additional_recipients;
    additional_recipients.push_back(ews::mailbox("gus.goose@duckburg.com"));
    auto prop = ews::property(ews::message_property_path::to_recipients,
                              additional_recipients);
    auto change =
        ews::update(prop, ews::update::operation::append_to_item_field);
    auto new_id = service().update_item(message.get_item_id(), change);
    message = service().get_message(item_id);
    ASSERT_EQ(2U, message.get_to_recipients().size());
}

TEST_F(ServiceTest, SendItem)
{
    auto msg = ews::message();
    msg.set_subject("You are hiding again, aren't you?");
    std::vector<ews::mailbox> recipients;
    recipients.push_back(ews::mailbox("darkwing.duck@duckburg.com"));
    msg.set_to_recipients(recipients);
    const auto item_id =
        service().create_item(msg, ews::message_disposition::save_only);
    msg = service().get_message(item_id);
    EXPECT_NO_THROW({ service().send_item(msg.get_item_id()); });
}
} // namespace tests
<commit_msg>Add test for basic_service::set_time_zone(...)<commit_after>
//   Copyright 2016 otris software AG
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//
//   This project is hosted at https://github.com/otris

#include "fixtures.hpp"

#include <fstream>
#include <ios>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <utility>

using ews::internal::on_scope_exit;

namespace tests
{

#ifdef EWS_HAS_FILESYSTEM_HEADER
class GetItemRequestTest : public FakeServiceFixture
{
private:
    void SetUp()
    {
        FakeServiceFixture::SetUp();

        const auto assets = std::filesystem::path(
            ews::test::global_data::instance().assets_dir);
        const auto file_path = assets / "get_item_response_message.xml";
        std::ifstream ifstr(file_path.string(),
                            std::ifstream::in | std::ios::binary);
        if (!ifstr.is_open())
        {
            throw std::runtime_error("Could not open file for reading: " +
                                     file_path.string());
        }
        ifstr.unsetf(std::ios::skipws);
        ifstr.seekg(0, std::ios::end);
        const auto file_size = ifstr.tellg();
        ifstr.seekg(0, std::ios::beg);

        std::vector<char> buf;
        buf.reserve(file_size);
        buf.insert(begin(buf), std::istream_iterator<char>(ifstr),
                   std::istream_iterator<char>());
        ifstr.close();
        buf.push_back('\0');

        set_next_fake_response(std::move(buf));
    }
};

TEST_F(GetItemRequestTest, WithAdditionalProperties)
{
    auto& serv = service();
    auto fake_id = ews::item_id();

    auto additional_props = std::vector<ews::property_path>();
    additional_props.push_back(ews::item_property_path::body);
    ews::item_shape shape(std::move(additional_props));
    auto cal_item = serv.get_calendar_item(fake_id, shape);
    (void)cal_item;

    EXPECT_NE(get_last_request().request_string().find(
                  "<t:AdditionalProperties>"
                  "<t:FieldURI FieldURI=\"item:Body\"/>"
                  "</t:AdditionalProperties>"),
              std::string::npos);
}
#endif // EWS_HAS_FILESYSTEM_HEADER

class SoapHeader : public FakeServiceFixture
{
private:
    void SetUp()
    {
        FakeServiceFixture::SetUp();
        set_next_fake_response(
            "<s:Envelope "
            "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
            "    <s:Header>\n"
            "        <h:ServerVersionInfo MajorVersion=\"15\" "
            "MinorVersion=\"0\" MajorBuildNumber=\"847\" "
            "MinorBuildNumber=\"31\" Version=\"V2_8\" "
            "xmlns:h=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\" "
            "xmlns=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>\n"
            "    </s:Header>\n"
            "    <s:Body "
            "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
            "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n"
            "        <m:CreateItemResponse "
            "xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/"
            "messages\" "
            "xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/"
            "types\">\n"
            "            <m:ResponseMessages>\n"
            "                <m:CreateItemResponseMessage "
            "ResponseClass=\"Success\">\n"
            "                    <m:ResponseCode>NoError</m:ResponseCode>\n"
            "                    <m:Items>\n"
            "                        <t:Message>\n"
            "                            <t:ItemId "
            "Id="
            "\"AAMkAGRhYmQ5Njg0LTNhMjEtNDZkOS1hN2QyLTUzZTI3MjdhN2ZkYgBGAAAA"
            "AAC5LuzvcattTqJiAgNAfv18BwDKOL2xzF+"
            "1SL9YsnXMX2cZAAAAAAEQAADKOL2xzF+1SL9YsnXMX2cZAAADQIPPAAA=\" "
            "ChangeKey=\"CQAAABYAAADKOL2xzF+1SL9YsnXMX2cZAAADQKty\"/>\n"
            "                        </t:Message>\n"
            "                    </m:Items>\n"
            "                </m:CreateItemResponseMessage>\n"
            "            </m:ResponseMessages>\n"
            "        </m:CreateItemResponse>\n"
            "    </s:Body>\n"
            "</s:Envelope>\n");
    }
};

TEST_F(SoapHeader, SupportsExchange2007)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2007);
    auto task = ews::task();
    task.set_subject("Random To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2007\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2007_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2007_sp1);
    auto task = ews::task();
    task.set_subject("Another To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2007_SP1\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010);
    auto task = ews::task();
    task.set_subject("Yet another To-Do item");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010_sp1);
    auto task = ews::task();
    task.set_subject("Feed the cat");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010_SP1\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2010_SP2)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2010_sp2);
    auto task = ews::task();
    task.set_subject("Do something about code duplication");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2010_SP2\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2013)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2013);
    auto task = ews::task();
    task.set_subject("Buy new shoes");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2013\"/>"));
}

TEST_F(SoapHeader, SupportsExchange2013_SP1)
{
    auto& serv = service();
    serv.set_request_server_version(ews::server_version::exchange_2013_sp1);
    auto task = ews::task();
    task.set_subject("Get some milk from the store");
    serv.create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:RequestServerVersion Version=\"Exchange2013_SP1\"/>"));
}

TEST_F(SoapHeader, DefaultServerVersionIs2013_SP1)
{
    auto serv = service();
    EXPECT_EQ(serv.get_request_server_version(),
              ews::server_version::exchange_2013_sp1);
}

TEST_F(SoapHeader, SpecifyTimeZone)
{
   auto& serv = service();
   serv.set_time_zone(ews::time_zone::w_european_standard_time);
   auto task = ews::task();
   task.set_subject("Get some milk from the store");
   serv.create_item(task);
   auto request = get_last_request();
   EXPECT_TRUE(request.header_contains(
      "<t:TimeZoneContext>"
      "<t:TimeZoneDefinition Id=\"W.Europe Standard Time\"/>"
      "</t:TimeZoneContext>"));
   EXPECT_EQ(serv.get_time_zone(),
             ews::time_zone::w_european_standard_time);
}

TEST_F(SoapHeader, ImpersonateAsAnotherUser)
{
    const auto someone = ews::connecting_sid(
        ews::connecting_sid::type::smtp_address, "batman@gothamcity.com");
    auto& serv = service();

    auto task = ews::task();
    task.set_subject("Random To-Do item");

    serv.impersonate(someone).create_item(task);
    auto request = get_last_request();
    EXPECT_TRUE(request.header_contains(
        "<t:ExchangeImpersonation><t:ConnectingSID><t:SmtpAddress>batman@"
        "gothamcity.com</t:SmtpAddress></t:ConnectingSID></"
        "t:ExchangeImpersonation>"));

    serv.impersonate();
    serv.create_item(task);
    request = get_last_request();
    EXPECT_FALSE(request.header_contains(
        "<t:ExchangeImpersonation><t:ConnectingSID><t:SmtpAddress>batman@"
        "gothamcity.com</t:SmtpAddress></t:ConnectingSID></"
        "t:ExchangeImpersonation>"));
}

class ServiceTest : public ContactTest
{
};

TEST_F(ServiceTest, UpdateItemOfReadOnlyPropertyThrows)
{
    auto minnie = test_contact();
    ASSERT_FALSE(minnie.has_attachments());
    auto prop = ews::property(ews::item_property_path::has_attachments, true);
    EXPECT_THROW({ service().update_item(minnie.get_item_id(), prop); },
                 ews::exchange_error);
}

TEST_F(ServiceTest, UpdateItemOfReadOnlyPropertyThrowsWhatMessage)
{
    auto minnie = test_contact();
    ASSERT_FALSE(minnie.has_attachments());
    auto prop = ews::property(ews::item_property_path::has_attachments, true);
    try
    {
        service().update_item(minnie.get_item_id(), prop);
        FAIL() << "Expected exception to be thrown";
    }
    catch (ews::exchange_error& exc)
    {
        EXPECT_EQ(ews::response_code::error_invalid_property_set, exc.code());
    }
}

TEST_F(ServiceTest, UpdateItemWithSetItemField)
{
    // <SetItemField> is used whenever we want to replace an existing value.
    // If none exists yet, it is created

    auto minnie = test_contact();

    EXPECT_STREQ("Mickey", minnie.get_spouse_name().c_str());
    auto spouse_name_property =
        ews::property(ews::contact_property_path::spouse_name, "Mickey");
    auto new_id =
        service().update_item(minnie.get_item_id(), spouse_name_property,
                              ews::conflict_resolution::auto_resolve);
    minnie = service().get_contact(new_id, ews::base_shape::all_properties);
    EXPECT_STREQ("Mickey", minnie.get_spouse_name().c_str());

    spouse_name_property =
        ews::property(ews::contact_property_path::spouse_name, "Peg-Leg Pedro");
    new_id = service().update_item(minnie.get_item_id(), spouse_name_property,
                                   ews::conflict_resolution::auto_resolve);
    minnie = service().get_contact(new_id, ews::base_shape::all_properties);
    EXPECT_STREQ("Peg-Leg Pedro", minnie.get_spouse_name().c_str());
}

TEST_F(ServiceTest, UpdateItemWithDeleteItemField)
{
    // <DeleteItemField> is simply just a FieldURI to the property that we
    // want to delete. Not much to it. It is automatically deduced by
    // service::update_item if the user has not provided any value to the
    // property he wanted to update

    auto minnie = test_contact();
    ASSERT_FALSE(minnie.get_given_name().empty());
    auto prop = ews::property(ews::contact_property_path::given_name, "");
    auto update = ews::update(prop, ews::update::operation::delete_item_field);
    auto new_id = service().update_item(minnie.get_item_id(), update);
    minnie = service().get_contact(new_id);
    EXPECT_TRUE(minnie.get_given_name().empty());
}

TEST_F(ServiceTest, UpdateItemWithAppendToItemField)
{
    // <AppendToItemField> is automatically deduced by service::update_item
    // so user does not need to bother. It is only valid for following
    // properties (at least in EWS 2007 slang):
    //
    // - calendar:OptionalAttendees
    // - calendar:RequiredAttendees
    // - calendar:Resources
    // - item:Body
    // - message:ToRecipients
    // - message:CcRecipients
    // - message:BccRecipients
    // - message:ReplyTo

    auto message = ews::message();
    message.set_subject("You are hiding again, aren't you?");
    std::vector<ews::mailbox> recipients;
    recipients.push_back(ews::mailbox("darkwing.duck@duckburg.com"));
    message.set_to_recipients(recipients);
    auto item_id =
        service().create_item(message, ews::message_disposition::save_only);
    on_scope_exit delete_message(
        [&] { service().delete_message(std::move(message)); });
    message = service().get_message(item_id);
    recipients = message.get_to_recipients();
    EXPECT_EQ(1U, recipients.size());

    std::vector<ews::mailbox> additional_recipients;
    additional_recipients.push_back(ews::mailbox("gus.goose@duckburg.com"));
    auto prop = ews::property(ews::message_property_path::to_recipients,
                              additional_recipients);
    auto change =
        ews::update(prop, ews::update::operation::append_to_item_field);
    auto new_id = service().update_item(message.get_item_id(), change);
    message = service().get_message(item_id);
    ASSERT_EQ(2U, message.get_to_recipients().size());
}

TEST_F(ServiceTest, SendItem)
{
    auto msg = ews::message();
    msg.set_subject("You are hiding again, aren't you?");
    std::vector<ews::mailbox> recipients;
    recipients.push_back(ews::mailbox("darkwing.duck@duckburg.com"));
    msg.set_to_recipients(recipients);
    const auto item_id =
        service().create_item(msg, ews::message_disposition::save_only);
    msg = service().get_message(item_id);
    EXPECT_NO_THROW({ service().send_item(msg.get_item_id()); });
}
} // namespace tests
<|endoftext|>


<commit_before>#include "rusttoolchain.h"
#include "rustoutputparser.h"
#include "rusttoolchainconfigwidget.h"

#include <projectexplorer/abi.h>
#include <projectexplorer/headerpath.h>
#include <utils/fileutils.h>

using namespace ProjectExplorer;
using namespace Utils;

namespace Rust {

RustToolChain::RustToolChain()
    : ToolChain(QString::fromLatin1("RustToolChainId"), ToolChain::ManualDetection)
{
    setDisplayName(QString::fromLatin1("Rust Compiler"));
}

void RustToolChain::setReleaseChannel(RustToolChain::ReleaseChannel c)
{
    releaseChannel_ = c;
}

RustToolChain::ReleaseChannel RustToolChain::releaseChannel()
{
    return releaseChannel_;
}

QString RustToolChain::type() const
{
    return QString::fromLatin1("rustc");
}

QString RustToolChain::typeDisplayName() const
{
    // STUB
    return QString::fromLatin1("MSVC");
}

Abi RustToolChain::targetAbi() const
{
    // STUB
    return Abi::hostAbi();
}

bool RustToolChain::isValid() const
{
    // STUB
    return true;
}

QByteArray RustToolChain::predefinedMacros(const QStringList& cxxflags) const
{
    Q_UNUSED(cxxflags)
    // STUB
    return QByteArray();
}

ToolChain::CompilerFlags RustToolChain::compilerFlags(const QStringList& cxxflags) const
{
    Q_UNUSED(cxxflags)
    // STUB
    return ToolChain::NoFlags;
}

ToolChain::WarningFlags RustToolChain::warningFlags(const QStringList& cflags) const
{
    Q_UNUSED(cflags)
    // STUB
    return ToolChain::WarningsDefault;
}

QList<HeaderPath> RustToolChain::systemHeaderPaths(const QStringList& cxxflags, const FileName& sysRoot) const
{
    Q_UNUSED(cxxflags)
    Q_UNUSED(sysRoot)
    // STUB
    return QList<HeaderPath>();
}

void RustToolChain::addToEnvironment(Environment& env) const
{
    Q_UNUSED(env)
    // STUB
}

QString RustToolChain::makeCommand(const Environment& env) const
{
    Q_UNUSED(env)
    // STUB
    return QString::fromLatin1("rustc");
}

FileName RustToolChain::compilerCommand() const
{
    // STUB
    return FileName::fromString(QString::fromLatin1(R"(C:\Program Files\Rust stable 1.1\bin\rustc.exe)"));
}

IOutputParser* RustToolChain::outputParser() const
{
    return new RustOutputParser;
}

ToolChainConfigWidget* RustToolChain::configurationWidget()
{
    return new RustToolChainConfigWidget(this);
}

ToolChain* RustToolChain::clone() const
{
    // STUB
    return nullptr;
}

}
<commit_msg>Fix CI build<commit_after>#include "rusttoolchain.h"
#include "rustoutputparser.h"
#include "rusttoolchainconfigwidget.h"

#include <projectexplorer/abi.h>
#include <projectexplorer/headerpath.h>
#include <utils/fileutils.h>
#include <utils/environment.h>

using namespace ProjectExplorer;
using namespace Utils;

namespace Rust {

RustToolChain::RustToolChain()
    : ToolChain(QString::fromLatin1("RustToolChainId"), ToolChain::ManualDetection)
{
    setDisplayName(QString::fromLatin1("Rust Compiler"));
}

void RustToolChain::setReleaseChannel(RustToolChain::ReleaseChannel c)
{
    releaseChannel_ = c;
}

RustToolChain::ReleaseChannel RustToolChain::releaseChannel()
{
    return releaseChannel_;
}

QString RustToolChain::type() const
{
    return QString::fromLatin1("rustc");
}

QString RustToolChain::typeDisplayName() const
{
    // STUB
    return QString::fromLatin1("MSVC");
}

Abi RustToolChain::targetAbi() const
{
    // STUB
    return Abi::hostAbi();
}

bool RustToolChain::isValid() const
{
    // STUB
    return true;
}

QByteArray RustToolChain::predefinedMacros(const QStringList& cxxflags) const
{
    Q_UNUSED(cxxflags)
    // STUB
    return QByteArray();
}

ToolChain::CompilerFlags RustToolChain::compilerFlags(const QStringList& cxxflags) const
{
    Q_UNUSED(cxxflags)
    // STUB
    return ToolChain::NoFlags;
}

ToolChain::WarningFlags RustToolChain::warningFlags(const QStringList& cflags) const
{
    Q_UNUSED(cflags)
    // STUB
    return ToolChain::WarningsDefault;
}

QList<HeaderPath> RustToolChain::systemHeaderPaths(const QStringList& cxxflags, const FileName& sysRoot) const
{
    Q_UNUSED(cxxflags)
    Q_UNUSED(sysRoot)
    // STUB
    return QList<HeaderPath>();
}

void RustToolChain::addToEnvironment(Environment& env) const
{
    Q_UNUSED(env)
    // STUB
}

QString RustToolChain::makeCommand(const Environment& env) const
{
    Q_UNUSED(env)
    // STUB
    return QString::fromLatin1("rustc");
}

FileName RustToolChain::compilerCommand() const
{
    // STUB
    return FileName::fromString(QString::fromLatin1(R"(C:\Program Files\Rust stable 1.1\bin\rustc.exe)"));
}

IOutputParser* RustToolChain::outputParser() const
{
    return new RustOutputParser;
}

ToolChainConfigWidget* RustToolChain::configurationWidget()
{
    return new RustToolChainConfigWidget(this);
}

ToolChain* RustToolChain::clone() const
{
    // STUB
    return nullptr;
}

}
<|endoftext|>


<commit_before>#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <cctype>
#include <iostream>
#include <iterator>
#include <stdio.h>

using namespace std;
using namespace cv;

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    double scale);

string cascadeName = "./haarcascade_frontalface_alt.xml";
string nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";

int main( int argc, const char** argv ) {
    CascadeClassifier cascade;
    if( !cascade.load( cascadeName ) ) {
        cerr << "ERROR: Could not load classifier cascade" << endl;
        return -1;
    }

    CvCapture* capture = cvCaptureFromCAM( 0 );
    if(!capture) {
        cerr << "Capture from CAM " <<  0  << " didn't work" << endl;
        return -1;
    }

    // todo, figure out how to make a fullscreen window.
    cvNamedWindow( "result", 1 );

    double scale = 1;
    CascadeClassifier nestedCascade; // todo delete
    for(;;)  {
        IplImage* iplImg = cvQueryFrame( capture );
        Mat frame = iplImg;
        if( frame.empty() )
            break;

        Mat frameCopy;
        if( iplImg->origin == IPL_ORIGIN_TL )
            frame.copyTo( frameCopy );
        else
            flip( frame, frameCopy, 0 );

        detectAndDraw( frameCopy, cascade, scale );

        if( waitKey( 10 ) >= 0 )
            goto _cleanup_;
    }

    waitKey(0);

_cleanup_:
    cvReleaseCapture( &capture );
    cvDestroyWindow("result");
    return 0;
}

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    double scale ) {
    int i = 0;
    double t = 0;
    vector<Rect> faces, faces2;
    const static Scalar colors[] =  { CV_RGB(0,0,255),
                                      CV_RGB(0,128,255),
                                      CV_RGB(0,255,255),
                                      CV_RGB(0,255,0),
                                      CV_RGB(255,128,0),
                                      CV_RGB(255,255,0),
                                      CV_RGB(255,0,0),
                                      CV_RGB(255,0,255)};

    Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );

    cvtColor( img, gray, CV_BGR2GRAY );
    resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
    equalizeHist( smallImg, smallImg );

    t = (double)cvGetTickCount();
    cascade.detectMultiScale( smallImg, faces,
        1.1, 2, 0
        //|CV_HAAR_FIND_BIGGEST_OBJECT
        //|CV_HAAR_DO_ROUGH_SEARCH
        |CV_HAAR_SCALE_IMAGE
        ,
        Size(30, 30) );

    t = (double)cvGetTickCount() - t;
    printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );

    for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
    {
        Mat smallImgROI;
        Point center;
        Scalar color = colors[i%8];
        int radius;

        double aspect_ratio = (double)r->width/r->height;
        if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
        {
            center.x = cvRound((r->x + r->width*0.5)*scale);
            center.y = cvRound((r->y + r->height*0.5)*scale);
            radius = cvRound((r->width + r->height)*0.25*scale);
            circle( img, center, radius, color, 3, 8, 0 );
        }
        else
            rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),
                       cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),
                       color, 3, 8, 0);
    }
    cv::imshow( "result", img );
}
<commit_msg>scale, cleaned<commit_after>#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <cctype>
#include <iostream>
#include <iterator>
#include <stdio.h>

using namespace std;
using namespace cv;

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    double scale);
string cascadeName = "./haarcascade_frontalface_alt.xml";

int main( int argc, const char** argv ) {
    CascadeClassifier cascade;
    if( !cascade.load( cascadeName ) ) {
        cerr << "ERROR: Could not load classifier cascade" << endl;
        return -1;
    }

    CvCapture* capture = cvCaptureFromCAM( 0 );
    if(!capture) {
        cerr << "Capture from CAM " <<  0  << " didn't work" << endl;
        return -1;
    }

    // todo, figure out how to make a fullscreen window.
    cvNamedWindow( "result", 1 );

    for(;;)  {
        IplImage* iplImg = cvQueryFrame( capture );
        Mat frame = iplImg;
        if( frame.empty() )
            break;

        Mat frameCopy;
        if( iplImg->origin == IPL_ORIGIN_TL )
            frame.copyTo( frameCopy );
        else
            flip( frame, frameCopy, 0 );

        detectAndDraw( frameCopy, cascade, 2.0 );

        if( waitKey( 10 ) >= 0 )
            goto _cleanup_;
    }

    waitKey(0);

_cleanup_:
    cvReleaseCapture( &capture );
    cvDestroyWindow("result");
    return 0;
}

void detectAndDraw( Mat& img, CascadeClassifier& cascade,
                    double scale ) {
    int i = 0;
    double t = 0;
    vector<Rect> faces, faces2;
    const static Scalar colors[] =  { CV_RGB(0,0,255),
                                      CV_RGB(0,128,255),
                                      CV_RGB(0,255,255),
                                      CV_RGB(0,255,0),
                                      CV_RGB(255,128,0),
                                      CV_RGB(255,255,0),
                                      CV_RGB(255,0,0),
                                      CV_RGB(255,0,255)};

    Mat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 );

    cvtColor( img, gray, CV_BGR2GRAY );
    resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR );
    equalizeHist( smallImg, smallImg );

    t = (double)cvGetTickCount();
    cascade.detectMultiScale( smallImg, faces,
        1.1, 2, 0
        //|CV_HAAR_FIND_BIGGEST_OBJECT
        //|CV_HAAR_DO_ROUGH_SEARCH
        |CV_HAAR_SCALE_IMAGE
        ,
        Size(30, 30) );

    t = (double)cvGetTickCount() - t;
    printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) );

    for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
    {
        Mat smallImgROI;
        Point center;
        Scalar color = colors[i%8];
        int radius;

        double aspect_ratio = (double)r->width/r->height;
        if( 0.75 < aspect_ratio && aspect_ratio < 1.3 )
        {
            center.x = cvRound((r->x + r->width*0.5)*scale);
            center.y = cvRound((r->y + r->height*0.5)*scale);
            radius = cvRound((r->width + r->height)*0.25*scale);
            circle( img, center, radius, color, 3, 8, 0 );
        }
        else
            rectangle( img, cvPoint(cvRound(r->x*scale), cvRound(r->y*scale)),
                       cvPoint(cvRound((r->x + r->width-1)*scale), cvRound((r->y + r->height-1)*scale)),
                       color, 3, 8, 0);
    }
    cv::imshow( "result", img );
}
<|endoftext|>


<commit_before>/*
 *  cam_SSAG.cpp
 *  PHD Guiding
 *
 *  Created by Craig Stark.
 *  Copyright (c) 2006, 2007, 2008, 2009, 2010 Craig Stark.
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *    Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *    Neither the name of Craig Stark, Stark Labs nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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 "phd.h"

#if defined (SSAG)

#include "camera.h"
#include "time.h"
#include "image_math.h"

#include <wx/stdpaths.h>
#include <wx/textfile.h>
//wxTextFile *qglogfile;

#include "cam_SSAG.h"
// QHY CMOS guide camera version
// Tom's driver

#include <Setupapi.h>

#define INITGUID
#include <devpkey.h>

extern int ushort_compare(const void * a, const void * b);

#if DONE_SUPPORTING_XP // this is the newer API, but it does not work on Windows XP

static bool GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const DEVPROPKEY& key, WCHAR *buf, DWORD size)
{
    DEVPROPTYPE proptype;
    return SetupDiGetDeviceProperty(h, data, &key, &proptype, (PBYTE)buf, size, &size, 0) &&
        proptype == DEVPROP_TYPE_STRING;
}

#else

static bool QueryValue(const wxRegKey& rk, const wxString& key, wxString& val)
{
    // prevent pop-up message if key does not exist
    bool save = wxLog::EnableLogging(false);
    bool ok = rk.QueryValue(key, val, false);
    wxLog::EnableLogging(save);
    return ok;
}

static wxString GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const wxString& key)
{
    wxString val;

    WCHAR buf[4096];
    DWORD size = sizeof(buf);
    DWORD proptype;
    if (SetupDiGetDeviceRegistryProperty(h, data, SPDRP_DRIVER, &proptype, (PBYTE)&buf[0], size, &size))
    {
        wxRegKey k(wxString("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\") + buf);
        if (!QueryValue(k, key, val))
        {
            Debug.AddLine("SSAG failed to get " + key + " driver property value");
        }
    }
    else
    {
        Debug.AddLine("SSAG failed to get SDRP_DIRVER registry property for SSAG");
    }

    return val;
}

#endif // XP

static unsigned int GetSSAGDriverVersion()
{
    // check to see if the SSAG driver is v2 ("1.2.0.0") or v4 ("3.0.0.0")

    Debug.AddLine("Checking SSAG driver version");

    bool found = false;
    unsigned int driverVersion = 2; // assume v2

    HDEVINFO h = SetupDiGetClassDevs(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (h != INVALID_HANDLE_VALUE)
    {
        DWORD idx = 0;
        SP_DEVINFO_DATA data;
        memset(&data, 0, sizeof(data));
        data.cbSize = sizeof(data);

        while (SetupDiEnumDeviceInfo(h, idx, &data))
        {
#if DONE_SUPPORTING_XP
            WCHAR buf[4096];

            if (GetDiPropStr(h, &data, DEVPKEY_Device_InstanceId, buf, sizeof(buf)) &&
                (wcsncmp(buf, L"USB\\VID_1856&PID_0012\\", 22) == 0) ||
                (wcsncmp(buf, L"USB\\VID_1856&PID_0011\\", 22) == 0))
            {
                Debug.AddLine(wxString::Format("Found SSAG device %s", buf));
                if (GetDiPropStr(h, &data, DEVPKEY_Device_DriverVersion, buf, sizeof(buf)))
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", wxString(buf)));
                    int v;
                    if (swscanf(buf, L"%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                found = true;
                break;
            }
#else
            WCHAR buf[4096];
            DWORD size = sizeof(buf);
            DWORD proptype;

            if (SetupDiGetDeviceRegistryProperty(h, &data, SPDRP_HARDWAREID, &proptype, (PBYTE)&buf[0], size, &size) &&
                (wcsncmp(buf, L"USB\\VID_1856&PID_0012", 21) == 0 ||
                 wcsncmp(buf, L"USB\\VID_1856&PID_0011", 21) == 0))
            {
                Debug.AddLine(wxString::Format("Found SSAG device %s", buf));
                wxString ver = GetDiPropStr(h, &data, "DriverVersion");
                if (ver.Length())
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", ver));
                    int v;
                    if (wxSscanf(ver, "%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                found = true;
                break;
            }
#endif // XP

            ++idx;
        }

        SetupDiDestroyDeviceInfoList(h);
    }

    if (!found)
        Debug.AddLine("No SSAG device was found");

    return driverVersion;
}

// declare function pointers for imported functions

#define F1(r,f,a1)             typedef r (_stdcall *f##_t)(a1);             static f##_t f;
#define F2(r,f,a1,a2)          typedef r (_stdcall *f##_t)(a1,a2);          static f##_t f;
#define F5(r,f,a1,a2,a3,a4,a5) typedef r (_stdcall *f##_t)(a1,a2,a3,a4,a5); static f##_t f;
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5

// initialize the function pointers

static bool InitProcs(HINSTANCE hinst)
{
    bool ok = false;

    try
    {

#define F(f,n) \
    if ((f = (f##_t) GetProcAddress(hinst, n)) == NULL) \
        throw ERROR_INFO("SSAGIF DLL missing " n);
#define F1(r,f,a1) F(f,#f)
#define F2(r,f,a1,a2) F(f,#f)
#define F5(r,f,a1,a2,a3,a4,a5) F(f,#f)
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5
#undef F

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
    }

    return ok;
}

static HINSTANCE s_dllinst;

//
// load the SSAGv2 or SSAGv4 DLL based on the SSAG driver version and load the addresses of the imported functions
//
static bool LoadSSAGIFDll()
{
    bool ok = false;

    try
    {
        unsigned int driverVersion = GetSSAGDriverVersion();

        LPCWSTR libname;
        if (driverVersion == 2)
            libname = _T("SSAGIFv2.dll");
        else if (driverVersion == 4)
            libname = _T("SSAGIFv4.dll");
        else
            throw ERROR_INFO("unexpected SSAG driver version!");

        wxASSERT(s_dllinst == NULL);
        Debug.AddLine(wxString::Format("Loading SSAG dll %s", libname));
        s_dllinst = LoadLibrary(libname);
        if (s_dllinst == NULL)
            throw ERROR_INFO("SSAG LoadLibrary failed");

        if (!InitProcs(s_dllinst))
            throw ERROR_INFO("SSAG failed to load required symbols");

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
        if (s_dllinst != NULL)
        {
            FreeLibrary(s_dllinst);
            s_dllinst = NULL;
        }
    }

    return ok;
}

static void UnloadSSAGIFDll()
{
    if (s_dllinst != NULL)
    {
        Debug.AddLine("Unloading SSAG DLL");
        FreeLibrary(s_dllinst);
        s_dllinst = NULL;
    }
}

Camera_SSAGClass::Camera_SSAGClass()
{
    Connected = false;
    Name = _T("StarShoot Autoguider");
    FullSize = wxSize(1280, 1024);
    m_hasGuideOutput = true;
    HasGainControl = true;
    PixelSize = 5.2;
}

bool Camera_SSAGClass::Connect()
{
    // returns true on error

    if (!LoadSSAGIFDll())
        return true;

    if (!_SSAG_openUSB())
    {
        UnloadSSAGIFDll();
        return true;
    }

    _SSAG_SETBUFFERMODE(0);
    Connected = true;

    //qglogfile = new wxTextFile(Debug.GetLogDir() + PATHSEPSTR + _T("PHD_QGuide_log.txt"));
    //qglogfile->AddLine(wxNow() + ": QGuide connected"); //qglogfile->Write();

    return false;
}

bool Camera_SSAGClass::ST4PulseGuideScope(int direction, int duration)
{
    int reg = 0;
    int dur = duration / 10;

    //qglogfile->AddLine(wxString::Format("Sending guide dur %d",dur)); //qglogfile->Write();

    if (dur >= 255) dur = 254; // Max guide pulse is 2.54s -- 255 keeps it on always

    // Output pins are NC, Com, RA+(W), Dec+(N), Dec-(S), RA-(E) ??  http://www.starlight-xpress.co.uk/faq.htm
    switch (direction) {
        case WEST: reg = 0x80; break;   // 0111 0000
        case NORTH: reg = 0x40; break;  // 1011 0000
        case SOUTH: reg = 0x20; break;  // 1101 0000
        case EAST: reg = 0x10;  break;  // 1110 0000
        default: return true; // bad direction passed in
    }
    _SSAG_GuideCommand(reg, dur);

    wxMilliSleep(duration + 10);

    //qglogfile->AddLine("Done"); //qglogfile->Write();

    return false;
}

void Camera_SSAGClass::ClearGuidePort()
{
}

void Camera_SSAGClass::InitCapture()
{
    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));
    _SSAG_SetNoiseReduction(0);
}

bool Camera_SSAGClass::Disconnect()
{
    _SSAG_closeUSB();
    UnloadSSAGIFDll();
    Connected = false;
    //qglogfile->AddLine(wxNow() + ": Disconnecting"); //qglogfile->Write(); //qglogfile->Close();
    return false;
}

bool Camera_SSAGClass::Capture(int duration, usImage& img, wxRect subframe, bool recon)
{
    // Only does full frames

    unsigned short *dptr;
    int xsize = FullSize.GetWidth();
    int ysize = FullSize.GetHeight();
    bool firstimg = true;

    //qglogfile->AddLine(wxString::Format("Capturing dur %d",duration)); //qglogfile->Write();

    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));

    if (img.NPixels != (xsize*ysize))
    {
        if (img.Init(xsize,ysize))
        {
            pFrame->Alert(_T("Memory allocation error during capture"));
            Disconnect();
            return true;
        }
    }

    _SSAG_ThreadedExposure(duration, NULL);

    //qglogfile->AddLine("Exposure programmed"); //qglogfile->Write();

    if (duration > 100) {
        wxMilliSleep(duration - 100);
        wxGetApp().Yield();
    }

    while (_SSAG_isExposing())
        wxMilliSleep(50);

    //qglogfile->AddLine("Exposure done"); //qglogfile->Write();

    dptr = img.ImageData;
    _SSAG_GETBUFFER(dptr, img.NPixels * 2);

    if (recon) SubtractDark(img);

    //qglogfile->AddLine("Image loaded"); //qglogfile->Write();

    // Do quick L recon to remove bayer array
//  QuickLRecon(img);
//  RemoveLines(img);

    return false;
}

void Camera_SSAGClass::RemoveLines(usImage& img)
{
    int i, j, val;
    unsigned short data[21];
    unsigned short *ptr1, *ptr2;
    unsigned short med[1024];
    int offset;
    double mean;
    int h = img.Size.GetHeight();
    int w = img.Size.GetWidth();
    size_t sz = sizeof(unsigned short);
    mean = 0.0;

    for (i=0; i<h; i++) {
        ptr1 = data;
        ptr2 = img.ImageData + i*w;
        for (j=0; j<21; j++, ptr1++, ptr2++)
            *ptr1 = *ptr2;
        qsort(data,21,sz,ushort_compare);
        med[i] = data[10];
        mean = mean + (double) (med[i]);
    }
    mean = mean / (double) h;
    for (i=0; i<h; i++) {
        offset = (int) mean - (int) med[i];
        ptr2 = img.ImageData + i*w;
        for (j=0; j<w; j++, ptr2++) {
            val = (int) *ptr2 + offset;
            if (val < 0) val = 0;
            else if (val > 65535) val = 65535;
            *ptr2 = (unsigned short) val;
        }

    }
}

#endif
<commit_msg>fix typo in debug message<commit_after>/*
 *  cam_SSAG.cpp
 *  PHD Guiding
 *
 *  Created by Craig Stark.
 *  Copyright (c) 2006, 2007, 2008, 2009, 2010 Craig Stark.
 *  All rights reserved.
 *
 *  This source code is distributed under the following "BSD" license
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *    Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *    Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *    Neither the name of Craig Stark, Stark Labs nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 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 "phd.h"

#if defined (SSAG)

#include "camera.h"
#include "time.h"
#include "image_math.h"

#include <wx/stdpaths.h>
#include <wx/textfile.h>
//wxTextFile *qglogfile;

#include "cam_SSAG.h"
// QHY CMOS guide camera version
// Tom's driver

#include <Setupapi.h>

#define INITGUID
#include <devpkey.h>

extern int ushort_compare(const void * a, const void * b);

#if DONE_SUPPORTING_XP // this is the newer API, but it does not work on Windows XP

static bool GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const DEVPROPKEY& key, WCHAR *buf, DWORD size)
{
    DEVPROPTYPE proptype;
    return SetupDiGetDeviceProperty(h, data, &key, &proptype, (PBYTE)buf, size, &size, 0) &&
        proptype == DEVPROP_TYPE_STRING;
}

#else

static bool QueryValue(const wxRegKey& rk, const wxString& key, wxString& val)
{
    // prevent pop-up message if key does not exist
    bool save = wxLog::EnableLogging(false);
    bool ok = rk.QueryValue(key, val, false);
    wxLog::EnableLogging(save);
    return ok;
}

static wxString GetDiPropStr(HDEVINFO h, SP_DEVINFO_DATA *data, const wxString& key)
{
    wxString val;

    WCHAR buf[4096];
    DWORD size = sizeof(buf);
    DWORD proptype;
    if (SetupDiGetDeviceRegistryProperty(h, data, SPDRP_DRIVER, &proptype, (PBYTE)&buf[0], size, &size))
    {
        wxRegKey k(wxString("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\") + buf);
        if (!QueryValue(k, key, val))
        {
            Debug.AddLine("SSAG failed to get " + key + " driver property value");
        }
    }
    else
    {
        Debug.AddLine("SSAG failed to get SDRP_DRIVER registry property for SSAG");
    }

    return val;
}

#endif // XP

static unsigned int GetSSAGDriverVersion()
{
    // check to see if the SSAG driver is v2 ("1.2.0.0") or v4 ("3.0.0.0")

    Debug.AddLine("Checking SSAG driver version");

    bool found = false;
    unsigned int driverVersion = 2; // assume v2

    HDEVINFO h = SetupDiGetClassDevs(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
    if (h != INVALID_HANDLE_VALUE)
    {
        DWORD idx = 0;
        SP_DEVINFO_DATA data;
        memset(&data, 0, sizeof(data));
        data.cbSize = sizeof(data);

        while (SetupDiEnumDeviceInfo(h, idx, &data))
        {
#if DONE_SUPPORTING_XP
            WCHAR buf[4096];

            if (GetDiPropStr(h, &data, DEVPKEY_Device_InstanceId, buf, sizeof(buf)) &&
                (wcsncmp(buf, L"USB\\VID_1856&PID_0012\\", 22) == 0) ||
                (wcsncmp(buf, L"USB\\VID_1856&PID_0011\\", 22) == 0))
            {
                Debug.AddLine(wxString::Format("Found SSAG device %s", buf));
                if (GetDiPropStr(h, &data, DEVPKEY_Device_DriverVersion, buf, sizeof(buf)))
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", wxString(buf)));
                    int v;
                    if (swscanf(buf, L"%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                found = true;
                break;
            }
#else
            WCHAR buf[4096];
            DWORD size = sizeof(buf);
            DWORD proptype;

            if (SetupDiGetDeviceRegistryProperty(h, &data, SPDRP_HARDWAREID, &proptype, (PBYTE)&buf[0], size, &size) &&
                (wcsncmp(buf, L"USB\\VID_1856&PID_0012", 21) == 0 ||
                 wcsncmp(buf, L"USB\\VID_1856&PID_0011", 21) == 0))
            {
                Debug.AddLine(wxString::Format("Found SSAG device %s", buf));
                wxString ver = GetDiPropStr(h, &data, "DriverVersion");
                if (ver.Length())
                {
                    Debug.AddLine(wxString::Format("SSAG driver version is %s", ver));
                    int v;
                    if (wxSscanf(ver, "%d", &v) == 1 && v >= 3)
                    {
                        driverVersion = 4;
                    }
                }
                found = true;
                break;
            }
#endif // XP

            ++idx;
        }

        SetupDiDestroyDeviceInfoList(h);
    }

    if (!found)
        Debug.AddLine("No SSAG device was found");

    return driverVersion;
}

// declare function pointers for imported functions

#define F1(r,f,a1)             typedef r (_stdcall *f##_t)(a1);             static f##_t f;
#define F2(r,f,a1,a2)          typedef r (_stdcall *f##_t)(a1,a2);          static f##_t f;
#define F5(r,f,a1,a2,a3,a4,a5) typedef r (_stdcall *f##_t)(a1,a2,a3,a4,a5); static f##_t f;
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5

// initialize the function pointers

static bool InitProcs(HINSTANCE hinst)
{
    bool ok = false;

    try
    {

#define F(f,n) \
    if ((f = (f##_t) GetProcAddress(hinst, n)) == NULL) \
        throw ERROR_INFO("SSAGIF DLL missing " n);
#define F1(r,f,a1) F(f,#f)
#define F2(r,f,a1,a2) F(f,#f)
#define F5(r,f,a1,a2,a3,a4,a5) F(f,#f)
#include "cameras/_SSAGIF.h"
#undef F1
#undef F2
#undef F5
#undef F

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
    }

    return ok;
}

static HINSTANCE s_dllinst;

//
// load the SSAGv2 or SSAGv4 DLL based on the SSAG driver version and load the addresses of the imported functions
//
static bool LoadSSAGIFDll()
{
    bool ok = false;

    try
    {
        unsigned int driverVersion = GetSSAGDriverVersion();

        LPCWSTR libname;
        if (driverVersion == 2)
            libname = _T("SSAGIFv2.dll");
        else if (driverVersion == 4)
            libname = _T("SSAGIFv4.dll");
        else
            throw ERROR_INFO("unexpected SSAG driver version!");

        wxASSERT(s_dllinst == NULL);
        Debug.AddLine(wxString::Format("Loading SSAG dll %s", libname));
        s_dllinst = LoadLibrary(libname);
        if (s_dllinst == NULL)
            throw ERROR_INFO("SSAG LoadLibrary failed");

        if (!InitProcs(s_dllinst))
            throw ERROR_INFO("SSAG failed to load required symbols");

        ok = true;
    }
    catch (const wxString& msg)
    {
        POSSIBLY_UNUSED(msg);
        if (s_dllinst != NULL)
        {
            FreeLibrary(s_dllinst);
            s_dllinst = NULL;
        }
    }

    return ok;
}

static void UnloadSSAGIFDll()
{
    if (s_dllinst != NULL)
    {
        Debug.AddLine("Unloading SSAG DLL");
        FreeLibrary(s_dllinst);
        s_dllinst = NULL;
    }
}

Camera_SSAGClass::Camera_SSAGClass()
{
    Connected = false;
    Name = _T("StarShoot Autoguider");
    FullSize = wxSize(1280, 1024);
    m_hasGuideOutput = true;
    HasGainControl = true;
    PixelSize = 5.2;
}

bool Camera_SSAGClass::Connect()
{
    // returns true on error

    if (!LoadSSAGIFDll())
        return true;

    if (!_SSAG_openUSB())
    {
        UnloadSSAGIFDll();
        return true;
    }

    _SSAG_SETBUFFERMODE(0);
    Connected = true;

    //qglogfile = new wxTextFile(Debug.GetLogDir() + PATHSEPSTR + _T("PHD_QGuide_log.txt"));
    //qglogfile->AddLine(wxNow() + ": QGuide connected"); //qglogfile->Write();

    return false;
}

bool Camera_SSAGClass::ST4PulseGuideScope(int direction, int duration)
{
    int reg = 0;
    int dur = duration / 10;

    //qglogfile->AddLine(wxString::Format("Sending guide dur %d",dur)); //qglogfile->Write();

    if (dur >= 255) dur = 254; // Max guide pulse is 2.54s -- 255 keeps it on always

    // Output pins are NC, Com, RA+(W), Dec+(N), Dec-(S), RA-(E) ??  http://www.starlight-xpress.co.uk/faq.htm
    switch (direction) {
        case WEST: reg = 0x80; break;   // 0111 0000
        case NORTH: reg = 0x40; break;  // 1011 0000
        case SOUTH: reg = 0x20; break;  // 1101 0000
        case EAST: reg = 0x10;  break;  // 1110 0000
        default: return true; // bad direction passed in
    }
    _SSAG_GuideCommand(reg, dur);

    wxMilliSleep(duration + 10);

    //qglogfile->AddLine("Done"); //qglogfile->Write();

    return false;
}

void Camera_SSAGClass::ClearGuidePort()
{
}

void Camera_SSAGClass::InitCapture()
{
    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));
    _SSAG_SetNoiseReduction(0);
}

bool Camera_SSAGClass::Disconnect()
{
    _SSAG_closeUSB();
    UnloadSSAGIFDll();
    Connected = false;
    //qglogfile->AddLine(wxNow() + ": Disconnecting"); //qglogfile->Write(); //qglogfile->Close();
    return false;
}

bool Camera_SSAGClass::Capture(int duration, usImage& img, wxRect subframe, bool recon)
{
    // Only does full frames

    unsigned short *dptr;
    int xsize = FullSize.GetWidth();
    int ysize = FullSize.GetHeight();
    bool firstimg = true;

    //qglogfile->AddLine(wxString::Format("Capturing dur %d",duration)); //qglogfile->Write();

    _SSAG_ProgramCamera(0, 0, 1280, 1024, (GuideCameraGain * 63 / 100));

    if (img.NPixels != (xsize*ysize))
    {
        if (img.Init(xsize,ysize))
        {
            pFrame->Alert(_T("Memory allocation error during capture"));
            Disconnect();
            return true;
        }
    }

    _SSAG_ThreadedExposure(duration, NULL);

    //qglogfile->AddLine("Exposure programmed"); //qglogfile->Write();

    if (duration > 100) {
        wxMilliSleep(duration - 100);
        wxGetApp().Yield();
    }

    while (_SSAG_isExposing())
        wxMilliSleep(50);

    //qglogfile->AddLine("Exposure done"); //qglogfile->Write();

    dptr = img.ImageData;
    _SSAG_GETBUFFER(dptr, img.NPixels * 2);

    if (recon) SubtractDark(img);

    //qglogfile->AddLine("Image loaded"); //qglogfile->Write();

    // Do quick L recon to remove bayer array
//  QuickLRecon(img);
//  RemoveLines(img);

    return false;
}

void Camera_SSAGClass::RemoveLines(usImage& img)
{
    int i, j, val;
    unsigned short data[21];
    unsigned short *ptr1, *ptr2;
    unsigned short med[1024];
    int offset;
    double mean;
    int h = img.Size.GetHeight();
    int w = img.Size.GetWidth();
    size_t sz = sizeof(unsigned short);
    mean = 0.0;

    for (i=0; i<h; i++) {
        ptr1 = data;
        ptr2 = img.ImageData + i*w;
        for (j=0; j<21; j++, ptr1++, ptr2++)
            *ptr1 = *ptr2;
        qsort(data,21,sz,ushort_compare);
        med[i] = data[10];
        mean = mean + (double) (med[i]);
    }
    mean = mean / (double) h;
    for (i=0; i<h; i++) {
        offset = (int) mean - (int) med[i];
        ptr2 = img.ImageData + i*w;
        for (j=0; j<w; j++, ptr2++) {
            val = (int) *ptr2 + offset;
            if (val < 0) val = 0;
            else if (val > 65535) val = 65535;
            *ptr2 = (unsigned short) val;
        }

    }
}

#endif
<|endoftext|>