<commit_before>/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * Copyright Projet JRL-Japan, 2007
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * File:      FeatureTask.cpp
 * Project:   SOT
 * Author:    Nicolas Mansard
 *
 * Version control
 * ===============
 *
 *  $Id$
 *
 * Description
 * ============
 *
 *
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/* --------------------------------------------------------------------- */
/* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */

/* --- SOT --- */
#include <sot-core/debug.h>
#include <sot-core/feature-task.h>
#include <sot-core/exception-feature.h>
#include <dynamic-graph/pool.h>
using namespace std;
using namespace sot;
using namespace dynamicgraph;

#include <sot-core/factory.h>
SOT_FACTORY_FEATURE_PLUGIN(FeatureTask,"FeatureTask");

/* --------------------------------------------------------------------- */
/* --- CLASS ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */

FeatureTask::
FeatureTask( const string& pointName )
  : FeatureGeneric( pointName )
{
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

ml::Vector& FeatureTask::
computeError( ml::Vector& res,int time )
{
  const ml::Vector& err = errorSIN.access(time);
  const Flags &fl = selectionSIN.access(time);
  const unsigned int & dim = dimensionSOUT(time);

  unsigned int curr = 0;
  res.resize( dim );
  if( err.size()<dim )
    { SOT_THROW ExceptionFeature( ExceptionFeature::UNCOMPATIBLE_SIZE,
				     "Error: dimension uncompatible with des->errorIN size."
				     " (while considering feature <%s>).",getName().c_str() ); }

  FeatureTask * sdes = NULL;
  if( desiredValueSIN )
    {
      FeatureAbstract* sdesAbs = desiredValueSIN(time);
      sdes = dynamic_cast<FeatureTask*>(sdesAbs);
    }

  sotDEBUG(15) << "Err = " << err;
  sotDEBUG(25) << "Dim = " << dim << endl;

  if( sdes )
    {
      const ml::Vector& errDes = sdes->errorSIN(time);
      sotDEBUG(15) << "Err* = " << errDes;
      if( errDes.size()<dim )
	{ SOT_THROW ExceptionFeature( ExceptionFeature::UNCOMPATIBLE_SIZE,
					 "Error: dimension uncompatible with des->errorIN size."
					 " (while considering feature <%s>).",getName().c_str() ); }

      for( unsigned int i=0;i<err.size();++i ) if( fl(i) )
	if( fl(i) ) res( curr++ ) = err(i)-errDes(i);
    }
  else for( unsigned int i=0;i<err.size();++i )
    if( fl(i) ) res( curr++ ) = -err(i);

  return res;

}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

void FeatureTask::
display( std::ostream& os ) const
{
  os << "Feature from task <" << getName();
  if( taskPtr ) os <<  ": from task " << taskPtr->getName();
  os << std::endl;
}

void FeatureTask::
commandLine( const std::string& cmdLine,
	     std::istringstream& cmdArgs,
	     std::ostream& os )
{
  if( cmdLine == "help" )
    {
      os << "FeatureTask: "
	 << "  - task [<taskname>] " << std::endl;
    }
  else if( cmdLine == "task" )
    {
      cmdArgs >>std::ws;
      if( cmdArgs.good() )
	{
	  std::string name; cmdArgs >> name;
	  TaskAbstract& task = dynamic_cast< TaskAbstract & > (g_pool .getEntity( name ));
	  taskPtr = &task;

	  errorSIN.plug( &task.taskSOUT );
	  jacobianSIN.plug( &task.jacobianSOUT );
	  activationSIN.plug( &task.featureActivationSOUT );
	} else {
	  if( taskPtr ) os << "task = " << (*taskPtr) << std::endl;
	  else  os << "task = NULL " <<std::endl;
	}
    }
  else { Entity::commandLine( cmdLine,cmdArgs,os); }
}

/*
 * Local variables:
 * c-basic-offset: 2
 * End:
 */
<commit_msg>sotFeatureTask depends on sotTask, not sotAbstractTask<commit_after>/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * Copyright Projet JRL-Japan, 2007
 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * File:      FeatureTask.cpp
 * Project:   SOT
 * Author:    Nicolas Mansard
 *
 * Version control
 * ===============
 *
 *  $Id$
 *
 * Description
 * ============
 *
 *
 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

/* --------------------------------------------------------------------- */
/* --- INCLUDE --------------------------------------------------------- */
/* --------------------------------------------------------------------- */

/* --- SOT --- */
#include <sot-core/debug.h>
#include <sot-core/feature-task.h>
#include <sot-core/exception-feature.h>
#include <sot-core/task.h>
#include <dynamic-graph/pool.h>
using namespace std;
using namespace sot;
using namespace dynamicgraph;

#include <sot-core/factory.h>
SOT_FACTORY_FEATURE_PLUGIN(FeatureTask,"FeatureTask");

/* --------------------------------------------------------------------- */
/* --- CLASS ----------------------------------------------------------- */
/* --------------------------------------------------------------------- */

FeatureTask::
FeatureTask( const string& pointName )
  : FeatureGeneric( pointName )
{
}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

ml::Vector& FeatureTask::
computeError( ml::Vector& res,int time )
{
  const ml::Vector& err = errorSIN.access(time);
  const Flags &fl = selectionSIN.access(time);
  const unsigned int & dim = dimensionSOUT(time);

  unsigned int curr = 0;
  res.resize( dim );
  if( err.size()<dim )
    { SOT_THROW ExceptionFeature( ExceptionFeature::UNCOMPATIBLE_SIZE,
				     "Error: dimension uncompatible with des->errorIN size."
				     " (while considering feature <%s>).",getName().c_str() ); }

  FeatureTask * sdes = NULL;
  if( desiredValueSIN )
    {
      FeatureAbstract* sdesAbs = desiredValueSIN(time);
      sdes = dynamic_cast<FeatureTask*>(sdesAbs);
    }

  sotDEBUG(15) << "Err = " << err;
  sotDEBUG(25) << "Dim = " << dim << endl;

  if( sdes )
    {
      const ml::Vector& errDes = sdes->errorSIN(time);
      sotDEBUG(15) << "Err* = " << errDes;
      if( errDes.size()<dim )
	{ SOT_THROW ExceptionFeature( ExceptionFeature::UNCOMPATIBLE_SIZE,
					 "Error: dimension uncompatible with des->errorIN size."
					 " (while considering feature <%s>).",getName().c_str() ); }

      for( unsigned int i=0;i<err.size();++i ) if( fl(i) )
	if( fl(i) ) res( curr++ ) = err(i)-errDes(i);
    }
  else for( unsigned int i=0;i<err.size();++i )
    if( fl(i) ) res( curr++ ) = -err(i);

  return res;

}

/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

void FeatureTask::
display( std::ostream& os ) const
{
  os << "Feature from task <" << getName();
  if( taskPtr ) os <<  ": from task " << taskPtr->getName();
  os << std::endl;
}

void FeatureTask::
commandLine( const std::string& cmdLine,
	     std::istringstream& cmdArgs,
	     std::ostream& os )
{
  if( cmdLine == "help" )
    {
      os << "FeatureTask: "
	 << "  - task [<taskname>] " << std::endl;
    }
  else if( cmdLine == "task" )
    {
      cmdArgs >>std::ws;
      if( cmdArgs.good() )
	{
	  std::string name; cmdArgs >> name;
	  Task& task = dynamic_cast< Task & > (g_pool .getEntity( name ));
	  taskPtr = &task;

	  errorSIN.plug( &task.errorSOUT );
	  jacobianSIN.plug( &task.jacobianSOUT );
	  activationSIN.plug( &task.featureActivationSOUT );
	} else {
	  if( taskPtr ) os << "task = " << (*taskPtr) << std::endl;
	  else  os << "task = NULL " <<std::endl;
	}
    }
  else { Entity::commandLine( cmdLine,cmdArgs,os); }
}

/*
 * Local variables:
 * c-basic-offset: 2
 * End:
 */
<|endoftext|>


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

#include "stdio.h"
#include "time.h"

#include "base/logging.h"

namespace google_base {
DateLogger::DateLogger() {
#if defined(_MSC_VER)
  _tzset();
#endif
}

char* const DateLogger::HumanDate() {
#if defined(_MSC_VER)
  _strtime_s(buffer_, sizeof(buffer_));
#else
  time_t time_value = time(NULL);
  struct tm now;
  localtime_r(&time_value, &now);
  snprintf(buffer_, sizeof(buffer_), "%02d:%02d:%02d",
           now.tm_hour, now.tm_min, now.tm_sec);
#endif
  return buffer_;
}
}  // namespace google_base
<commit_msg>Use localtime_s on Windows (required by new toolchain) (#9)<commit_after>// Copyright 2010 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "stdio.h"
#include "time.h"

#include "base/logging.h"

namespace google_base {
DateLogger::DateLogger() {
#if defined(_MSC_VER)
  _tzset();
#endif
}

char* const DateLogger::HumanDate() {
#if defined(_MSC_VER)
  _strtime_s(buffer_, sizeof(buffer_));
#else
  time_t time_value = time(NULL);
  struct tm now;
#ifdef _WIN32
  localtime_s(&now, &time_value);
#else
  localtime_r(&time_value, &now);
#endif
  snprintf(buffer_, sizeof(buffer_), "%02d:%02d:%02d",
           now.tm_hour, now.tm_min, now.tm_sec);
#endif
  return buffer_;
}
}  // namespace google_base
<|endoftext|>


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

#include "GrDrawingManager.h"

#include "GrBackendSemaphore.h"
#include "GrContext.h"
#include "GrGpu.h"
#include "GrOnFlushResourceProvider.h"
#include "GrOpList.h"
#include "GrRenderTargetContext.h"
#include "GrPathRenderingRenderTargetContext.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceAllocator.h"
#include "GrResourceProvider.h"
#include "GrSoftwarePathRenderer.h"
#include "GrSurfaceProxyPriv.h"
#include "GrTextureContext.h"
#include "GrTextureOpList.h"
#include "SkSurface_Gpu.h"
#include "SkTTopoSort.h"

#include "GrTracing.h"
#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"

void GrDrawingManager::cleanup() {
    for (int i = 0; i < fOpLists.count(); ++i) {
        // no opList should receive a new command after this
        fOpLists[i]->makeClosed(*fContext->caps());

        // We shouldn't need to do this, but it turns out some clients still hold onto opLists
        // after a cleanup.
        // MDB TODO: is this still true?
        fOpLists[i]->reset();
    }

    fOpLists.reset();

    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);

    fOnFlushCBObjects.reset();
}

GrDrawingManager::~GrDrawingManager() {
    this->cleanup();
}

void GrDrawingManager::abandon() {
    fAbandoned = true;
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->abandonGpuResources();
    }
    this->cleanup();
}

void GrDrawingManager::freeGpuResources() {
    for (int i = fOnFlushCBObjects.count() - 1; i >= 0; --i) {
        if (!fOnFlushCBObjects[i]->retainOnFreeGpuResources()) {
            // it's safe to just do this because we're iterating in reverse
            fOnFlushCBObjects.removeShuffle(i);
        }
    }

    // a path renderer may be holding onto resources
    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->freeGpuResources();
    }

}

void GrDrawingManager::reset() {
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->reset();
    }
    fFlushState.reset();
}

gr_instanced::OpAllocator* GrDrawingManager::instancingAllocator() {
    if (fInstancingAllocator) {
        return fInstancingAllocator.get();
    }

    fInstancingAllocator = fContext->getGpu()->createInstancedRenderingAllocator();
    return fInstancingAllocator.get();
}

// MDB TODO: make use of the 'proxy' parameter.
GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
                                                      GrResourceCache::FlushType type,
                                                      int numSemaphores,
                                                      GrBackendSemaphore backendSemaphores[]) {
    GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "internalFlush", fContext);

    if (fFlushing || this->wasAbandoned()) {
        return GrSemaphoresSubmitted::kNo;
    }
    fFlushing = true;
    bool flushed = false;

    for (int i = 0; i < fOpLists.count(); ++i) {
        // Semi-usually the GrOpLists are already closed at this point, but sometimes Ganesh
        // needs to flush mid-draw. In that case, the SkGpuDevice's GrOpLists won't be closed
        // but need to be flushed anyway. Closing such GrOpLists here will mean new
        // GrOpLists will be created to replace them if the SkGpuDevice(s) write to them again.
        fOpLists[i]->makeClosed(*fContext->caps());
    }

#ifdef SK_DEBUG
    // This block checks for any unnecessary splits in the opLists. If two sequential opLists
    // share the same backing GrSurfaceProxy it means the opList was artificially split.
    if (fOpLists.count()) {
        GrRenderTargetOpList* prevOpList = fOpLists[0]->asRenderTargetOpList();
        for (int i = 1; i < fOpLists.count(); ++i) {
            GrRenderTargetOpList* curOpList = fOpLists[i]->asRenderTargetOpList();

            if (prevOpList && curOpList) {
                SkASSERT(prevOpList->fTarget.get() != curOpList->fTarget.get());
            }

            prevOpList = curOpList;
        }
    }
#endif

#ifdef ENABLE_MDB_SORT
    SkDEBUGCODE(bool result =)
                        SkTTopoSort<GrOpList, GrOpList::TopoSortTraits>(&fOpLists);
    SkASSERT(result);
#endif

    GrOnFlushResourceProvider onFlushProvider(this);

    if (!fOnFlushCBObjects.empty()) {
        // MDB TODO: pre-MDB '1' is the correct pre-allocated size. Post-MDB it will need
        // to be larger.
        SkAutoSTArray<1, uint32_t> opListIds(fOpLists.count());
        for (int i = 0; i < fOpLists.count(); ++i) {
            opListIds[i] = fOpLists[i]->uniqueID();
        }

        SkSTArray<1, sk_sp<GrRenderTargetContext>> renderTargetContexts;
        for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
            onFlushCBObject->preFlush(&onFlushProvider,
                                      opListIds.get(), opListIds.count(),
                                      &renderTargetContexts);
            if (!renderTargetContexts.count()) {
                continue;       // This is fine. No atlases of this type are required for this flush
            }

            for (int j = 0; j < renderTargetContexts.count(); ++j) {
                GrOpList* opList = renderTargetContexts[j]->getOpList();
                if (!opList) {
                    continue;   // Odd - but not a big deal
                }
                opList->makeClosed(*fContext->caps());
                opList->prepare(&fFlushState);
                if (!opList->execute(&fFlushState)) {
                    continue;         // This is bad
                }
            }
            renderTargetContexts.reset();
        }
    }

#if 0
    // Enable this to print out verbose GrOp information
    for (int i = 0; i < fOpLists.count(); ++i) {
        SkDEBUGCODE(fOpLists[i]->dump();)
    }
#endif

#ifdef MDB_ALLOC_RESOURCES
    GrResourceAllocator alloc(fContext->resourceProvider());
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->gatherProxyIntervals(&alloc);
    }

    alloc.assign();
#endif

    for (int i = 0; i < fOpLists.count(); ++i) {
        if (!fOpLists[i]->instantiate(fContext->resourceProvider())) {
            SkDebugf("OpList failed to instantiate.\n");
            fOpLists[i] = nullptr;
            continue;
        }

        // Instantiate all deferred proxies (being built on worker threads) so we can upload them
        fOpLists[i]->instantiateDeferredProxies(fContext->resourceProvider());
        fOpLists[i]->prepare(&fFlushState);
    }

    // Upload all data to the GPU
    fFlushState.preIssueDraws();

    for (int i = 0; i < fOpLists.count(); ++i) {
        if (!fOpLists[i]) {
            continue;
        }

        if (fOpLists[i]->execute(&fFlushState)) {
            flushed = true;
        }
    }

    SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());

    // We reset the flush state before the OpLists so that the last resources to be freed are those
    // that are written to in the OpLists. This helps to make sure the most recently used resources
    // are the last to be purged by the resource cache.
    fFlushState.reset();

    for (int i = 0; i < fOpLists.count(); ++i) {
        if (!fOpLists[i]) {
            continue;
        }
        fOpLists[i]->reset();
    }
    fOpLists.reset();

    GrSemaphoresSubmitted result = fContext->getGpu()->finishFlush(numSemaphores,
                                                                   backendSemaphores);

    // We always have to notify the cache when it requested a flush so it can reset its state.
    if (flushed || type == GrResourceCache::FlushType::kCacheRequested) {
        fContext->getResourceCache()->notifyFlushOccurred(type);
    }
    for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
        onFlushCBObject->postFlush(fFlushState.nextTokenToFlush());
    }
    fFlushing = false;

    return result;
}

GrSemaphoresSubmitted GrDrawingManager::prepareSurfaceForExternalIO(
        GrSurfaceProxy* proxy, int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
    if (this->wasAbandoned()) {
        return GrSemaphoresSubmitted::kNo;
    }
    SkASSERT(proxy);

    GrSemaphoresSubmitted result;
    if (proxy->priv().hasPendingIO() || numSemaphores) {
        result = this->flush(proxy, numSemaphores, backendSemaphores);
    }

    if (!proxy->instantiate(fContext->resourceProvider())) {
        return result;
    }

    GrSurface* surface = proxy->priv().peekSurface();

    if (fContext->getGpu() && surface->asRenderTarget()) {
        fContext->getGpu()->resolveRenderTarget(surface->asRenderTarget(), proxy->origin());
    }
    return result;
}

void GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    fOnFlushCBObjects.push_back(onFlushCBObject);
}

sk_sp<GrRenderTargetOpList> GrDrawingManager::newRTOpList(GrRenderTargetProxy* rtp,
                                                          bool managedOpList) {
    SkASSERT(fContext);

    // This is  a temporary fix for the partial-MDB world. In that world we're not reordering
    // so ops that (in the single opList world) would've just glommed onto the end of the single
    // opList but referred to a far earlier RT need to appear in their own opList.
    if (!fOpLists.empty()) {
        fOpLists.back()->makeClosed(*fContext->caps());
    }

    sk_sp<GrRenderTargetOpList> opList(new GrRenderTargetOpList(rtp,
                                                                fContext->getGpu(),
                                                                fContext->getAuditTrail()));
    SkASSERT(rtp->getLastOpList() == opList.get());

    if (managedOpList) {
        fOpLists.push_back() = opList;
    }

    return opList;
}

sk_sp<GrTextureOpList> GrDrawingManager::newTextureOpList(GrTextureProxy* textureProxy) {
    SkASSERT(fContext);

    // This is  a temporary fix for the partial-MDB world. In that world we're not reordering
    // so ops that (in the single opList world) would've just glommed onto the end of the single
    // opList but referred to a far earlier RT need to appear in their own opList.
    if (!fOpLists.empty()) {
        fOpLists.back()->makeClosed(*fContext->caps());
    }

    sk_sp<GrTextureOpList> opList(new GrTextureOpList(fContext->resourceProvider(),
                                                      textureProxy,
                                                      fContext->getAuditTrail()));

    SkASSERT(textureProxy->getLastOpList() == opList.get());

    fOpLists.push_back() = opList;

    return opList;
}

GrAtlasTextContext* GrDrawingManager::getAtlasTextContext() {
    if (!fAtlasTextContext) {
        fAtlasTextContext.reset(GrAtlasTextContext::Create());
    }

    return fAtlasTextContext.get();
}

/*
 * This method finds a path renderer that can draw the specified path on
 * the provided target.
 * Due to its expense, the software path renderer has split out so it can
 * can be individually allowed/disallowed via the "allowSW" boolean.
 */
GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                                  bool allowSW,
                                                  GrPathRendererChain::DrawType drawType,
                                                  GrPathRenderer::StencilSupport* stencilSupport) {

    if (!fPathRendererChain) {
        fPathRendererChain = new GrPathRendererChain(fContext, fOptionsForPathRendererChain);
    }

    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
    if (!pr && allowSW) {
        if (!fSoftwarePathRenderer) {
            fSoftwarePathRenderer =
                    new GrSoftwarePathRenderer(fContext->resourceProvider(),
                                               fOptionsForPathRendererChain.fAllowPathMaskCaching);
        }
        if (GrPathRenderer::CanDrawPath::kNo != fSoftwarePathRenderer->canDrawPath(args)) {
            pr = fSoftwarePathRenderer;
        }
    }

    return pr;
}

sk_sp<GrRenderTargetContext> GrDrawingManager::makeRenderTargetContext(
                                                            sk_sp<GrSurfaceProxy> sProxy,
                                                            sk_sp<SkColorSpace> colorSpace,
                                                            const SkSurfaceProps* surfaceProps,
                                                            bool managedOpList) {
    if (this->wasAbandoned() || !sProxy->asRenderTargetProxy()) {
        return nullptr;
    }

    // SkSurface catches bad color space usage at creation. This check handles anything that slips
    // by, including internal usage. We allow a null color space here, for read/write pixels and
    // other special code paths. If a color space is provided, though, enforce all other rules.
    if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
        SkDEBUGFAIL("Invalid config and colorspace combination");
        return nullptr;
    }

    sk_sp<GrRenderTargetProxy> rtp(sk_ref_sp(sProxy->asRenderTargetProxy()));

    bool useDIF = false;
    if (surfaceProps) {
        useDIF = surfaceProps->isUseDeviceIndependentFonts();
    }

    if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
        GrFSAAType::kNone != rtp->fsaaType()) {

        return sk_sp<GrRenderTargetContext>(new GrPathRenderingRenderTargetContext(
                                                    fContext, this, std::move(rtp),
                                                    std::move(colorSpace), surfaceProps,
                                                    fContext->getAuditTrail(), fSingleOwner));
    }

    return sk_sp<GrRenderTargetContext>(new GrRenderTargetContext(fContext, this, std::move(rtp),
                                                                  std::move(colorSpace),
                                                                  surfaceProps,
                                                                  fContext->getAuditTrail(),
                                                                  fSingleOwner, managedOpList));
}

sk_sp<GrTextureContext> GrDrawingManager::makeTextureContext(sk_sp<GrSurfaceProxy> sProxy,
                                                             sk_sp<SkColorSpace> colorSpace) {
    if (this->wasAbandoned() || !sProxy->asTextureProxy()) {
        return nullptr;
    }

    // SkSurface catches bad color space usage at creation. This check handles anything that slips
    // by, including internal usage. We allow a null color space here, for read/write pixels and
    // other special code paths. If a color space is provided, though, enforce all other rules.
    if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
        SkDEBUGFAIL("Invalid config and colorspace combination");
        return nullptr;
    }

    // GrTextureRenderTargets should always be using GrRenderTargetContext
    SkASSERT(!sProxy->asRenderTargetProxy());

    sk_sp<GrTextureProxy> textureProxy(sk_ref_sp(sProxy->asTextureProxy()));

    return sk_sp<GrTextureContext>(new GrTextureContext(fContext, this, std::move(textureProxy),
                                                        std::move(colorSpace),
                                                        fContext->getAuditTrail(),
                                                        fSingleOwner));
}
<commit_msg>Roll external/skia 78bdee200..f8bc0018b (1 commits)<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrDrawingManager.h"

#include "GrBackendSemaphore.h"
#include "GrContext.h"
#include "GrGpu.h"
#include "GrOnFlushResourceProvider.h"
#include "GrOpList.h"
#include "GrRenderTargetContext.h"
#include "GrPathRenderingRenderTargetContext.h"
#include "GrRenderTargetProxy.h"
#include "GrResourceAllocator.h"
#include "GrResourceProvider.h"
#include "GrSoftwarePathRenderer.h"
#include "GrSurfaceProxyPriv.h"
#include "GrTextureContext.h"
#include "GrTextureOpList.h"
#include "SkSurface_Gpu.h"
#include "SkTTopoSort.h"

#include "GrTracing.h"
#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"

void GrDrawingManager::cleanup() {
    for (int i = 0; i < fOpLists.count(); ++i) {
        // no opList should receive a new command after this
        fOpLists[i]->makeClosed(*fContext->caps());

        // We shouldn't need to do this, but it turns out some clients still hold onto opLists
        // after a cleanup.
        // MDB TODO: is this still true?
        fOpLists[i]->reset();
    }

    fOpLists.reset();

    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);

    fOnFlushCBObjects.reset();
}

GrDrawingManager::~GrDrawingManager() {
    this->cleanup();
}

void GrDrawingManager::abandon() {
    fAbandoned = true;
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->abandonGpuResources();
    }
    this->cleanup();
}

void GrDrawingManager::freeGpuResources() {
    for (int i = fOnFlushCBObjects.count() - 1; i >= 0; --i) {
        if (!fOnFlushCBObjects[i]->retainOnFreeGpuResources()) {
            // it's safe to just do this because we're iterating in reverse
            fOnFlushCBObjects.removeShuffle(i);
        }
    }

    // a path renderer may be holding onto resources
    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->freeGpuResources();
    }

}

void GrDrawingManager::reset() {
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->reset();
    }
    fFlushState.reset();
}

gr_instanced::OpAllocator* GrDrawingManager::instancingAllocator() {
    if (fInstancingAllocator) {
        return fInstancingAllocator.get();
    }

    fInstancingAllocator = fContext->getGpu()->createInstancedRenderingAllocator();
    return fInstancingAllocator.get();
}

// MDB TODO: make use of the 'proxy' parameter.
GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
                                                      GrResourceCache::FlushType type,
                                                      int numSemaphores,
                                                      GrBackendSemaphore backendSemaphores[]) {
    GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "internalFlush", fContext);

    if (fFlushing || this->wasAbandoned()) {
        return GrSemaphoresSubmitted::kNo;
    }
    fFlushing = true;
    bool flushed = false;

    for (int i = 0; i < fOpLists.count(); ++i) {
        // Semi-usually the GrOpLists are already closed at this point, but sometimes Ganesh
        // needs to flush mid-draw. In that case, the SkGpuDevice's GrOpLists won't be closed
        // but need to be flushed anyway. Closing such GrOpLists here will mean new
        // GrOpLists will be created to replace them if the SkGpuDevice(s) write to them again.
        fOpLists[i]->makeClosed(*fContext->caps());
    }

#ifdef SK_DEBUG
    // This block checks for any unnecessary splits in the opLists. If two sequential opLists
    // share the same backing GrSurfaceProxy it means the opList was artificially split.
    if (fOpLists.count()) {
        GrRenderTargetOpList* prevOpList = fOpLists[0]->asRenderTargetOpList();
        for (int i = 1; i < fOpLists.count(); ++i) {
            GrRenderTargetOpList* curOpList = fOpLists[i]->asRenderTargetOpList();

            if (prevOpList && curOpList) {
                SkASSERT(prevOpList->fTarget.get() != curOpList->fTarget.get());
            }

            prevOpList = curOpList;
        }
    }
#endif

#ifdef ENABLE_MDB_SORT
    SkDEBUGCODE(bool result =)
                        SkTTopoSort<GrOpList, GrOpList::TopoSortTraits>(&fOpLists);
    SkASSERT(result);
#endif

    GrOnFlushResourceProvider onFlushProvider(this);

    if (!fOnFlushCBObjects.empty()) {
        // MDB TODO: pre-MDB '1' is the correct pre-allocated size. Post-MDB it will need
        // to be larger.
        SkAutoSTArray<1, uint32_t> opListIds(fOpLists.count());
        for (int i = 0; i < fOpLists.count(); ++i) {
            opListIds[i] = fOpLists[i]->uniqueID();
        }

        SkSTArray<1, sk_sp<GrRenderTargetContext>> renderTargetContexts;
        for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
            onFlushCBObject->preFlush(&onFlushProvider,
                                      opListIds.get(), opListIds.count(),
                                      &renderTargetContexts);
            if (!renderTargetContexts.count()) {
                continue;       // This is fine. No atlases of this type are required for this flush
            }

            for (int j = 0; j < renderTargetContexts.count(); ++j) {
                GrOpList* opList = renderTargetContexts[j]->getOpList();
                if (!opList) {
                    continue;   // Odd - but not a big deal
                }
                opList->makeClosed(*fContext->caps());
                opList->prepare(&fFlushState);
                if (!opList->execute(&fFlushState)) {
                    continue;         // This is bad
                }
            }
            renderTargetContexts.reset();
        }
    }

#if 0
    // Enable this to print out verbose GrOp information
    for (int i = 0; i < fOpLists.count(); ++i) {
        SkDEBUGCODE(fOpLists[i]->dump();)
    }
#endif

#ifdef MDB_ALLOC_RESOURCES
    GrResourceAllocator alloc(fContext->resourceProvider());
    for (int i = 0; i < fOpLists.count(); ++i) {
        fOpLists[i]->gatherProxyIntervals(&alloc);
    }

    alloc.assign();
#endif

    for (int i = 0; i < fOpLists.count(); ++i) {
        if (!fOpLists[i]->instantiate(fContext->resourceProvider())) {
            SkDebugf("OpList failed to instantiate.\n");
            fOpLists[i] = nullptr;
            continue;
        }

        // Instantiate all deferred proxies (being built on worker threads) so we can upload them
        fOpLists[i]->instantiateDeferredProxies(fContext->resourceProvider());
        fOpLists[i]->prepare(&fFlushState);
    }

    // Upload all data to the GPU
    fFlushState.preIssueDraws();

    for (int i = 0; i < fOpLists.count(); ++i) {
        if (!fOpLists[i]) {
            continue;
        }

        if (fOpLists[i]->execute(&fFlushState)) {
            flushed = true;
        }
        fOpLists[i]->reset();
    }
    fOpLists.reset();

    SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());

    GrSemaphoresSubmitted result = fContext->getGpu()->finishFlush(numSemaphores,
                                                                   backendSemaphores);

    fFlushState.reset();
    // We always have to notify the cache when it requested a flush so it can reset its state.
    if (flushed || type == GrResourceCache::FlushType::kCacheRequested) {
        fContext->getResourceCache()->notifyFlushOccurred(type);
    }
    for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
        onFlushCBObject->postFlush(fFlushState.nextTokenToFlush());
    }
    fFlushing = false;

    return result;
}

GrSemaphoresSubmitted GrDrawingManager::prepareSurfaceForExternalIO(
        GrSurfaceProxy* proxy, int numSemaphores, GrBackendSemaphore backendSemaphores[]) {
    if (this->wasAbandoned()) {
        return GrSemaphoresSubmitted::kNo;
    }
    SkASSERT(proxy);

    GrSemaphoresSubmitted result;
    if (proxy->priv().hasPendingIO() || numSemaphores) {
        result = this->flush(proxy, numSemaphores, backendSemaphores);
    }

    if (!proxy->instantiate(fContext->resourceProvider())) {
        return result;
    }

    GrSurface* surface = proxy->priv().peekSurface();

    if (fContext->getGpu() && surface->asRenderTarget()) {
        fContext->getGpu()->resolveRenderTarget(surface->asRenderTarget(), proxy->origin());
    }
    return result;
}

void GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
    fOnFlushCBObjects.push_back(onFlushCBObject);
}

sk_sp<GrRenderTargetOpList> GrDrawingManager::newRTOpList(GrRenderTargetProxy* rtp,
                                                          bool managedOpList) {
    SkASSERT(fContext);

    // This is  a temporary fix for the partial-MDB world. In that world we're not reordering
    // so ops that (in the single opList world) would've just glommed onto the end of the single
    // opList but referred to a far earlier RT need to appear in their own opList.
    if (!fOpLists.empty()) {
        fOpLists.back()->makeClosed(*fContext->caps());
    }

    sk_sp<GrRenderTargetOpList> opList(new GrRenderTargetOpList(rtp,
                                                                fContext->getGpu(),
                                                                fContext->getAuditTrail()));
    SkASSERT(rtp->getLastOpList() == opList.get());

    if (managedOpList) {
        fOpLists.push_back() = opList;
    }

    return opList;
}

sk_sp<GrTextureOpList> GrDrawingManager::newTextureOpList(GrTextureProxy* textureProxy) {
    SkASSERT(fContext);

    // This is  a temporary fix for the partial-MDB world. In that world we're not reordering
    // so ops that (in the single opList world) would've just glommed onto the end of the single
    // opList but referred to a far earlier RT need to appear in their own opList.
    if (!fOpLists.empty()) {
        fOpLists.back()->makeClosed(*fContext->caps());
    }

    sk_sp<GrTextureOpList> opList(new GrTextureOpList(fContext->resourceProvider(),
                                                      textureProxy,
                                                      fContext->getAuditTrail()));

    SkASSERT(textureProxy->getLastOpList() == opList.get());

    fOpLists.push_back() = opList;

    return opList;
}

GrAtlasTextContext* GrDrawingManager::getAtlasTextContext() {
    if (!fAtlasTextContext) {
        fAtlasTextContext.reset(GrAtlasTextContext::Create());
    }

    return fAtlasTextContext.get();
}

/*
 * This method finds a path renderer that can draw the specified path on
 * the provided target.
 * Due to its expense, the software path renderer has split out so it can
 * can be individually allowed/disallowed via the "allowSW" boolean.
 */
GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                                  bool allowSW,
                                                  GrPathRendererChain::DrawType drawType,
                                                  GrPathRenderer::StencilSupport* stencilSupport) {

    if (!fPathRendererChain) {
        fPathRendererChain = new GrPathRendererChain(fContext, fOptionsForPathRendererChain);
    }

    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
    if (!pr && allowSW) {
        if (!fSoftwarePathRenderer) {
            fSoftwarePathRenderer =
                    new GrSoftwarePathRenderer(fContext->resourceProvider(),
                                               fOptionsForPathRendererChain.fAllowPathMaskCaching);
        }
        if (GrPathRenderer::CanDrawPath::kNo != fSoftwarePathRenderer->canDrawPath(args)) {
            pr = fSoftwarePathRenderer;
        }
    }

    return pr;
}

sk_sp<GrRenderTargetContext> GrDrawingManager::makeRenderTargetContext(
                                                            sk_sp<GrSurfaceProxy> sProxy,
                                                            sk_sp<SkColorSpace> colorSpace,
                                                            const SkSurfaceProps* surfaceProps,
                                                            bool managedOpList) {
    if (this->wasAbandoned() || !sProxy->asRenderTargetProxy()) {
        return nullptr;
    }

    // SkSurface catches bad color space usage at creation. This check handles anything that slips
    // by, including internal usage. We allow a null color space here, for read/write pixels and
    // other special code paths. If a color space is provided, though, enforce all other rules.
    if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
        SkDEBUGFAIL("Invalid config and colorspace combination");
        return nullptr;
    }

    sk_sp<GrRenderTargetProxy> rtp(sk_ref_sp(sProxy->asRenderTargetProxy()));

    bool useDIF = false;
    if (surfaceProps) {
        useDIF = surfaceProps->isUseDeviceIndependentFonts();
    }

    if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
        GrFSAAType::kNone != rtp->fsaaType()) {

        return sk_sp<GrRenderTargetContext>(new GrPathRenderingRenderTargetContext(
                                                    fContext, this, std::move(rtp),
                                                    std::move(colorSpace), surfaceProps,
                                                    fContext->getAuditTrail(), fSingleOwner));
    }

    return sk_sp<GrRenderTargetContext>(new GrRenderTargetContext(fContext, this, std::move(rtp),
                                                                  std::move(colorSpace),
                                                                  surfaceProps,
                                                                  fContext->getAuditTrail(),
                                                                  fSingleOwner, managedOpList));
}

sk_sp<GrTextureContext> GrDrawingManager::makeTextureContext(sk_sp<GrSurfaceProxy> sProxy,
                                                             sk_sp<SkColorSpace> colorSpace) {
    if (this->wasAbandoned() || !sProxy->asTextureProxy()) {
        return nullptr;
    }

    // SkSurface catches bad color space usage at creation. This check handles anything that slips
    // by, including internal usage. We allow a null color space here, for read/write pixels and
    // other special code paths. If a color space is provided, though, enforce all other rules.
    if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
        SkDEBUGFAIL("Invalid config and colorspace combination");
        return nullptr;
    }

    // GrTextureRenderTargets should always be using GrRenderTargetContext
    SkASSERT(!sProxy->asRenderTargetProxy());

    sk_sp<GrTextureProxy> textureProxy(sk_ref_sp(sProxy->asTextureProxy()));

    return sk_sp<GrTextureContext>(new GrTextureContext(fContext, this, std::move(textureProxy),
                                                        std::move(colorSpace),
                                                        fContext->getAuditTrail(),
                                                        fSingleOwner));
}
<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "StratumMinerGrin.h"

#include "StratumSessionGrin.h"
#include "StratumServerGrin.h"

#include "DiffController.h"

StratumMinerGrin::StratumMinerGrin(
  StratumSessionGrin &session,
  const DiffController &diffController,
  const std::string &clientAgent,
  const std::string &workerName,
  int64_t workerId)
  : StratumMinerBase(session, diffController, clientAgent, workerName, workerId) {
}

void StratumMinerGrin::handleRequest(
  const std::string &idStr,
  const std::string &method,
  const JsonNode &jparams,
  const JsonNode &jroot) {
  if (method == "submit") {
    handleRequest_Submit(idStr, jparams);
  }
}

void StratumMinerGrin::handleRequest_Submit(const string &idStr, const JsonNode &jparams) {
  // const type cannot access string indexed object member
  JsonNode &jsonParams = const_cast<JsonNode &>(jparams);

  auto &session = getSession();
  if (session.getState() != StratumSession::AUTHENTICATED) {
    session.responseError(idStr, StratumStatus::UNAUTHORIZED);
    return;
  }

  if (
    jsonParams["edge_bits"].type() != Utilities::JS::type::Int ||
    jsonParams["height"].type() != Utilities::JS::type::Int ||
    jsonParams["job_id"].type() != Utilities::JS::type::Int ||
    jsonParams["nonce"].type() != Utilities::JS::type::Int ||
    jsonParams["pow"].type() != Utilities::JS::type::Array) {
    session.responseError(idStr, StratumStatus::ILLEGAL_PARARMS);
    return;
  }

  uint32_t edgeBits = jsonParams["edge_bits"].uint32();
  uint64_t height = jsonParams["height"].uint32();
  uint32_t prePowHash = jsonParams["job_id"].uint32();
  uint64_t nonce = jsonParams["nonce"].uint64();
  vector<uint64_t> proofs;
  for (auto &p : jsonParams["pow"].array()) {
    if (p.type() != Utilities::JS::type::Int) {
      session.responseError(idStr, StratumStatus::ILLEGAL_PARARMS);
      return;
    } else {
      proofs.push_back(p.uint64());
    }
  }

  auto localJob = session.findLocalJob(prePowHash);
  // can't find local job
  if (localJob == nullptr) {
    session.responseError(idStr, StratumStatus::JOB_NOT_FOUND);
    return;
  }

  auto &server = session.getServer();
  auto &worker = session.getWorker();
  auto sessionId = session.getSessionId();

  shared_ptr<StratumJobEx> exjob = server.GetJobRepository(localJob->chainId_)->getStratumJobEx(localJob->jobId_);
  // can't find stratum job
  if (exjob.get() == nullptr) {
    session.responseError(idStr, StratumStatus::JOB_NOT_FOUND);
    return;
  }
  auto sjob = dynamic_cast<StratumJobGrin *>(exjob->sjob_);

  auto iter = jobDiffs_.find(localJob);
  if (iter == jobDiffs_.end()) {
    LOG(ERROR) << "can't find session's diff, worker: " << worker.fullName_;
    return;
  }
  auto &jobDiff = iter->second;

  ShareGrin share;
  share.set_version(ShareGrin::CURRENT_VERSION);
  share.set_jobid(sjob->jobId_);
  share.set_workerhashid(workerId_);
  share.set_userid(worker.userId(exjob->chainId_));
  share.set_timestamp((uint64_t) time(nullptr));
  share.set_status(StratumStatus::REJECT_NO_REASON);
  share.set_sharediff(jobDiff.currentJobDiff_);
  share.set_blockdiff(sjob->difficulty_);
  share.set_height(height);
  share.set_nonce(nonce);
  share.set_sessionid(sessionId); // TODO: fix it, set as real session id.
  share.set_edgebits(edgeBits);
  share.set_scaling(PowScalingGrin(height, edgeBits, sjob->prePow_.secondaryScaling.value()));
  IpAddress ip;
  ip.fromIpv4Int(session.getClientIp());
  share.set_ip(ip.toString());

  LocalShare localShare(nonce, 0, 0);
  // can't add local share
  if (!localJob->addLocalShare(localShare)) {
    session.responseError(idStr, StratumStatus::DUPLICATE_SHARE);
    // add invalid share to counter
    invalidSharesCounter_.insert((int64_t) time(nullptr), 1);
    return;
  }

  uint256 blockHash;
  server.checkAndUpdateShare(
    localJob->chainId_,
    share,
    exjob,
    proofs,
    jobDiff.jobDiffs_,
    worker.fullName_,
    blockHash);

  if (StratumStatus::isAccepted(share.status())) {
    DLOG(INFO) << "share reached the diff: " << share.scaledShareDiff();
  } else {
    DLOG(INFO) << "share not reached the diff: " << share.scaledShareDiff();
  }

  // we send share to kafka by default, but if there are lots of invalid
  // shares in a short time, we just drop them.
  if (handleShare(idStr, share.status(), share.sharediff())) {
    if (StratumStatus::isSolved(share.status())) {
      server.sendSolvedShare2Kafka(localJob->chainId_, share, exjob, proofs, worker, blockHash);
      // mark jobs as stale
      server.GetJobRepository(exjob->chainId_)->markAllJobsAsStale();
    }
  } else {
    // check if there is invalid share spamming
    int64_t invalidSharesNum = invalidSharesCounter_.sum(time(nullptr), INVALID_SHARE_SLIDING_WINDOWS_SIZE);
    // too much invalid shares, don't send them to kafka
    if (invalidSharesNum >= INVALID_SHARE_SLIDING_WINDOWS_MAX_LIMIT) {
      LOG(WARNING) << "invalid share spamming, worker: " << worker.fullName_
                   << ", " << share.toString();
      return;
    }
  }

  DLOG(INFO) << share.toString();

  std::string message;
  uint32_t size = 0;
  if (!share.SerializeToArrayWithVersion(message, size)) {
    LOG(ERROR) << "share SerializeToBuffer failed!"<< share.toString();
    return;
  }
  server.sendShare2Kafka(localJob->chainId_, message.data(), size);
}<commit_msg>Grin fix local share duplication check<commit_after>/*
 The MIT License (MIT)

 Copyright (c) [2016] [BTC.COM]

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

#include "StratumMinerGrin.h"

#include "StratumSessionGrin.h"
#include "StratumServerGrin.h"

#include "DiffController.h"

#include <boost/functional/hash.hpp>

StratumMinerGrin::StratumMinerGrin(
  StratumSessionGrin &session,
  const DiffController &diffController,
  const std::string &clientAgent,
  const std::string &workerName,
  int64_t workerId)
  : StratumMinerBase(session, diffController, clientAgent, workerName, workerId) {
}

void StratumMinerGrin::handleRequest(
  const std::string &idStr,
  const std::string &method,
  const JsonNode &jparams,
  const JsonNode &jroot) {
  if (method == "submit") {
    handleRequest_Submit(idStr, jparams);
  }
}

void StratumMinerGrin::handleRequest_Submit(const string &idStr, const JsonNode &jparams) {
  // const type cannot access string indexed object member
  JsonNode &jsonParams = const_cast<JsonNode &>(jparams);

  auto &session = getSession();
  if (session.getState() != StratumSession::AUTHENTICATED) {
    session.responseError(idStr, StratumStatus::UNAUTHORIZED);
    return;
  }

  if (
    jsonParams["edge_bits"].type() != Utilities::JS::type::Int ||
    jsonParams["height"].type() != Utilities::JS::type::Int ||
    jsonParams["job_id"].type() != Utilities::JS::type::Int ||
    jsonParams["nonce"].type() != Utilities::JS::type::Int ||
    jsonParams["pow"].type() != Utilities::JS::type::Array) {
    session.responseError(idStr, StratumStatus::ILLEGAL_PARARMS);
    return;
  }

  uint32_t edgeBits = jsonParams["edge_bits"].uint32();
  uint64_t height = jsonParams["height"].uint32();
  uint32_t prePowHash = jsonParams["job_id"].uint32();
  uint64_t nonce = jsonParams["nonce"].uint64();
  vector<uint64_t> proofs;
  for (auto &p : jsonParams["pow"].array()) {
    if (p.type() != Utilities::JS::type::Int) {
      session.responseError(idStr, StratumStatus::ILLEGAL_PARARMS);
      return;
    } else {
      proofs.push_back(p.uint64());
    }
  }

  auto localJob = session.findLocalJob(prePowHash);
  // can't find local job
  if (localJob == nullptr) {
    session.responseError(idStr, StratumStatus::JOB_NOT_FOUND);
    return;
  }

  auto &server = session.getServer();
  auto &worker = session.getWorker();
  auto sessionId = session.getSessionId();

  shared_ptr<StratumJobEx> exjob = server.GetJobRepository(localJob->chainId_)->getStratumJobEx(localJob->jobId_);
  // can't find stratum job
  if (exjob.get() == nullptr) {
    session.responseError(idStr, StratumStatus::JOB_NOT_FOUND);
    return;
  }
  auto sjob = dynamic_cast<StratumJobGrin *>(exjob->sjob_);

  auto iter = jobDiffs_.find(localJob);
  if (iter == jobDiffs_.end()) {
    LOG(ERROR) << "can't find session's diff, worker: " << worker.fullName_;
    return;
  }
  auto &jobDiff = iter->second;

  ShareGrin share;
  share.set_version(ShareGrin::CURRENT_VERSION);
  share.set_jobid(sjob->jobId_);
  share.set_workerhashid(workerId_);
  share.set_userid(worker.userId(exjob->chainId_));
  share.set_timestamp((uint64_t) time(nullptr));
  share.set_status(StratumStatus::REJECT_NO_REASON);
  share.set_sharediff(jobDiff.currentJobDiff_);
  share.set_blockdiff(sjob->difficulty_);
  share.set_height(height);
  share.set_nonce(nonce);
  share.set_sessionid(sessionId); // TODO: fix it, set as real session id.
  share.set_edgebits(edgeBits);
  share.set_scaling(PowScalingGrin(height, edgeBits, sjob->prePow_.secondaryScaling.value()));
  IpAddress ip;
  ip.fromIpv4Int(session.getClientIp());
  share.set_ip(ip.toString());

  LocalShare localShare(nonce, boost::hash_value(proofs), edgeBits);
  // can't add local share
  if (!localJob->addLocalShare(localShare)) {
    session.responseError(idStr, StratumStatus::DUPLICATE_SHARE);
    // add invalid share to counter
    invalidSharesCounter_.insert((int64_t) time(nullptr), 1);
    return;
  }

  uint256 blockHash;
  server.checkAndUpdateShare(
    localJob->chainId_,
    share,
    exjob,
    proofs,
    jobDiff.jobDiffs_,
    worker.fullName_,
    blockHash);

  if (StratumStatus::isAccepted(share.status())) {
    DLOG(INFO) << "share reached the diff: " << share.scaledShareDiff();
  } else {
    DLOG(INFO) << "share not reached the diff: " << share.scaledShareDiff();
  }

  // we send share to kafka by default, but if there are lots of invalid
  // shares in a short time, we just drop them.
  if (handleShare(idStr, share.status(), share.sharediff())) {
    if (StratumStatus::isSolved(share.status())) {
      server.sendSolvedShare2Kafka(localJob->chainId_, share, exjob, proofs, worker, blockHash);
      // mark jobs as stale
      server.GetJobRepository(exjob->chainId_)->markAllJobsAsStale();
    }
  } else {
    // check if there is invalid share spamming
    int64_t invalidSharesNum = invalidSharesCounter_.sum(time(nullptr), INVALID_SHARE_SLIDING_WINDOWS_SIZE);
    // too much invalid shares, don't send them to kafka
    if (invalidSharesNum >= INVALID_SHARE_SLIDING_WINDOWS_MAX_LIMIT) {
      LOG(WARNING) << "invalid share spamming, worker: " << worker.fullName_
                   << ", " << share.toString();
      return;
    }
  }

  DLOG(INFO) << share.toString();

  std::string message;
  uint32_t size = 0;
  if (!share.SerializeToArrayWithVersion(message, size)) {
    LOG(ERROR) << "share SerializeToBuffer failed!"<< share.toString();
    return;
  }
  server.sendShare2Kafka(localJob->chainId_, message.data(), size);
}<|endoftext|>


<commit_before>// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
// RUN: %run %t 2>&1
//

#include "sanitizer/asan_interface.h"
#include <assert.h>

__attribute__((noinline)) void foo(int index, int len) {
  volatile char str[len] __attribute__((aligned(32)));
  assert(!(reinterpret_cast<long>(str) & 31L));
  char *q = (char *)__asan_region_is_poisoned((char *)str, 64);
  assert(q && ((q - str) == index));
}

int main(int argc, char **argv) {
  for (int i = 1; i < 33; ++i)
    foo(i, i);

  for (int i = 1; i < 33; ++i)
    foo(i, i);

  return 0;
}
<commit_msg>Fix alloca_instruments_all_paddings.cc test to work under higher -O levels (compiler-rt part)<commit_after>// RUN: %clangxx_asan -O0 -mllvm -asan-instrument-allocas %s -o %t
// RUN: %clangxx_asan -O3 -mllvm -asan-instrument-allocas %s -o %t
// RUN: %run %t 2>&1
//

#include "sanitizer/asan_interface.h"
#include <assert.h>

__attribute__((noinline)) void foo(int index, int len) {
  volatile char str[len] __attribute__((aligned(32)));
  assert(!(reinterpret_cast<long>(str) & 31L));
  char *q = (char *)__asan_region_is_poisoned((char *)str, 64);
  assert(q && ((q - str) == index));
}

int main(int argc, char **argv) {
  for (int i = 1; i < 33; ++i)
    foo(i, i);

  for (int i = 1; i < 33; ++i)
    foo(i, i);

  return 0;
}
<|endoftext|>


<commit_before>#ifndef MODBUS_SERVER_HPP
#define MODBUS_SERVER_HPP

#include "ModbusServerSession.hpp"

#include <set>
#include <stdexcept>

namespace modbus {
namespace tcp {

class Server {
public:
                                    Server(boost::asio::io_service& io, ServerDevice& device);

    void                            start(const boost::asio::ip::tcp::endpoint& ep, std::function<void(void)> done_cb);
    void                            stop();

private:
    using PModbusSession = std::shared_ptr<ServerSession>;

    ServerDevice                   &m_device;
    boost::asio::ip::tcp::acceptor  m_acceptor;
    std::set<PModbusSession>        m_sessions;
    std::function<void(void)>       m_done_cb;

    void                            on_start(const boost::asio::ip::tcp::endpoint& ep, std::function<void(void)> done_cb);
    void                            init_accepting();
    void                            on_client_connected(PModbusSession session, const boost::system::error_code& ec);
    void                            on_session_done(PModbusSession session);

    void                            trigger_done_cb();
    void                            init_shutdown_sessions();
};

Server::Server(boost::asio::io_service& io, ServerDevice& device) :
    m_device(device),
    m_acceptor(io),
    m_sessions()
{}

void Server::start(const boost::asio::ip::tcp::endpoint& ep, std::function<void(void)> cb) {
    m_acceptor.get_io_service().post([this, ep, cb]() {
        m_acceptor.open(ep.protocol());
        m_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
        m_acceptor.bind(ep);
        m_acceptor.listen();

        m_done_cb = cb;
        init_accepting();
    });
}

void Server::init_accepting() {
    PModbusSession session = std::make_shared<ServerSession>(m_acceptor.get_io_service(), m_device);

    m_acceptor.async_accept(
        session->socket(),
        [this, session](const boost::system::error_code& ec) {
            on_client_connected(session, ec);
        });
}

void Server::on_client_connected(PModbusSession session, const boost::system::error_code& ec) {
    if (ec == boost::asio::error::operation_aborted) {
        if (m_sessions.empty())
            trigger_done_cb();
        else
            init_shutdown_sessions();
    } else {
        m_sessions.insert(session);
        session->start([this, session]() {
            m_acceptor.get_io_service().post([this, session]() {
                on_session_done(session);
            });
        });
        init_accepting();
    }
}

void Server::on_session_done(PModbusSession session) {
    m_sessions.erase(session);
    std::cout << "session done " << session.get() << std::endl;

    if ((!m_acceptor.is_open()) && m_sessions.empty())
        trigger_done_cb();
}

void Server::stop() {
    m_acceptor.get_io_service().post([this]() {
        m_acceptor.close();
    });
}

void Server::trigger_done_cb() {
    m_acceptor.get_io_service().post([this]() {
        m_done_cb();
        m_done_cb = nullptr;
    });
}

void Server::init_shutdown_sessions() {
    for (auto &s: m_sessions) {
        s->stop();
    }
}

} // namespace tcp
} // namespace modbus

#endif
<commit_msg>Remove member function prototype<commit_after>#ifndef MODBUS_SERVER_HPP
#define MODBUS_SERVER_HPP

#include "ModbusServerSession.hpp"

#include <set>
#include <stdexcept>

namespace modbus {
namespace tcp {

class Server {
public:
                                    Server(boost::asio::io_service& io, ServerDevice& device);

    void                            start(const boost::asio::ip::tcp::endpoint& ep, std::function<void(void)> done_cb);
    void                            stop();

private:
    using PModbusSession = std::shared_ptr<ServerSession>;

    ServerDevice                   &m_device;
    boost::asio::ip::tcp::acceptor  m_acceptor;
    std::set<PModbusSession>        m_sessions;
    std::function<void(void)>       m_done_cb;

    void                            init_accepting();
    void                            on_client_connected(PModbusSession session, const boost::system::error_code& ec);
    void                            on_session_done(PModbusSession session);

    void                            trigger_done_cb();
    void                            init_shutdown_sessions();
};

Server::Server(boost::asio::io_service& io, ServerDevice& device) :
    m_device(device),
    m_acceptor(io),
    m_sessions()
{}

void Server::start(const boost::asio::ip::tcp::endpoint& ep, std::function<void(void)> cb) {
    m_acceptor.get_io_service().post([this, ep, cb]() {
        m_acceptor.open(ep.protocol());
        m_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
        m_acceptor.bind(ep);
        m_acceptor.listen();

        m_done_cb = cb;
        init_accepting();
    });
}

void Server::init_accepting() {
    PModbusSession session = std::make_shared<ServerSession>(m_acceptor.get_io_service(), m_device);

    m_acceptor.async_accept(
        session->socket(),
        [this, session](const boost::system::error_code& ec) {
            on_client_connected(session, ec);
        });
}

void Server::on_client_connected(PModbusSession session, const boost::system::error_code& ec) {
    if (ec == boost::asio::error::operation_aborted) {
        if (m_sessions.empty())
            trigger_done_cb();
        else
            init_shutdown_sessions();
    } else {
        m_sessions.insert(session);
        session->start([this, session]() {
            m_acceptor.get_io_service().post([this, session]() {
                on_session_done(session);
            });
        });
        init_accepting();
    }
}

void Server::on_session_done(PModbusSession session) {
    m_sessions.erase(session);
    std::cout << "session done " << session.get() << std::endl;

    if ((!m_acceptor.is_open()) && m_sessions.empty())
        trigger_done_cb();
}

void Server::stop() {
    m_acceptor.get_io_service().post([this]() {
        m_acceptor.close();
    });
}

void Server::trigger_done_cb() {
    m_acceptor.get_io_service().post([this]() {
        m_done_cb();
        m_done_cb = nullptr;
    });
}

void Server::init_shutdown_sessions() {
    for (auto &s: m_sessions) {
        s->stop();
    }
}

} // namespace tcp
} // namespace modbus

#endif
<|endoftext|>


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

#include "tools/json_schema_compiler/test/simple_api.h"

#include "testing/gtest/include/gtest/gtest.h"

using namespace test::api::simple_api;

namespace {

static scoped_ptr<DictionaryValue> CreateTestTypeDictionary() {
  scoped_ptr<DictionaryValue> value(new DictionaryValue());
  value->SetWithoutPathExpansion("number", Value::CreateDoubleValue(1.1));
  value->SetWithoutPathExpansion("integer", Value::CreateIntegerValue(4));
  value->SetWithoutPathExpansion("string", Value::CreateStringValue("bling"));
  value->SetWithoutPathExpansion("boolean", Value::CreateBooleanValue(true));
  return value.Pass();
}

}  // namespace

TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerResultCreate) {
  scoped_ptr<Value> result(IncrementInteger::Result::Create(5));
  int temp = 0;
  EXPECT_TRUE(result->GetAsInteger(&temp));
  EXPECT_EQ(5, temp);
}

TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerParamsCreate) {
  scoped_ptr<ListValue> params_value(new ListValue());
  params_value->Append(Value::CreateIntegerValue(6));
  scoped_ptr<IncrementInteger::Params> params(
      IncrementInteger::Params::Create(*params_value));
  EXPECT_TRUE(params.get());
  EXPECT_EQ(6, params->num);
}

TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsCreate) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_FALSE(params->str.get());
  }
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateStringValue("asdf"));
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_TRUE(params->str.get());
    EXPECT_EQ("asdf", *params->str);
  }
}

TEST(JsonSchemaCompilerSimpleTest, OptionalParamsTakingNull) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateNullValue());
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_FALSE(params->str.get());
  }
}

TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsWrongType) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateIntegerValue(5));
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_FALSE(params.get());
  }
}

TEST(JsonSchemaCompilerSimpleTest, NoParamsResultCreate) {
  EXPECT_TRUE(Value::Equals(OptionalString::Result::Create(),
                            Value::CreateNullValue()));
}

TEST(JsonSchemaCompilerSimpleTest, TestTypePopulate) {
  {
    scoped_ptr<TestType> test_type(new TestType());
    scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
    EXPECT_TRUE(TestType::Populate(*value, test_type.get()));
    EXPECT_EQ("bling", test_type->string);
    EXPECT_EQ(1.1, test_type->number);
    EXPECT_EQ(4, test_type->integer);
    EXPECT_EQ(true, test_type->boolean);
    EXPECT_TRUE(value->Equals(test_type->ToValue().get()));
  }
  {
    scoped_ptr<TestType> test_type(new TestType());
    scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
    value->RemoveWithoutPathExpansion("number", NULL);
    EXPECT_FALSE(TestType::Populate(*value, test_type.get()));
  }
}

TEST(JsonSchemaCompilerSimpleTest, GetTestType) {
  scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
  scoped_ptr<TestType> test_type(new TestType());
  EXPECT_TRUE(TestType::Populate(*value, test_type.get()));
  scoped_ptr<Value> result(GetTestType::Result::Create(*test_type));
  EXPECT_TRUE(value->Equals(result.get()));
}

<commit_msg>Fixed leaks in JsonSchemaCompilerSimpleTest_NoParamsResultCreate.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tools/json_schema_compiler/test/simple_api.h"

#include "testing/gtest/include/gtest/gtest.h"

using namespace test::api::simple_api;

namespace {

static scoped_ptr<DictionaryValue> CreateTestTypeDictionary() {
  scoped_ptr<DictionaryValue> value(new DictionaryValue());
  value->SetWithoutPathExpansion("number", Value::CreateDoubleValue(1.1));
  value->SetWithoutPathExpansion("integer", Value::CreateIntegerValue(4));
  value->SetWithoutPathExpansion("string", Value::CreateStringValue("bling"));
  value->SetWithoutPathExpansion("boolean", Value::CreateBooleanValue(true));
  return value.Pass();
}

}  // namespace

TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerResultCreate) {
  scoped_ptr<Value> result(IncrementInteger::Result::Create(5));
  int temp = 0;
  EXPECT_TRUE(result->GetAsInteger(&temp));
  EXPECT_EQ(5, temp);
}

TEST(JsonSchemaCompilerSimpleTest, IncrementIntegerParamsCreate) {
  scoped_ptr<ListValue> params_value(new ListValue());
  params_value->Append(Value::CreateIntegerValue(6));
  scoped_ptr<IncrementInteger::Params> params(
      IncrementInteger::Params::Create(*params_value));
  EXPECT_TRUE(params.get());
  EXPECT_EQ(6, params->num);
}

TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsCreate) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_FALSE(params->str.get());
  }
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateStringValue("asdf"));
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_TRUE(params->str.get());
    EXPECT_EQ("asdf", *params->str);
  }
}

TEST(JsonSchemaCompilerSimpleTest, OptionalParamsTakingNull) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateNullValue());
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_TRUE(params.get());
    EXPECT_FALSE(params->str.get());
  }
}

TEST(JsonSchemaCompilerSimpleTest, OptionalStringParamsWrongType) {
  {
    scoped_ptr<ListValue> params_value(new ListValue());
    params_value->Append(Value::CreateIntegerValue(5));
    scoped_ptr<OptionalString::Params> params(
        OptionalString::Params::Create(*params_value));
    EXPECT_FALSE(params.get());
  }
}

TEST(JsonSchemaCompilerSimpleTest, NoParamsResultCreate) {
  scoped_ptr<Value> result(OptionalString::Result::Create());
  scoped_ptr<Value> expected(Value::CreateNullValue());
  EXPECT_TRUE(Value::Equals(result.get(), expected.get()));
}

TEST(JsonSchemaCompilerSimpleTest, TestTypePopulate) {
  {
    scoped_ptr<TestType> test_type(new TestType());
    scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
    EXPECT_TRUE(TestType::Populate(*value, test_type.get()));
    EXPECT_EQ("bling", test_type->string);
    EXPECT_EQ(1.1, test_type->number);
    EXPECT_EQ(4, test_type->integer);
    EXPECT_EQ(true, test_type->boolean);
    EXPECT_TRUE(value->Equals(test_type->ToValue().get()));
  }
  {
    scoped_ptr<TestType> test_type(new TestType());
    scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
    value->RemoveWithoutPathExpansion("number", NULL);
    EXPECT_FALSE(TestType::Populate(*value, test_type.get()));
  }
}

TEST(JsonSchemaCompilerSimpleTest, GetTestType) {
  scoped_ptr<DictionaryValue> value = CreateTestTypeDictionary();
  scoped_ptr<TestType> test_type(new TestType());
  EXPECT_TRUE(TestType::Populate(*value, test_type.get()));
  scoped_ptr<Value> result(GetTestType::Result::Create(*test_type));
  EXPECT_TRUE(value->Equals(result.get()));
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: _serviceregistration_tools.cxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include <cppuhelper/implementationentry.hxx>
#include "LabeledDataSequence.hxx"
#include "CachedDataSequence.hxx"
#include "DataSource.hxx"
#include "ConfigColorScheme.hxx"
#include "Scaling.hxx"
#include "ErrorBar.hxx"
#include "RegressionCurveModel.hxx"
#include "RegressionEquation.hxx"

static struct ::cppu::ImplementationEntry g_entries_chart2_tools[] =
{
    {
          ::chart::LabeledDataSequence::create
        , ::chart::LabeledDataSequence::getImplementationName_Static
        , ::chart::LabeledDataSequence::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::CachedDataSequence::create
        , ::chart::CachedDataSequence::getImplementationName_Static
        , ::chart::CachedDataSequence::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::DataSource::create
        , ::chart::DataSource::getImplementationName_Static
        , ::chart::DataSource::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ConfigColorScheme::create
        , ::chart::ConfigColorScheme::getImplementationName_Static
        , ::chart::ConfigColorScheme::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }

    ,{
          ::chart::LogarithmicScaling::create
        , ::chart::LogarithmicScaling::getImplementationName_Static
        , ::chart::LogarithmicScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ExponentialScaling::create
        , ::chart::ExponentialScaling::getImplementationName_Static
        , ::chart::ExponentialScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LinearScaling::create
        , ::chart::LinearScaling::getImplementationName_Static
        , ::chart::LinearScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::PowerScaling::create
        , ::chart::PowerScaling::getImplementationName_Static
        , ::chart::PowerScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ErrorBar::create
        , ::chart::ErrorBar::getImplementationName_Static
        , ::chart::ErrorBar::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::MeanValueRegressionCurve::create
        , ::chart::MeanValueRegressionCurve::getImplementationName_Static
        , ::chart::MeanValueRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LinearRegressionCurve::create
        , ::chart::LinearRegressionCurve::getImplementationName_Static
        , ::chart::LinearRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LogarithmicRegressionCurve::create
        , ::chart::LogarithmicRegressionCurve::getImplementationName_Static
        , ::chart::LogarithmicRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ExponentialRegressionCurve::create
        , ::chart::ExponentialRegressionCurve::getImplementationName_Static
        , ::chart::ExponentialRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::PotentialRegressionCurve::create
        , ::chart::PotentialRegressionCurve::getImplementationName_Static
        , ::chart::PotentialRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::RegressionEquation::create
        , ::chart::RegressionEquation::getImplementationName_Static
        , ::chart::RegressionEquation::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{ 0, 0, 0, 0, 0, 0 }
};

// component exports
extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
                pServiceManager, pRegistryKey, g_entries_chart2_tools );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey , g_entries_chart2_tools );
}
}
//=========================================================================
<commit_msg>INTEGRATION: CWS rptchart02 (1.5.4); FILE MERGED 2008/04/16 06:36:11 oj 1.5.4.2: RESYNC: (1.5-1.6); FILE MERGED 2008/03/12 09:01:26 oj 1.5.4.1: register InternalDataProvider as service to use it as delegatee<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: _serviceregistration_tools.cxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_chart2.hxx"
#include <cppuhelper/implementationentry.hxx>
#include "LabeledDataSequence.hxx"
#include "CachedDataSequence.hxx"
#include "DataSource.hxx"
#include "ConfigColorScheme.hxx"
#include "Scaling.hxx"
#include "ErrorBar.hxx"
#include "RegressionCurveModel.hxx"
#include "RegressionEquation.hxx"
#include "InternalDataProvider.hxx"

static struct ::cppu::ImplementationEntry g_entries_chart2_tools[] =
{
    {
          ::chart::LabeledDataSequence::create
        , ::chart::LabeledDataSequence::getImplementationName_Static
        , ::chart::LabeledDataSequence::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::CachedDataSequence::create
        , ::chart::CachedDataSequence::getImplementationName_Static
        , ::chart::CachedDataSequence::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::DataSource::create
        , ::chart::DataSource::getImplementationName_Static
        , ::chart::DataSource::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ConfigColorScheme::create
        , ::chart::ConfigColorScheme::getImplementationName_Static
        , ::chart::ConfigColorScheme::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }

    ,{
          ::chart::LogarithmicScaling::create
        , ::chart::LogarithmicScaling::getImplementationName_Static
        , ::chart::LogarithmicScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ExponentialScaling::create
        , ::chart::ExponentialScaling::getImplementationName_Static
        , ::chart::ExponentialScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LinearScaling::create
        , ::chart::LinearScaling::getImplementationName_Static
        , ::chart::LinearScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::PowerScaling::create
        , ::chart::PowerScaling::getImplementationName_Static
        , ::chart::PowerScaling::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ErrorBar::create
        , ::chart::ErrorBar::getImplementationName_Static
        , ::chart::ErrorBar::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::MeanValueRegressionCurve::create
        , ::chart::MeanValueRegressionCurve::getImplementationName_Static
        , ::chart::MeanValueRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LinearRegressionCurve::create
        , ::chart::LinearRegressionCurve::getImplementationName_Static
        , ::chart::LinearRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::LogarithmicRegressionCurve::create
        , ::chart::LogarithmicRegressionCurve::getImplementationName_Static
        , ::chart::LogarithmicRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::ExponentialRegressionCurve::create
        , ::chart::ExponentialRegressionCurve::getImplementationName_Static
        , ::chart::ExponentialRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::PotentialRegressionCurve::create
        , ::chart::PotentialRegressionCurve::getImplementationName_Static
        , ::chart::PotentialRegressionCurve::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::RegressionEquation::create
        , ::chart::RegressionEquation::getImplementationName_Static
        , ::chart::RegressionEquation::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{
          ::chart::InternalDataProvider::create
        , ::chart::InternalDataProvider::getImplementationName_Static
        , ::chart::InternalDataProvider::getSupportedServiceNames_Static
        , ::cppu::createSingleComponentFactory
        , 0
        , 0
    }
   ,{ 0, 0, 0, 0, 0, 0 }
};

// component exports
extern "C"
{
//==================================================================================================
void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}
//==================================================================================================
sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
                pServiceManager, pRegistryKey, g_entries_chart2_tools );
}
//==================================================================================================
void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey , g_entries_chart2_tools );
}
}
//=========================================================================
<|endoftext|>


<commit_before>// Copyright (c) 2013 Joshua Beitler, Mirus contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <term/terminal.hpp>

// terminal sizes
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 24;

// term info
static size_t terminal_row;
static size_t terminal_column;
static uint8_t terminal_color;
static uint16_t* terminal_buffer;

uint8_t mirus::make_color(enum vga_color fg, enum vga_color bg) {
    return fg | bg << 4;
}

uint16_t mirus::make_vgaentry(char c, uint8_t color) {
    uint16_t c16 = c;
    uint16_t color16 = color;

    return c16 | color16 << 8;
}

void mirus::terminal_initialize() {
    using namespace mirus;

    terminal_row = 0;
    terminal_column = 0;
    terminal_color = make_color(COLOR_WHITE, COLOR_BLACK);
    terminal_buffer = (uint16_t*) 0xB8000;

    for ( size_t y = 0; y < VGA_HEIGHT; y++ )
    {
        for ( size_t x = 0; x < VGA_WIDTH; x++ )
        {
            const size_t index = y * VGA_WIDTH + x;
            terminal_buffer[index] = make_vgaentry(' ', terminal_color);
        }
    }
}

// set color
void mirus::terminal_setcolor(uint8_t color) {
    terminal_color = color;
}

// put an entry at location
void mirus::terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
    using namespace mirus;

    const size_t index = y * VGA_WIDTH + x;
    terminal_buffer[index] = make_vgaentry(c, color);
}

// put a char at a location
void mirus::terminal_putchar(char c) {
    using namespace mirus;

    if (c == '\r') {
        ++terminal_row;
        terminal_column = 0;
    } else if (c == '\b') {
        terminal_column--;
    } else {
        terminal_putentryat(c, terminal_color, terminal_column, terminal_row);

        if ( ++terminal_column == VGA_WIDTH )
        {
            terminal_column = 0;
            terminal_row++;

            // if (++terminal_row == 25)
            // {
            //     terminal_scroll();
            // }

    }

    // TODO: bug here
    // if (++terminal_row == VGA_HEIGHT) {
    //     terminal_scroll();
    // }

    terminal_move_cursor();
}

void mirus::terminal_putchar(char c, uint8_t color) {
    uint8_t oldcolor = terminal_color;
    terminal_setcolor(color);
    mirus::terminal_putchar(c);
    terminal_setcolor(oldcolor);
}

// write a string
void mirus::terminal_writestring(const char* data) {
    using namespace mirus;

    size_t datalen = strlen(data);

    for (size_t i = 0; i < datalen; i++) {
        if (data[i] == '\r') {
            ++terminal_column;
            terminal_row = 0;
        } else if (data[i] == '\b') {
            terminal_column--;
        } else
            terminal_putchar(data[i]);
    }
}

void mirus::terminal_writestring(const char* data, uint8_t color) {
    using namespace mirus;

    size_t datalen = strlen(data);
    for (size_t i = 0; i < datalen; i++) {
        if (data[i] == '\r') {
            ++terminal_column;
            terminal_row = 0;
        }  else if (data[i] == '\b') {
            terminal_column--;
        } else
            terminal_putchar(data[i], color);
    }
}

void mirus::terminal_clear() {
    using namespace mirus;

    uint8_t attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
    uint16_t blank = 0x20 /* space */ | (attributeByte << 8);

    for (int i = 0; i < 80 * 25; i++)
        terminal_buffer[i] = 0;

    // Move the hardware cursor back to the start.
    terminal_row = 0;
    terminal_column = 0;

    terminal_move_cursor();
}

// TODO: does not scroll correctly
void mirus::terminal_scroll() {
    using namespace mirus;

    uint8_t blank = make_color(COLOR_BLACK, COLOR_BLACK);
    unsigned temp;
    unsigned short* vidmem = nullptr;

    vidmem = (unsigned short*)0xB8000;

    temp = terminal_column - 25 + 1;

    mirus::memcpy(vidmem, vidmem + temp * 80, (25 - temp) * 80 * 2);
    mirus::memsetw(vidmem + (25 - temp) * 80, blank, 80);

    terminal_column = 25 - 1;
}

void mirus::terminal_move_cursor() {
    using namespace mirus;

    unsigned temp;

    /* The equation for finding the index in a linear
    *  chunk of memory can be represented by:
    *  Index = [(y * width) + x] */
    temp = terminal_row * 80 + terminal_column;

    /* This sends a command to indicies 14 and 15 in the
    *  CRT Control Register of the VGA controller. These
    *  are the high and low bytes of the index that show
    *  where the hardware cursor is to be 'blinking'. To
    *  learn more, you should look up some VGA specific
    *  programming documents. A great start to graphics:
    *  http://www.brackeen.com/home/vga */
    mirus::outb(0x3D4, 14);
    mirus::outb(0x3D5, temp >> 8);
    mirus::outb(0x3D4, 15);
    mirus::outb(0x3D5, temp);
}<commit_msg>stuff<commit_after>// Copyright (c) 2013 Joshua Beitler, Mirus contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include <term/terminal.hpp>

// terminal sizes
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 24;

// term info
static size_t terminal_row;
static size_t terminal_column;
static uint8_t terminal_color;
static uint16_t* terminal_buffer;

uint8_t mirus::make_color(enum vga_color fg, enum vga_color bg) {
    return fg | bg << 4;
}

uint16_t mirus::make_vgaentry(char c, uint8_t color) {
    uint16_t c16 = c;
    uint16_t color16 = color;

    return c16 | color16 << 8;
}

void mirus::terminal_initialize() {
    using namespace mirus;

    terminal_row = 0;
    terminal_column = 0;
    terminal_color = make_color(COLOR_WHITE, COLOR_BLACK);
    terminal_buffer = (uint16_t*) 0xB8000;

    for ( size_t y = 0; y < VGA_HEIGHT; y++ )
    {
        for ( size_t x = 0; x < VGA_WIDTH; x++ )
        {
            const size_t index = y * VGA_WIDTH + x;
            terminal_buffer[index] = make_vgaentry(' ', terminal_color);
        }
    }
}

// set color
void mirus::terminal_setcolor(uint8_t color) {
    terminal_color = color;
}

// put an entry at location
void mirus::terminal_putentryat(char c, uint8_t color, size_t x, size_t y) {
    using namespace mirus;

    const size_t index = y * VGA_WIDTH + x;
    terminal_buffer[index] = make_vgaentry(c, color);
}

// put a char at a location
void mirus::terminal_putchar(char c) {
    using namespace mirus;

    if (c == '\r') {
        ++terminal_row;
        terminal_column = 0;
    } else if (c == '\b') {
        terminal_column--;
    } else {
        terminal_putentryat(c, terminal_color, terminal_column, terminal_row);

        if ( ++terminal_column == VGA_WIDTH ) {
            terminal_column = 0;
            terminal_row++;

            // if (++terminal_row == 25)
            // {
            //     terminal_scroll();
            // }

        }
    }

    // TODO: bug here
    // if (++terminal_row == VGA_HEIGHT) {
    //     terminal_scroll();
    // }

    terminal_move_cursor();
}

void mirus::terminal_putchar(char c, uint8_t color) {
    uint8_t oldcolor = terminal_color;
    terminal_setcolor(color);
    mirus::terminal_putchar(c);
    terminal_setcolor(oldcolor);
}

// write a string
void mirus::terminal_writestring(const char* data) {
    using namespace mirus;

    size_t datalen = strlen(data);

    for (size_t i = 0; i < datalen; i++) {
        if (data[i] == '\r') {
            ++terminal_column;
            terminal_row = 0;
        } else if (data[i] == '\b') {
            terminal_column--;
        } else
            terminal_putchar(data[i]);
    }
}

void mirus::terminal_writestring(const char* data, uint8_t color) {
    using namespace mirus;

    size_t datalen = strlen(data);
    for (size_t i = 0; i < datalen; i++) {
        if (data[i] == '\r') {
            ++terminal_column;
            terminal_row = 0;
        }  else if (data[i] == '\b') {
            terminal_column--;
        } else
            terminal_putchar(data[i], color);
    }
}

void mirus::terminal_clear() {
    using namespace mirus;

    uint8_t attributeByte = (0 /*black*/ << 4) | (15 /*white*/ & 0x0F);
    uint16_t blank = 0x20 /* space */ | (attributeByte << 8);

    for (int i = 0; i < 80 * 25; i++)
        terminal_buffer[i] = 0;

    // Move the hardware cursor back to the start.
    terminal_row = 0;
    terminal_column = 0;

    terminal_move_cursor();
}

// TODO: does not scroll correctly
void mirus::terminal_scroll() {
    using namespace mirus;

    uint8_t blank = make_color(COLOR_BLACK, COLOR_BLACK);
    unsigned temp;
    unsigned short* vidmem = nullptr;

    vidmem = (unsigned short*)0xB8000;

    temp = terminal_column - 25 + 1;

    mirus::memcpy(vidmem, vidmem + temp * 80, (25 - temp) * 80 * 2);
    mirus::memsetw(vidmem + (25 - temp) * 80, blank, 80);

    terminal_column = 25 - 1;
}

void mirus::terminal_move_cursor() {
    using namespace mirus;

    unsigned temp;

    /* The equation for finding the index in a linear
    *  chunk of memory can be represented by:
    *  Index = [(y * width) + x] */
    temp = terminal_row * 80 + terminal_column;

    /* This sends a command to indicies 14 and 15 in the
    *  CRT Control Register of the VGA controller. These
    *  are the high and low bytes of the index that show
    *  where the hardware cursor is to be 'blinking'. To
    *  learn more, you should look up some VGA specific
    *  programming documents. A great start to graphics:
    *  http://www.brackeen.com/home/vga */
    mirus::outb(0x3D4, 14);
    mirus::outb(0x3D5, temp >> 8);
    mirus::outb(0x3D4, 15);
    mirus::outb(0x3D5, temp);
}<|endoftext|>