text:
package ncc

// This file implements the IPVS interface for the Seesaw Network Control
// component.

import (
	"sync"

	"github.com/google/seesaw/ipvs"
	ncctypes "github.com/google/seesaw/ncc/types"

	log "github.com/golang/glog"
)

var ipvsMutex sync.Mutex

// initIPVS initialises the IPVS sub-component.
func initIPVS() {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	log.Infof("Initialising IPVS...")
	if err := ipvs.Init(); err != nil {
		// TODO(jsing): modprobe ip_vs and try again.
		log.Fatalf("IPVS initialisation failed: %v", err)
	}
	log.Infof("IPVS version %s", ipvs.Version())
}

// IPVSFlush flushes all services and destinations from the IPVS table.
func (ncc *SeesawNCC) IPVSFlush(in int, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.Flush()
}

// IPVSGetServices gets the currently configured services from the IPVS table.
func (ncc *SeesawNCC) IPVSGetServices(in int, s *ncctypes.IPVSServices) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	svcs, err := ipvs.GetServices()
	if err != nil {
		return err
	}
	s.Services = nil
	for _, svc := range svcs {
		s.Services = append(s.Services, svc)
	}
	return nil
}

// IPVSGetService gets the currently configured service from the IPVS table,
// which matches the specified service.
func (ncc *SeesawNCC) IPVSGetService(si *ipvs.Service, s *ncctypes.IPVSServices) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	so, err := ipvs.GetService(si)
	if err != nil {
		return err
	}
	s.Services = []*ipvs.Service{so}
	return nil
}

// IPVSAddService adds the specified service to the IPVS table.
func (ncc *SeesawNCC) IPVSAddService(svc *ipvs.Service, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.AddService(*svc)
}

// IPVSUpdateService updates the specified service in the IPVS table.
func (ncc *SeesawNCC) IPVSUpdateService(svc *ipvs.Service, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.UpdateService(*svc)
}

// IPVSDeleteService deletes the specified service from the IPVS table.
func (ncc *SeesawNCC) IPVSDeleteService(svc *ipvs.Service, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.DeleteService(*svc)
}

// IPVSAddDestination adds the specified destination to the IPVS table.
func (ncc *SeesawNCC) IPVSAddDestination(dst *ncctypes.IPVSDestination, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.AddDestination(*dst.Service, *dst.Destination)
}

// IPVSUpdateDestination updates the specified destination in the IPVS table.
func (ncc *SeesawNCC) IPVSUpdateDestination(dst *ncctypes.IPVSDestination, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.UpdateDestination(*dst.Service, *dst.Destination)
}

// IPVSDeleteDestination deletes the specified destination from the IPVS table.
func (ncc *SeesawNCC) IPVSDeleteDestination(dst *ncctypes.IPVSDestination, out *int) error {
	ipvsMutex.Lock()
	defer ipvsMutex.Unlock()
	return ipvs.DeleteDestination(*dst.Service, *dst.Destination)
}


text:
package tk.roaimsapp.centrefinder;
import android.support.v4.widget.CursorAdapter;
import android.content.Context;
import android.view.View;
import android.database.Cursor;
import android.view.ViewGroup;
import android.widget.TextView;

public class SpinnerAdapter extends CursorAdapter
{

		private View v;
		public SpinnerAdapter(Context context,Cursor cursor){
				super(context,cursor,false);
		}
		@Override
		public View newView ( Context p1, Cursor p2, ViewGroup p3 ) {
						v=View.inflate(p1,R.layout.view_spinner,null);
				return v;
		}

		@Override
		public void bindView ( View p1, Context p2, Cursor p3 ) {
				// TODO: Implement this method
				TextView tv = (TextView) p1.findViewById(R.id.viewspinnerTextView1);
				String text = p3.getString(1)+"\n"+p3.getString(2);
				tv.setText ( text );
		}

		@Override
		public Integer getItem ( int position ) {
				// TODO: Implement this method
				Cursor c = getCursor();
				c.moveToPosition(position);
				return c.getInt(0);
		}

}

redpajama_set_name: RedPajamaGithub


text:
 Specialty.create name: 'Cardiology'
 Specialty.create name: 'Dermatology'
 Specialty.create name: 'General Surgery'


text:
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// Array of videoIds
// The key corresponds to the data attributes in about/index.html
var playerInfoList = [
];

function createPlayer(key) {
  $('#player').append('');
}

// click event for presentations/talks in about
$('.pt').on('click', function() {
  var self = this,
      video = playerInfoList.filter(function(obj) {
        return obj.key == $(self).data('key');
      })[0];

  if (video.type == 'yt') {
    createPlayer(video.key);
  } else {
    window.open(video.key);
  }

  resizePlayer();
  $('#player iframe').on('load', function() {
    $('.pt-lightbox').addClass('active');
  });
});

// Close lightbox when clicking anywhere on overlay
$('.pt-lightbox').on('click', function() {
  if ($(this).hasClass('active')) {
    $(this).removeClass('active');
    $(this).find('iframe').remove();
    $('body, html').removeClass('noscroll');
  }
});

// Resize Player
function resizePlayer() {
  var $inner = $('.pt-player'),
      defaultHeight = window.innerHeight || document.documentElement.clientHeight,
      defaultWidth = window.innerWidth || document.documentElement.clientWidth,
      maxHeight = defaultHeight*.75,
      maxWidth = defaultWidth*.75,
      newWidth = maxWidth,
      newHeight = 16 * maxWidth / 9;

  if (defaultWidth > defaultHeight){
      if (newHeight > maxHeight){
        newWidth = 16 * maxHeight / 9;
        newHeight = maxHeight;
      }
  } else {
      newWidth = 16 * maxHeight / 9;
      newHeight = maxHeight;
      if (newWidth > maxWidth){
          newHeight = 9 * maxWidth / 16;
          newWidth = maxWidth;
      }
  }

  $inner.css({"width": newWidth, "height": newHeight});
}

// Jquery UI for tabbed panes
$.getScript("https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js", function(){
  setupTabs();
});

// Add the 'external' class to every outbound link on the site.
// The css will add a small right arrow after the link.
$('a').filter(function() {
   return this.hostname && this.hostname !== location.hostname;
}).addClass("external");

//Set up tabs
function setupTabs(rootElement) {
      rootElement = rootElement || document;
      var tabs = $(rootElement).find('div.tabs');
      if(tabs.length > 0) {
        tabs.tabs();
      }
};

// Make the table of contents
$(document).ready(function() {
    var $window = $(window);

    // Sticky Nav on Scroll Up
    var iScrollPos = 0;

    $window.scroll(function () {
      var iCurScrollPos = $(this).scrollTop();
        if (iCurScrollPos > iScrollPos) {
          //Scrolling Down
          if ($('#sticky-nav').visible()){
            $('#sticky-nav').removeClass("on-page");
          }
        } else {
          //Scrolling Up
          if ($('.nav-hero-container').visible(true) && $('#sticky-nav').visible()){
            $('#sticky-nav').removeClass("on-page");
          } else if (!$('.nav-hero-container').visible(true)) {
            $('#sticky-nav').addClass("on-page");
          }
        }
        iScrollPos = iCurScrollPos;
    });

    $('.toc').click(function(){
      setTimeout(function(){
        $('#sticky-nav').addClass("on-page");
      }, 1000)
    });

    setTimeout(function(){
      if (document.URL.indexOf("#") != -1 && document.URL.indexOf("contribute") == -1 ) {
        $('#sticky-nav').addClass("on-page");
      }
    }, 1000);

    // Scroll to sections
    $('.btn-floating').on('click', function(){
      $('html, body').scrollTo(('#' +($(this).data("target"))), 350);
    })

    // Invoke slick JS carousel
    // Detailed documentation: http://kenwheeler.github.io/slick/
    $('.pt-container').slick({
      arrows: true,
      dots: false,
      autoplay: false,
      infinite: true,
      slidesToShow: 4,
      slidesToScroll: 1,
      responsive: [
        {
          breakpoint: 1024,
          settings: {
            slidesToShow: 3,
            dots: false,
            arrows: true
          }
        },
        {
          breakpoint: 800,
          settings: {
            slidesToShow: 3,
            dots: true,
            arrows: false
          }
        },
        {
          breakpoint: 600,
          settings: {
            slidesToShow: 2,
            dots: true,
            arrows: false
          }
        },
        {
          breakpoint: 480,
          settings: {
            slidesToShow: 1,
            dots: true,
            arrows: false
          }
        }
      ]
    });

    $('.slick-next').on('click', function() {
      $('.slick-prev').addClass('active');
    });

    $('.toc').toc({ listType: 'ul' });

    $('.nav-toggle, .hamburger').on('click', function(){
      $('.top-nav').toggleClass('right');
    });

    $('.nav-doc-toggle').on('click', function(){
      $('.doc-list').toggleClass('active');
    });

    $(window).on('resize',function(){
       //send resize event to slick after it's been destroyed
      $('.pt-container').slick('resize');

      //reset event listener on resize
      $('.slick-next').on('click', function() {
        $('.slick-prev').addClass('active');
      });

      if ($(window).width() >= 768 && !($('.top-nav').hasClass('right'))) {
        $('.top-nav').addClass('right');
      }
    });

    $('.toggle').on('click',function(){
      $(this).toggleClass('active');
    });

    var forwarding = window.location.hash.replace("#","");
    if (forwarding) {
        $("#generalInstructions").hide();
        $("#continueEdit").show();
        $("#continueEditButton").text("Edit " + forwarding);
        $("#continueEditButton").attr("href", "{{ site.githuburl }}edit/master/" + forwarding)
    } else {
        $("#generalInstructions").show();
        $("#continueEdit").hide();
    }
});

// Prettyprint
$('pre').addClass("prettyprint");
$.getScript("https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js", function(){
});

// Collapsible navbar menu, using https://github.com/jordnkr/collapsible
$.getScript("/js/jquery.collapsible.js", function(){
  highlightActive();
  $('.submenu').collapsible();
});

// TOC script
// https://github.com/ghiculescu/jekyll-table-of-contents
(function($){
  $.fn.toc = function(options) {
    var defaults = {
      noBackToTopLinks: false,
      title: '',
      minimumHeaders: 2,
      headers: 'h1, h2, h3, h4, h5, h6',
      listType: 'ol', // values: [ol|ul]
      showEffect: 'show', // values: [show|slideDown|fadeIn|none]
      showSpeed: 'slow' // set to 0 to deactivate effect
    },
    settings = $.extend(defaults, options);

    function fixedEncodeURIComponent (str) {
      return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
        return '%' + c.charCodeAt(0).toString(16);
      });
    }

    var headers = $(settings.headers).filter(function() {
      // get all headers with an ID
      var previousSiblingName = $(this).prev().attr( "name" );
      if (!this.id && previousSiblingName) {
        this.id = $(this).attr( "id", previousSiblingName.replace(/\./g, "-") );
      }
      return this.id;
    }), output = $(this);
    if (!headers.length || headers.length < settings.minimumHeaders || !output.length) {
      return;
    }

    if (0 === settings.showSpeed) {
      settings.showEffect = 'none';
    }

    var render = {
      show: function() { output.hide().html(html).show(settings.showSpeed); },
      slideDown: function() { output.hide().html(html).slideDown(settings.showSpeed); },
      fadeIn: function() { output.hide().html(html).fadeIn(settings.showSpeed); },
      none: function() { output.html(html); }
    };

    var get_level = function(ele) { return parseInt(ele.nodeName.replace("H", ""), 10); }
    var highest_level = headers.map(function(_, ele) { return get_level(ele); }).get().sort()[0];
    var return_to_top = ' ';

    var level = get_level(headers[0]),
      this_level,
      html = settings.title + " <"+settings.listType+">";
    headers.on('click', function() {
      if (!settings.noBackToTopLinks) {
        window.location.hash = this.id;
      }
    })
    .addClass('clickable-header')
    .each(function(_, header) {
      this_level = get_level(header);
      if (!settings.noBackToTopLinks && this_level === highest_level) {
        $(header).addClass('top-level-header').after(return_to_top);
      }
      if (this_level === level) // same level as before; same indenting
        html += "
" + header.innerHTML + "";
      else if (this_level <= level){ // higher level than before; end parent ol
        for(i = this_level; i < level; i++) {
          html += "
</"+settings.listType+">"
        }
        html += "
" + header.innerHTML + "";
      }
      else if (this_level > level) { // lower level than before; expand the previous to contain a ol
        for(i = this_level; i > level; i--) {
          html += "<"+settings.listType+">
"
        }
        html += "" + header.innerHTML + "";
      }
      level = this_level; // update for the next one
    });
    html += "</"+settings.listType+">";
    if (!settings.noBackToTopLinks) {
      $(document).on('click', '.back-to-top', function() {
        $(window).scrollTop(0);
        window.location.hash = '';
      });
    }

    render[settings.showEffect]();
  };
})(jQuery);


text:
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''

---

**ONLY IN ENGLISH**


text:
from oslo_log import log as logging

import cinder.volume.driver
from cinder.volume.drivers.dothill import dothill_common
from cinder.volume.drivers.san import san
from cinder.zonemanager import utils as fczm_utils

LOG = logging.getLogger(__name__)

class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver):
    """Openstack Fibre Channel cinder drivers for DotHill Arrays.

    Version history:
        0.1    - Base version developed for HPMSA FC drivers:
                    "https://github.com/openstack/cinder/tree/stable/juno/
                     cinder/volume/drivers/san/hp"
        1.0    - Version developed for DotHill arrays with the following
                 modifications:
                     - added support for v3 API(realstor feature)
                     - added support for retype volume
                     - added support for manage/unmanage volume
                     - added initiator target mapping in FC zoning
                     - added https support

    """

    VERSION = "1.0"

    def __init__(self, *args, **kwargs):
        super(DotHillFCDriver, self).__init__(*args, **kwargs)
        self.common = None
        self.configuration.append_config_values(dothill_common.common_opt)
        self.configuration.append_config_values(san.san_opts)
        self.lookup_service = fczm_utils.create_lookup_service()

    def _init_common(self):
        return dothill_common.DotHillCommon(self.configuration)

    def _check_flags(self):
        required_flags = ['san_ip', 'san_login', 'san_password']
        self.common.check_flags(self.configuration, required_flags)

    def do_setup(self, context):
        self.common = self._init_common()
        self._check_flags()
        self.common.do_setup(context)

    def check_for_setup_error(self):
        self._check_flags()

    def create_volume(self, volume):
        return {'metadata': self.common.create_volume(volume)}

    def create_volume_from_snapshot(self, volume, src_vref):
        self.common.create_volume_from_snapshot(volume, src_vref)

    def create_cloned_volume(self, volume, src_vref):
        return {'metadata': self.common.create_cloned_volume(volume, src_vref)}

    def delete_volume(self, volume):
        self.common.delete_volume(volume)

    @fczm_utils.AddFCZone
    def initialize_connection(self, volume, connector):
        self.common.client_login()
        try:
            data = {}
            data['target_lun'] = self.common.map_volume(volume,
                                                        connector,
                                                        'wwpns')

            ports, init_targ_map = self.get_init_targ_map(connector)
            data['target_discovered'] = True
            data['target_wwn'] = ports
            data['initiator_target_map'] = init_targ_map
            info = {'driver_volume_type': 'fibre_channel',
                    'data': data}
            return info
        finally:
            self.common.client_logout()

    @fczm_utils.RemoveFCZone
    def terminate_connection(self, volume, connector, **kwargs):
        self.common.unmap_volume(volume, connector, 'wwpns')
        info = {'driver_volume_type': 'fibre_channel', 'data': {}}
        if not self.common.client.list_luns_for_host(connector['wwpns'][0]):
            ports, init_targ_map = self.get_init_targ_map(connector)
            info['data'] = {'target_wwn': ports,
                            'initiator_target_map': init_targ_map}
        return info

    def get_init_targ_map(self, connector):
        init_targ_map = {}
        target_wwns = []
        ports = self.common.get_active_fc_target_ports()
        if self.lookup_service is not None:
            dev_map = self.lookup_service.get_device_mapping_from_network(
                connector['wwpns'],
                ports)
            for fabric_name in dev_map:
                fabric = dev_map[fabric_name]
                target_wwns += fabric['target_port_wwn_list']
                for initiator in fabric['initiator_port_wwn_list']:
                    if initiator not in init_targ_map:
                        init_targ_map[initiator] = []
                    init_targ_map[initiator] += fabric['target_port_wwn_list']
                    init_targ_map[initiator] = list(set(
                                                    init_targ_map[initiator]))
            target_wwns = list(set(target_wwns))
        else:
            initiator_wwns = connector['wwpns']
            target_wwns = ports
            for initiator in initiator_wwns:
                init_targ_map[initiator] = target_wwns

        return target_wwns, init_targ_map

    def get_volume_stats(self, refresh=False):
        stats = self.common.get_volume_stats(refresh)
        stats['storage_protocol'] = 'FC'
        stats['driver_version'] = self.VERSION
        backend_name = self.configuration.safe_get('volume_backend_name')
        stats['volume_backend_name'] = (backend_name or
                                        self.__class__.__name__)
        return stats

    def create_export(self, context, volume, connector):
        pass

    def ensure_export(self, context, volume):
        pass

    def remove_export(self, context, volume):
        pass

    def create_snapshot(self, snapshot):
        self.common.create_snapshot(snapshot)

    def delete_snapshot(self, snapshot):
        self.common.delete_snapshot(snapshot)

    def extend_volume(self, volume, new_size):
        self.common.extend_volume(volume, new_size)

    def retype(self, context, volume, new_type, diff, host):
        return self.common.retype(volume, new_type, diff, host)

    def manage_existing(self, volume, existing_ref):
        self.common.manage_existing(volume, existing_ref)

    def manage_existing_get_size(self, volume, existing_ref):
        return self.common.manage_existing_get_size(volume, existing_ref)

    def unmanage(self, volume):
        pass


text:
package com.centurylink.mdw.script;

public class JsonBuilder extends groovy.json.JsonBuilder implements Builder {

    private String name;
    public String getName() { return name; }

    public JsonBuilder(String name) {
        this.name = name;
    }

    public String getString() {
        return toString();
    }
}


text:
//// [constructSignatureAssignabilityInInheritance2.ts]
// checking subtype relations for function types as it relates to contextual signature instantiation

class Base { foo: string; }
class Derived extends Base { bar: string; }
class Derived2 extends Derived { baz: string; }
class OtherDerived extends Base { bing: string; }

interface A { // T
    // M's
    a: new (x: number) => number[];
    a2: new (x: number) => string[];
    a3: new (x: number) => void;
    a4: new (x: string, y: number) => string;
    a5: new (x: (arg: string) => number) => string;
    a6: new (x: (arg: Base) => Derived) => Base;
    a7: new (x: (arg: Base) => Derived) => (r: Base) => Derived;
    a8: new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived;
    a9: new (x: (arg: Base) => Derived, y: (arg2: Base) => Derived) => (r: Base) => Derived;
    a10: new (...x: Derived[]) => Derived;
    a11: new (x: { foo: string }, y: { foo: string; bar: string }) => Base;
    a12: new (x: Array<Base>, y: Array<Derived2>) => Array<Derived>;
    a13: new (x: Array<Base>, y: Array<Derived>) => Array<Derived>;
    a14: new (x: { a: string; b: number }) => Object;
    a15: {
        new (x: number): number[];
        new (x: string): string[];
    };
    a16: {
        new <T extends Derived>(x: T): number[];
        new <U extends Base>(x: U): number[];
    };
    a17: {
        new (x: new (a: number) => number): number[];
        new (x: new (a: string) => string): string[];
    };
    a18: {
        new (x: {
            new (a: number): number;
            new (a: string): string;
        }): any[];
        new (x: {
            new (a: boolean): boolean;
            new (a: Date): Date;
        }): any[];
    };
}

// S's
interface I extends A {
    // N's
    a: new <T>(x: T) => T[]; // ok, instantiation of N is a subtype of M, T is number
    a2: new <T>(x: T) => string[]; // ok
    a3: new <T>(x: T) => T; // ok since Base returns void
    a4: new <T, U>(x: T, y: U) => T; // ok, instantiation of N is a subtype of M, T is string, U is number
    a5: new <T, U>(x: (arg: T) => U) => T; // ok, U is in a parameter position so inferences can be made
    a6: new <T extends Base, U extends Derived>(x: (arg: T) => U) => T; // ok, same as a5 but with object type hierarchy
    a7: new <T extends Base, U extends Derived>(x: (arg: T) => U) => (r: T) => U; // ok
    a8: new <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: T) => U) => (r: T) => U; // ok
    a9: new <T extends Base, U extends Derived>(x: (arg: T) => U, y: (arg2: { foo: string; bing: number }) => U) => (r: T) => U; // ok, same as a8 with compatible object literal
    a10: new <T extends Derived>(...x: T[]) => T; // ok
    a11: new <T extends Base>(x: T, y: T) => T; // ok
    a12: new <T extends Array<Base>>(x: Array<Base>, y: T) => Array<Derived>; // ok, less specific parameter type
    a13: new <T extends Array<Derived>>(x: Array<Base>, y: T) => T; // ok, T = Array<Derived>, satisfies constraint, contextual signature instantiation succeeds
    a14: new <T, U>(x: { a: T; b: U }) => T; // ok
    a15: new <T>(x: T) => T[]; // ok
    a16: new <T extends Base>(x: T) => number[]; // ok
    a17: new <T>(x: new (a: T) => T) => T[]; // ok
    a18: new <T>(x: new (a: T) => T) => T[]; // ok, no inferences for T but assignable to any
}

//// [constructSignatureAssignabilityInInheritance2.js]
// checking subtype relations for function types as it relates to contextual signature instantiation
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var Base = /** @class */ (function () {
    function Base() {
    }
    return Base;
}());
var Derived = /** @class */ (function (_super) {
    __extends(Derived, _super);
    function Derived() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Derived;
}(Base));
var Derived2 = /** @class */ (function (_super) {
    __extends(Derived2, _super);
    function Derived2() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return Derived2;
}(Derived));
var OtherDerived = /** @class */ (function (_super) {
    __extends(OtherDerived, _super);
    function OtherDerived() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return OtherDerived;
}(Base));


text:
void statlog_log(const char* metric_type, const char* metric, int value);
void statlog_log(const char* metric_type, const char* metric, float value);

#define statlog_gauge(metric, value) statlog_log(STATLOG_GAUGE, metric, value)
#define statlog_sample(metric, value) statlog_log(STATLOG_SAMPLE, metric, value)


text:
/*
 * These authors would like to acknowledge the Spanish Ministry of Industry,
 * Tourism and Trade, for the support in the project TSI020301-2008-2
 * "PIRAmIDE: Personalizable Interactions with Resources on AmI-enabled
 * Mobile Dynamic Environments", led by Treelogic
 * ( http://www.treelogic.com/ ):
 *
 *   http://www.piramidepse.com/
 */

package com.google.zxing.oned.rss.expanded;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.BitArray;
import com.google.zxing.oned.rss.AbstractRSSReader;
import com.google.zxing.oned.rss.DataCharacter;
import com.google.zxing.oned.rss.FinderPattern;
import com.google.zxing.oned.rss.RSSUtils;
import com.google.zxing.oned.rss.expanded.decoders.AbstractExpandedDecoder;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Collections;

/**
 * @author Pablo Orduña, University of Deusto (pablo.orduna@deusto.es)
 * @author Eduardo Castillejo, University of Deusto (eduardo.castillejo@deusto.es)
 */
public final class RSSExpandedReader extends AbstractRSSReader {

  private static final int[] SYMBOL_WIDEST = {7, 5, 4, 3, 1};
  private static final int[] EVEN_TOTAL_SUBSET = {4, 20, 52, 104, 204};
  private static final int[] GSUM = {0, 348, 1388, 2948, 3988};

  private static final int[][] FINDER_PATTERNS = {
    {1,8,4,1}, // A
    {3,6,4,1}, // B
    {3,4,6,1}, // C
    {3,2,8,1}, // D
    {2,6,5,1}, // E
    {2,2,9,1}  // F
  };

  private static final int[][] WEIGHTS = {
    {  1,   3,   9,  27,  81,  32,  96,  77},
    { 20,  60, 180, 118, 143,   7,  21,  63},
    {189, 145,  13,  39, 117, 140, 209, 205},
    {193, 157,  49, 147,  19,  57, 171,  91},
    { 62, 186, 136, 197, 169,  85,  44, 132},
    {185, 133, 188, 142,   4,  12,  36, 108},
    {113, 128, 173,  97,  80,  29,  87,  50},
    {150,  28,  84,  41, 123, 158,  52, 156},
    { 46, 138, 203, 187, 139, 206, 196, 166},
    { 76,  17,  51, 153,  37, 111, 122, 155},
    { 43, 129, 176, 106, 107, 110, 119, 146},
    { 16,  48, 144,  10,  30,  90,  59, 177},
    {109, 116, 137, 200, 178, 112, 125, 164},
    { 70, 210, 208, 202, 184, 130, 179, 115},
    {134, 191, 151,  31,  93,  68, 204, 190},
    {148,  22,  66, 198, 172,   94, 71,   2},
    {  6,  18,  54, 162,  64,  192,154,  40},
    {120, 149,  25,  75,  14,   42,126, 167},
    { 79,  26,  78,  23,  69,  207,199, 175},
    {103,  98,  83,  38, 114, 131, 182, 124},
    {161,  61, 183, 127, 170,  88,  53, 159},
    { 55, 165,  73,   8,  24,  72,   5,  15},
    { 45, 135, 194, 160,  58, 174, 100,  89}
  };

  private static final int FINDER_PAT_A = 0;
  private static final int FINDER_PAT_B = 1;
  private static final int FINDER_PAT_C = 2;
  private static final int FINDER_PAT_D = 3;
  private static final int FINDER_PAT_E = 4;
  private static final int FINDER_PAT_F = 5;

  private static final int[][] FINDER_PATTERN_SEQUENCES = {
    { FINDER_PAT_A, FINDER_PAT_A },
    { FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B },
    { FINDER_PAT_A, FINDER_PAT_C, FINDER_PAT_B, FINDER_PAT_D },
    { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_C },
    { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_F },
    { FINDER_PAT_A, FINDER_PAT_E, FINDER_PAT_B, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
    { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D },
    { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E },
    { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
    { FINDER_PAT_A, FINDER_PAT_A, FINDER_PAT_B, FINDER_PAT_B, FINDER_PAT_C, FINDER_PAT_D, FINDER_PAT_D, FINDER_PAT_E, FINDER_PAT_E, FINDER_PAT_F, FINDER_PAT_F },
  };

  //private static final int LONGEST_SEQUENCE_SIZE = FINDER_PATTERN_SEQUENCES[FINDER_PATTERN_SEQUENCES.length - 1].length;

  private static final int MAX_PAIRS = 11;

  private final List<ExpandedPair> pairs = new ArrayList<>(MAX_PAIRS);
  private final List<ExpandedRow> rows = new ArrayList<>();
  private final int [] startEnd = new int[2];
  //private final int [] currentSequence = new int[LONGEST_SEQUENCE_SIZE];
  private boolean startFromEven = false;

  @Override
  public Result decodeRow(int rowNumber,
                          BitArray row,
                          Map<DecodeHintType,?> hints) throws NotFoundException, FormatException {
    // Rows can start with even pattern in case in prev rows there where odd number of patters.
    // So lets try twice
    this.pairs.clear();
    this.startFromEven = false;
    try {
      List<ExpandedPair> pairs = decodeRow2pairs(rowNumber, row);
      return constructResult(pairs);
    } catch (NotFoundException e) {
      // OK
    }

    this.pairs.clear();
    this.startFromEven = true;
    List<ExpandedPair> pairs = decodeRow2pairs(rowNumber, row);
    return constructResult(pairs);
  }

  @Override
  public void reset() {
    this.pairs.clear();
    this.rows.clear();
  }

  // Not private for testing
  List<ExpandedPair> decodeRow2pairs(int rowNumber, BitArray row) throws NotFoundException {
    try {
      while (true){
        ExpandedPair nextPair = retrieveNextPair(row, this.pairs, rowNumber);
        this.pairs.add(nextPair);
        //System.out.println(this.pairs.size()+" pairs found so far on row "+rowNumber+": "+this.pairs);
        // exit this loop when retrieveNextPair() fails and throws
      }
    } catch (NotFoundException nfe) {
      if (this.pairs.isEmpty()) {
        throw nfe;
      }
    }

    // TODO: verify sequence of finder patterns as in checkPairSequence()
    if (checkChecksum()) {
      return this.pairs;
    }

    boolean tryStackedDecode = !this.rows.isEmpty();
    boolean wasReversed = false; // TODO: deal with reversed rows
    storeRow(rowNumber, wasReversed);
    if (tryStackedDecode) {
      // When the image is 180-rotated, then rows are sorted in wrong dirrection.
      // Try twice with both the directions.
      List<ExpandedPair> ps = checkRows(false);
      if (ps != null) {
        return ps;
      }
      ps = checkRows(true);
      if (ps != null) {
        return ps;
      }
    }

    throw NotFoundException.getNotFoundInstance();
  }

  private List<ExpandedPair> checkRows(boolean reverse) {
    // Limit number of rows we are checking
    // We use recursive algorithm with pure complexity and don't want it to take forever
    // Stacked barcode can have up to 11 rows, so 25 seems resonable enough
    if (this.rows.size() > 25) {
      this.rows.clear();  // We will never have a chance to get result, so clear it
      return null;
    }

    this.pairs.clear();
    if (reverse) {
      Collections.reverse(this.rows);
    }

    List<ExpandedPair> ps = null;
    try {
      ps = checkRows(new ArrayList<ExpandedRow>(), 0);
    } catch (NotFoundException e) {
      // OK
    }

    if (reverse) {
      Collections.reverse(this.rows);
    }

    return ps;
  }

  // Try to construct a valid rows sequence
  // Recursion is used to implement backtracking
  private List<ExpandedPair> checkRows(List<ExpandedRow> collectedRows, int currentRow) throws NotFoundException {
    for (int i = currentRow; i < rows.size(); i++) {
      ExpandedRow row = rows.get(i);
      this.pairs.clear();
      int size = collectedRows.size();
      for (int j = 0; j < size; j++) {
        this.pairs.addAll(collectedRows.get(j).getPairs());
      }
      this.pairs.addAll(row.getPairs());

      if (!isValidSequence(this.pairs)) {
        continue;
      }

      if (checkChecksum()) {
        return this.pairs;
      }

      List<ExpandedRow> rs = new ArrayList<>();
      rs.addAll(collectedRows);
      rs.add(row);
      try {
        // Recursion: try to add more rows
        return checkRows(rs, i + 1);
      } catch (NotFoundException e) {
        // We failed, try the next candidate
      }
    }

    throw NotFoundException.getNotFoundInstance();
  }

  // Whether the pairs form a valid find pattern seqience,
  // either complete or a prefix
  private static boolean isValidSequence(List<ExpandedPair> pairs) {
    for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
      if (pairs.size() > sequence.length) {
        continue;
      }

      boolean stop = true;
      for (int j = 0; j < pairs.size(); j++) {
        if (pairs.get(j).getFinderPattern().getValue() != sequence[j]) {
          stop = false;
          break;
        }
      }

      if (stop) {
        return true;
      }
    }

    return false;
  }

  private void storeRow(int rowNumber, boolean wasReversed) {
    // Discard if duplicate above or below; otherwise insert in order by row number.
    int insertPos = 0;
    boolean prevIsSame = false;
    boolean nextIsSame = false;
    while (insertPos < this.rows.size()) {
      ExpandedRow erow = this.rows.get(insertPos);
      if (erow.getRowNumber() > rowNumber) {
        nextIsSame = erow.isEquivalent(this.pairs);
        break;
      }
      prevIsSame = erow.isEquivalent(this.pairs);
      insertPos++;
    }
    if (nextIsSame || prevIsSame) {
      return;
    }

    // When the row was partially decoded (e.g. 2 pairs found instead of 3),
    // it will prevent us from detecting the barcode.
    // Try to merge partial rows

    // Check whether the row is part of an allready detected row
    if (isPartialRow(this.pairs, this.rows)) {
      return;
    }

    this.rows.add(insertPos, new ExpandedRow(this.pairs, rowNumber, wasReversed));

    removePartialRows(this.pairs, this.rows);
  }

  // Remove all the rows that contains only specified pairs
  private static void removePartialRows(List<ExpandedPair> pairs, List<ExpandedRow> rows) {
    for (Iterator<ExpandedRow> iterator = rows.iterator(); iterator.hasNext(); ) {
      ExpandedRow r = iterator.next();
      if (r.getPairs().size() == pairs.size()) {
        continue;
      }
      boolean allFound = true;
      for (ExpandedPair p : r.getPairs()) {
        boolean found = false;
        for (ExpandedPair pp : pairs) {
          if (p.equals(pp)) {
            found = true;
            break;
          }
        }
        if (!found) {
          allFound = false;
          break;
        }
      }
      if (allFound) {
        // 'pairs' contains all the pairs from the row 'r'
        iterator.remove();
      }
    }
  }

  // Returns true when one of the rows already contains all the pairs
  private static boolean isPartialRow(Iterable<ExpandedPair> pairs, Iterable<ExpandedRow> rows) {
    for (ExpandedRow r : rows) {
      boolean allFound = true;
      for (ExpandedPair p : pairs) {
        boolean found = false;
        for (ExpandedPair pp : r.getPairs()) {
          if (p.equals(pp)) {
            found = true;
            break;
          }
        }
        if (!found) {
          allFound = false;
          break;
        }
      }
      if (allFound) {
        // the row 'r' contain all the pairs from 'pairs'
        return true;
      }
    }
    return false;
  }

  // Only used for unit testing
  List<ExpandedRow> getRows() {
    return this.rows;
  }

  // Not private for unit testing
  static Result constructResult(List<ExpandedPair> pairs) throws NotFoundException, FormatException {
    BitArray binary = BitArrayBuilder.buildBitArray(pairs);

    AbstractExpandedDecoder decoder = AbstractExpandedDecoder.createDecoder(binary);
    String resultingString = decoder.parseInformation();

    ResultPoint[] firstPoints = pairs.get(0).getFinderPattern().getResultPoints();
    ResultPoint[] lastPoints  = pairs.get(pairs.size() - 1).getFinderPattern().getResultPoints();

    return new Result(
          resultingString,
          null,
          new ResultPoint[]{firstPoints[0], firstPoints[1], lastPoints[0], lastPoints[1]},
          BarcodeFormat.RSS_EXPANDED
      );
  }

  private boolean checkChecksum() {
    ExpandedPair firstPair = this.pairs.get(0);
    DataCharacter checkCharacter = firstPair.getLeftChar();
    DataCharacter firstCharacter = firstPair.getRightChar();

    if (firstCharacter == null) {
      return false;
    }

    int checksum = firstCharacter.getChecksumPortion();
    int s = 2;

    for(int i = 1; i < this.pairs.size(); ++i){
      ExpandedPair currentPair = this.pairs.get(i);
      checksum += currentPair.getLeftChar().getChecksumPortion();
      s++;
      DataCharacter currentRightChar = currentPair.getRightChar();
      if (currentRightChar != null) {
        checksum += currentRightChar.getChecksumPortion();
        s++;
      }
    }

    checksum %= 211;

    int checkCharacterValue = 211 * (s - 4) + checksum;

    return checkCharacterValue == checkCharacter.getValue();
  }

  private static int getNextSecondBar(BitArray row, int initialPos){
    int currentPos;
    if (row.get(initialPos)) {
      currentPos = row.getNextUnset(initialPos);
      currentPos = row.getNextSet(currentPos);
    } else {
      currentPos = row.getNextSet(initialPos);
      currentPos = row.getNextUnset(currentPos);
    }
    return currentPos;
  }

  // not private for testing
  ExpandedPair retrieveNextPair(BitArray row, List<ExpandedPair> previousPairs, int rowNumber)
      throws NotFoundException {
    boolean isOddPattern  = previousPairs.size() % 2 == 0;
    if (startFromEven) {
      isOddPattern = !isOddPattern;
    }

    FinderPattern pattern;

    boolean keepFinding = true;
    int forcedOffset = -1;
    do{
      this.findNextPair(row, previousPairs, forcedOffset);
      pattern = parseFoundFinderPattern(row, rowNumber, isOddPattern);
      if (pattern == null){
        forcedOffset = getNextSecondBar(row, this.startEnd[0]);
      } else {
        keepFinding = false;
      }
    }while(keepFinding);

    // When stacked symbol is split over multiple rows, there's no way to guess if this pair can be last or not.
    // boolean mayBeLast = checkPairSequence(previousPairs, pattern);

    DataCharacter leftChar  = this.decodeDataCharacter(row, pattern, isOddPattern, true);

    if (!previousPairs.isEmpty() && previousPairs.get(previousPairs.size()-1).mustBeLast()) {
      throw NotFoundException.getNotFoundInstance();
    }

    DataCharacter rightChar;
    try {
      rightChar = this.decodeDataCharacter(row, pattern, isOddPattern, false);
    } catch(NotFoundException ignored) {
      rightChar = null;
    }
    boolean mayBeLast = true;
    return new ExpandedPair(leftChar, rightChar, pattern, mayBeLast);
  }

  private void findNextPair(BitArray row, List<ExpandedPair> previousPairs, int forcedOffset)
      throws NotFoundException {
    int[] counters = this.getDecodeFinderCounters();
    counters[0] = 0;
    counters[1] = 0;
    counters[2] = 0;
    counters[3] = 0;

    int width = row.getSize();

    int rowOffset;
    if (forcedOffset >= 0) {
      rowOffset = forcedOffset;
    } else if (previousPairs.isEmpty()) {
      rowOffset = 0;
    } else{
      ExpandedPair lastPair = previousPairs.get(previousPairs.size() - 1);
      rowOffset = lastPair.getFinderPattern().getStartEnd()[1];
    }
    boolean searchingEvenPair = previousPairs.size() % 2 != 0;
    if (startFromEven) {
      searchingEvenPair = !searchingEvenPair;
    }

    boolean isWhite = false;
    while (rowOffset < width) {
      isWhite = !row.get(rowOffset);
      if (!isWhite) {
        break;
      }
      rowOffset++;
    }

    int counterPosition = 0;
    int patternStart = rowOffset;
    for (int x = rowOffset; x < width; x++) {
      if (row.get(x) ^ isWhite) {
        counters[counterPosition]++;
      } else {
        if (counterPosition == 3) {
          if (searchingEvenPair) {
            reverseCounters(counters);
          }

          if (isFinderPattern(counters)){
            this.startEnd[0] = patternStart;
            this.startEnd[1] = x;
            return;
          }

          if (searchingEvenPair) {
            reverseCounters(counters);
          }

          patternStart += counters[0] + counters[1];
          counters[0] = counters[2];
          counters[1] = counters[3];
          counters[2] = 0;
          counters[3] = 0;
          counterPosition--;
        } else {
          counterPosition++;
        }
        counters[counterPosition] = 1;
        isWhite = !isWhite;
      }
    }
    throw NotFoundException.getNotFoundInstance();
  }

  private static void reverseCounters(int [] counters){
    int length = counters.length;
    for(int i = 0; i < length / 2; ++i){
      int tmp = counters[i];
      counters[i] = counters[length - i - 1];
      counters[length - i - 1] = tmp;
    }
  }

  private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean oddPattern) {
    // Actually we found elements 2-5.
    int firstCounter;
    int start;
    int end;

    if(oddPattern){
      // If pattern number is odd, we need to locate element 1 *before* the current block.

      int firstElementStart = this.startEnd[0] - 1;
      // Locate element 1
      while (firstElementStart >= 0 && !row.get(firstElementStart)) {
        firstElementStart--;
      }

      firstElementStart++;
      firstCounter = this.startEnd[0] - firstElementStart;
      start = firstElementStart;
      end = this.startEnd[1];

    }else{
      // If pattern number is even, the pattern is reversed, so we need to locate element 1 *after* the current block.

      start = this.startEnd[0];

      end = row.getNextUnset(this.startEnd[1] + 1);
      firstCounter = end - this.startEnd[1];
    }

    // Make 'counters' hold 1-4
    int [] counters = this.getDecodeFinderCounters();
    System.arraycopy(counters, 0, counters, 1, counters.length - 1);

    counters[0] = firstCounter;
    int value;
    try {
      value = parseFinderValue(counters, FINDER_PATTERNS);
    } catch (NotFoundException ignored) {
      return null;
    }
    return new FinderPattern(value, new int[] {start, end}, start, end, rowNumber);
  }

  DataCharacter decodeDataCharacter(BitArray row,
                                    FinderPattern pattern,
                                    boolean isOddPattern,
                                    boolean leftChar) throws NotFoundException {
    int[] counters = this.getDataCharacterCounters();
    counters[0] = 0;
    counters[1] = 0;
    counters[2] = 0;
    counters[3] = 0;
    counters[4] = 0;
    counters[5] = 0;
    counters[6] = 0;
    counters[7] = 0;

    if (leftChar) {
      recordPatternInReverse(row, pattern.getStartEnd()[0], counters);
    } else {
      recordPattern(row, pattern.getStartEnd()[1], counters);
      // reverse it
      for (int i = 0, j = counters.length - 1; i < j; i++, j--) {
        int temp = counters[i];
        counters[i] = counters[j];
        counters[j] = temp;
      }
    }//counters[] has the pixels of the module

    int numModules = 17; //left and right data characters have all the same length
    float elementWidth = (float) count(counters) / (float) numModules;

    // Sanity check: element width for pattern and the character should match
    float expectedElementWidth = (pattern.getStartEnd()[1] - pattern.getStartEnd()[0]) / 15.0f;
    if (Math.abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3f) {
      throw NotFoundException.getNotFoundInstance();
    }

    int[] oddCounts = this.getOddCounts();
    int[] evenCounts = this.getEvenCounts();
    float[] oddRoundingErrors = this.getOddRoundingErrors();
    float[] evenRoundingErrors = this.getEvenRoundingErrors();

    for (int i = 0; i < counters.length; i++) {
      float value = 1.0f * counters[i] / elementWidth;
      int count = (int) (value + 0.5f); // Round
      if (count < 1) {
        if (value < 0.3f) {
          throw NotFoundException.getNotFoundInstance();
        }
        count = 1;
      } else if (count > 8) {
        if (value > 8.7f) {
          throw NotFoundException.getNotFoundInstance();
        }
        count = 8;
      }
      int offset = i / 2;
      if ((i & 0x01) == 0) {
        oddCounts[offset] = count;
        oddRoundingErrors[offset] = value - count;
      } else {
        evenCounts[offset] = count;
        evenRoundingErrors[offset] = value - count;
      }
    }

    adjustOddEvenCounts(numModules);

    int weightRowNumber = 4 * pattern.getValue() + (isOddPattern?0:2) + (leftChar?0:1) - 1;

    int oddSum = 0;
    int oddChecksumPortion = 0;
    for (int i = oddCounts.length - 1; i >= 0; i--) {
      if(isNotA1left(pattern, isOddPattern, leftChar)){
        int weight = WEIGHTS[weightRowNumber][2 * i];
        oddChecksumPortion += oddCounts[i] * weight;
      }
      oddSum += oddCounts[i];
    }
    int evenChecksumPortion = 0;
    //int evenSum = 0;
    for (int i = evenCounts.length - 1; i >= 0; i--) {
      if(isNotA1left(pattern, isOddPattern, leftChar)){
        int weight = WEIGHTS[weightRowNumber][2 * i + 1];
        evenChecksumPortion += evenCounts[i] * weight;
      }
      //evenSum += evenCounts[i];
    }
    int checksumPortion = oddChecksumPortion + evenChecksumPortion;

    if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4) {
      throw NotFoundException.getNotFoundInstance();
    }

    int group = (13 - oddSum) / 2;
    int oddWidest = SYMBOL_WIDEST[group];
    int evenWidest = 9 - oddWidest;
    int vOdd = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);
    int vEven = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);
    int tEven = EVEN_TOTAL_SUBSET[group];
    int gSum = GSUM[group];
    int value = vOdd * tEven + vEven + gSum;

    return new DataCharacter(value, checksumPortion);
  }

  private static boolean isNotA1left(FinderPattern pattern, boolean isOddPattern, boolean leftChar) {
    // A1: pattern.getValue is 0 (A), and it's an oddPattern, and it is a left char
    return !(pattern.getValue() == 0 && isOddPattern && leftChar);
  }

  private void adjustOddEvenCounts(int numModules) throws NotFoundException {

    int oddSum = count(this.getOddCounts());
    int evenSum = count(this.getEvenCounts());
    int mismatch = oddSum + evenSum - numModules;
    boolean oddParityBad = (oddSum & 0x01) == 1;
    boolean evenParityBad = (evenSum & 0x01) == 0;

    boolean incrementOdd = false;
    boolean decrementOdd = false;

    if (oddSum > 13) {
      decrementOdd = true;
    } else if (oddSum < 4) {
      incrementOdd = true;
    }
    boolean incrementEven = false;
    boolean decrementEven = false;
    if (evenSum > 13) {
      decrementEven = true;
    } else if (evenSum < 4) {
      incrementEven = true;
    }

    if (mismatch == 1) {
      if (oddParityBad) {
        if (evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        decrementOdd = true;
      } else {
        if (!evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        decrementEven = true;
      }
    } else if (mismatch == -1) {
      if (oddParityBad) {
        if (evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        incrementOdd = true;
      } else {
        if (!evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        incrementEven = true;
      }
    } else if (mismatch == 0) {
      if (oddParityBad) {
        if (!evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        // Both bad
        if (oddSum < evenSum) {
          incrementOdd = true;
          decrementEven = true;
        } else {
          decrementOdd = true;
          incrementEven = true;
        }
      } else {
        if (evenParityBad) {
          throw NotFoundException.getNotFoundInstance();
        }
        // Nothing to do!
      }
    } else {
      throw NotFoundException.getNotFoundInstance();
    }

    if (incrementOdd) {
      if (decrementOdd) {
        throw NotFoundException.getNotFoundInstance();
      }
      increment(this.getOddCounts(), this.getOddRoundingErrors());
    }
    if (decrementOdd) {
      decrement(this.getOddCounts(), this.getOddRoundingErrors());
    }
    if (incrementEven) {
      if (decrementEven) {
        throw NotFoundException.getNotFoundInstance();
      }
      increment(this.getEvenCounts(), this.getOddRoundingErrors());
    }
    if (decrementEven) {
      decrement(this.getEvenCounts(), this.getEvenRoundingErrors());
    }
  }
}


text:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>basic_parser::operator=</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="../../../index.html" title="Chapter 1. Boost.JSON">
<link rel="up" href="../boost__json__basic_parser.html" title="basic_parser">
<link rel="prev" href="basic_parser/overload2.html" title="basic_parser::basic_parser (2 of 2 overloads)">
<link rel="next" href="_dtor_basic_parser.html" title="basic_parser::~basic_parser">

Home
Libraries
People
FAQ
More

basic_parser::operator=

          Copy assignment (deleted)

          Synopsis

basic_parser&
operator=(
    basic_parser const&);

Copyright © 2019, 2020 Vinnie Falco
Copyright © 2020 Krystian Stasiowski

        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)


text:
require 'spec_helper.rb'

describe 'WorkersCumulativeStatistics' do
  it "can fetch" do
    @holodeck.mock(Twilio::Response.new(500, ''))

    expect {
      @client.taskrouter.v1.workspaces('WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') \
                           .workers('WKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') \
                           .cumulative_statistics().fetch()
    }.to raise_exception(Twilio::REST::TwilioError)

    expect(
    @holodeck.has_request?(Holodeck::Request.new(
        method: 'get',
        url: 'https://taskrouter.twilio.com/v1/Workspaces/WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Workers/CumulativeStatistics',
    ))).to eq(true)
  end

  it "receives fetch responses" do
    @holodeck.mock(Twilio::Response.new(
        200,
      %q[
      {
          "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "workspace_sid": "WSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
          "url": "https://taskrouter.twilio.com/v1/Workspaces/WSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Workers/CumulativeStatistics",
          "reservations_created": 100,
          "reservations_accepted": 100,
          "reservations_rejected": 100,
          "reservations_timed_out": 100,
          "reservations_canceled": 100,
          "reservations_rescinded": 100,
          "activity_durations": [
              {
                  "max": 0,
                  "min": 900,
                  "sid": "WAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                  "friendly_name": "Offline",
                  "avg": 1080,
                  "total": 5400
              },
              {
                  "max": 0,
                  "min": 900,
                  "sid": "WAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                  "friendly_name": "Busy",
                  "avg": 1012,
                  "total": 8100
              },
              {
                  "max": 0,
                  "min": 0,
                  "sid": "WAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                  "friendly_name": "Idle",
                  "avg": 0,
                  "total": 0
              },
              {
                  "max": 0,
                  "min": 0,
                  "sid": "WAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                  "friendly_name": "Reserved",
                  "avg": 0,
                  "total": 0
              }
          ],
          "start_time": "2015-07-30T20:00:00Z",
          "end_time": "2015-07-30T20:00:00Z"
      }
      ]
    ))

    actual = @client.taskrouter.v1.workspaces('WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') \
                                  .workers('WKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX') \
                                  .cumulative_statistics().fetch()

    expect(actual).to_not eq(nil)
  end
end


text:
class Book
  include Lotus::Entity

  attributes :name
end


text:
	// Kinda void now as autocall is always on

	var appName1 = NSWorkspace.sharedWorkspace.activeApplication.objectForKey('NSApplicationName')
	var appName2 = NSWorkspace.sharedWorkspace.activeApplication.objectForKey('NSApplicationName')
//	JSCocoaController.log('appName1=' + appName1)
//	JSCocoaController.log('appName2=' + appName2)

	var numBundles1 = NSBundle.allBundles.count
	var bundles = NSBundle.allBundles
	var numBundles2 = bundles.count
//	JSCocoaController.log('numBundles1=' + numBundles1)
//	JSCocoaController.log('numBundles2=' + numBundles2)

	if (String(appName1) != String(appName2))	throw 'zeroarg caller failed 1'
	if (String(appName1) != String(appName2))	throw 'zeroarg caller failed 2'

//	log(typeof numBundles1)
//	log(typeof numBundles2)
	if (numBundles1 != numBundles2)				throw 'zeroarg valueOf caller failed'


text:
package common

import (
	"fmt"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/gravitational/teleport"
	"github.com/gravitational/teleport/lib/config"
	"github.com/gravitational/teleport/lib/defaults"
	"github.com/gravitational/teleport/lib/service"
	"github.com/gravitational/teleport/lib/sshutils/scp"
	"github.com/gravitational/teleport/lib/utils"

	log "github.com/Sirupsen/logrus"
	"github.com/google/gops/agent"
	"github.com/gravitational/roundtrip"
	"github.com/gravitational/trace"
	"github.com/prometheus/client_golang/prometheus"
)

// same as main() but has a testing switch
func Run(cmdlineArgs []string, testRun bool) (executedCommand string, conf *service.Config) {
	var err error
	// configure trace's errors to produce full stack traces
	isDebug, _ := strconv.ParseBool(os.Getenv(teleport.VerboseLogsEnvVar))
	if isDebug {
		trace.SetDebug(true)
	}
	// configure logger for a typical CLI scenario until configuration file is
	// parsed
	utils.InitLogger(utils.LoggingForDaemon, log.WarnLevel)
	app := utils.InitCLIParser("teleport", "Clustered SSH service. Learn more at http://teleport.gravitational.com")

	// define global flags:
	var ccf config.CommandLineFlags
	var scpCommand scp.Command

	// define commands:
	start := app.Command("start", "Starts the Teleport service.")
	status := app.Command("status", "Print the status of the current SSH session.")
	dump := app.Command("configure", "Print the sample config file into stdout.")
	ver := app.Command("version", "Print the version.")
	scpc := app.Command("scp", "server-side implementation of scp").Hidden()
	app.HelpFlag.Short('h')

	// define start flags:
	start.Flag("debug", "Enable verbose logging to stderr").
		Short('d').
		BoolVar(&ccf.Debug)
	start.Flag("roles",
		fmt.Sprintf("Comma-separated list of roles to start with [%s]", strings.Join(defaults.StartRoles, ","))).
		Short('r').
		StringVar(&ccf.Roles)
	start.Flag("pid-file",
		"Full path to the PID file. By default no PID file will be created").StringVar(&ccf.PIDFile)
	start.Flag("advertise-ip",
		"IP to advertise to clients if running behind NAT").
		IPVar(&ccf.AdvertiseIP)
	start.Flag("listen-ip",
		fmt.Sprintf("IP address to bind to [%s]", defaults.BindIP)).
		Short('l').
		IPVar(&ccf.ListenIP)
	start.Flag("auth-server",
		fmt.Sprintf("Address of the auth server [%s]", defaults.AuthConnectAddr().Addr)).
		StringVar(&ccf.AuthServerAddr)
	start.Flag("token",
		"One-time token to register with an auth server [none]").
		StringVar(&ccf.AuthToken)
	start.Flag("nodename",
		"Name of this node, defaults to hostname").
		StringVar(&ccf.NodeName)
	start.Flag("config",
		fmt.Sprintf("Path to a configuration file [%v]", defaults.ConfigFilePath)).
		Short('c').ExistingFileVar(&ccf.ConfigFile)
	start.Flag("config-string",
		"Base64 encoded configuration string").Hidden().Envar(defaults.ConfigEnvar).
		StringVar(&ccf.ConfigString)
	start.Flag("labels", "List of labels for this node").StringVar(&ccf.Labels)
	start.Flag("httpprofile",
		"[DEPRECATED] Start profiling endpoint on localhost:6060").Hidden().BoolVar(&ccf.HTTPProfileEndpoint)
	start.Flag("gops",
		"Start gops endpoint on a given address").Hidden().BoolVar(&ccf.Gops)
	start.Flag("gops-addr",
		"Specify gops addr to listen on").Hidden().StringVar(&ccf.GopsAddr)
	start.Flag("diag-addr",
		"Start diangonstic endpoint on this address").Hidden().StringVar(&ccf.DiagnosticAddr)
	start.Flag("permit-user-env",
		"Enables reading of ~/.tsh/environment when creating a session").BoolVar(&ccf.PermitUserEnvironment)

	// define start's usage info (we use kingpin's "alias" field for this)
	start.Alias(usageNotes + usageExamples)

	// define a hidden 'scp' command (it implements server-side implementation of handling
	// 'scp' requests)
	scpc.Flag("t", "sink mode (data consumer)").Short('t').Default("false").BoolVar(&scpCommand.Sink)
	scpc.Flag("f", "source mode (data producer)").Short('f').Default("false").BoolVar(&scpCommand.Source)
	scpc.Flag("v", "verbose mode").Default("false").Short('v').BoolVar(&scpCommand.Verbose)
	scpc.Flag("r", "recursive mode").Default("false").Short('r').BoolVar(&scpCommand.Recursive)
	scpc.Flag("remote-addr", "address of the remote client").StringVar(&scpCommand.RemoteAddr)
	scpc.Flag("local-addr", "local address which accepted the request").StringVar(&scpCommand.LocalAddr)
	scpc.Arg("target", "").StringVar(&scpCommand.Target)

	// parse CLI commands+flags:
	command, err := app.Parse(cmdlineArgs)
	if err != nil {
		utils.FatalError(err)
	}

	// create the default configuration:
	conf = service.MakeDefaultConfig()

	// execute the selected command unless we're running tests
	switch command {
	case start.FullCommand():
		// configuration merge: defaults -> file-based conf -> CLI conf
		if err = config.Configure(&ccf, conf); err != nil {
			utils.FatalError(err)
		}
		if !testRun {
			log.Info(conf.DebugDumpToYAML())
		}
		if ccf.HTTPProfileEndpoint {
			log.Warningf("http profile endpoint is deprecated, use gops instead")
		}
		if ccf.Gops {
			log.Debugf("starting gops agent")
			err := agent.Listen(&agent.Options{Addr: ccf.GopsAddr})
			if err != nil {
				log.Warningf("failed to start gops agent %v", err)
			}
		}
		// collect and expose diagnostic endpoint
		if ccf.DiagnosticAddr != "" {
			mux := http.NewServeMux()
			mux.Handle("/metrics", prometheus.Handler())
			mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
				roundtrip.ReplyJSON(w, http.StatusOK, map[string]interface{}{"status": "ok"})
			})
			go func() {
				err := http.ListenAndServe(ccf.DiagnosticAddr, mux)
				if err != nil {
					log.Warningf("diagnostic endpoint exited %v", err)
				}
			}()
		}
		if !testRun {
			err = onStart(conf)
		}
	case scpc.FullCommand():
		err = onSCP(&scpCommand)
	case status.FullCommand():
		err = onStatus()
	case dump.FullCommand():
		onConfigDump()
	case ver.FullCommand():
		onVersion()
	}
	if err != nil {
		utils.FatalError(err)
	}
	log.Info("teleport: clean exit")
	return command, conf
}

// onStart is the handler for "start" CLI command
func onStart(config *service.Config) error {
	srv, err := service.NewTeleport(config)
	if err != nil {
		return trace.Wrap(err, "initializing teleport")
	}
	if err := srv.Start(); err != nil {
		return trace.Wrap(err, "starting teleport")
	}

	// create the pid file
	if config.PIDFile != "" {
		f, err := os.OpenFile(config.PIDFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666)
		if err != nil {
			return trace.Wrap(err, "failed to create the PID file")
		}
		fmt.Fprintf(f, "%v", os.Getpid())
		defer f.Close()
	}
	srv.Wait()
	return nil
}

// onStatus is the handler for "status" CLI command
func onStatus() error {
	sshClient := os.Getenv("SSH_CLIENT")
	systemUser := os.Getenv("USER")
	teleportUser := os.Getenv(teleport.SSHTeleportUser)
	proxyHost := os.Getenv(teleport.SSHSessionWebproxyAddr)
	clusterName := os.Getenv(teleport.SSHTeleportClusterName)
	hostUUID := os.Getenv(teleport.SSHTeleportHostUUID)
	sid := os.Getenv(teleport.SSHSessionID)

	if sid == "" || proxyHost == "" {
		fmt.Println("You are not inside of a Teleport SSH session")
		return nil
	}

	fmt.Printf("User ID     : %s, logged in as %s from %s\n", teleportUser, systemUser, sshClient)
	fmt.Printf("Cluster Name: %s\n", clusterName)
	fmt.Printf("Host UUID   : %s\n", hostUUID)
	fmt.Printf("Session ID  : %s\n", sid)
	fmt.Printf("Session URL : https://%s/web/cluster/%v/node/%v/%v/%v\n", proxyHost, clusterName, hostUUID, systemUser, sid)

	return nil
}

// onConfigDump is the handler for "configure" CLI command
func onConfigDump() {
	sfc := config.MakeSampleFileConfig()
	fmt.Printf("%s\n%s\n", sampleConfComment, sfc.DebugDumpToYAML())
}

// onSCP implements handling of 'scp' requests on the server side. When the teleport SSH daemon
// receives an SSH "scp" request, it launches itself with 'scp' flag under the requested
// user's privileges
//
// This is the entry point of "teleport scp" call (the parent process is the teleport daemon)
func onSCP(cmd *scp.Command) (err error) {
	// get user's home dir (it serves as a default destination)
	cmd.User, err = user.Current()
	if err != nil {
		return trace.Wrap(err)
	}
	// see if the target is absolute. if not, use user's homedir to make
	// it absolute (and if the user doesn't have a homedir, use "/")
	slash := string(filepath.Separator)
	withSlash := strings.HasSuffix(cmd.Target, slash)
	if !filepath.IsAbs(cmd.Target) {
		rootDir := cmd.User.HomeDir
		if !utils.IsDir(rootDir) {
			cmd.Target = slash + cmd.Target
		} else {
			cmd.Target = filepath.Join(rootDir, cmd.Target)
			if withSlash {
				cmd.Target = cmd.Target + slash
			}
		}
	}
	if !cmd.Source && !cmd.Sink {
		return trace.Errorf("remote mode is not supported")
	}
	return trace.Wrap(cmd.Execute(&StdReadWriter{}))
}

type StdReadWriter struct {
}

func (rw *StdReadWriter) Read(b []byte) (int, error) {
	return os.Stdin.Read(b)
}

func (rw *StdReadWriter) Write(b []byte) (int, error) {
	return os.Stdout.Write(b)
}

// onVersion is the handler for "version"
func onVersion() {
	utils.PrintVersion()
}


text:
"use strict";

var applyFlags = require( "./applyFlags" );
var commandLine = require( "./commandLine" );
var evalTemplateTree = require( "./evalTemplateTree" );
var getGithubUserInfo = require( "./getGithubUserInfo" );
var getGitUserName = require( "./getGitUserName" );
var initDir = require( "./initDir" );
var readFiles = require( "./readFiles" );
var writeFiles = require( "./writeFiles" );

module.exports = function( baseDir, argv, console ) {
	var templates = readFiles( __dirname + "/../template" );
	return commandLine( baseDir, argv )
		.chain( getGitUserName )
		.chain( getGithubUserInfo )
		.progress( console.log.bind( console ) )
		.chain( function( config ) {
			return templates
				.chain( applyFlags( config.flags ) )
				.chain( evalTemplateTree( config ) )
				.chain( writeFiles( config ) );
		} )
		.success( function() {
			console.log( "initial file structure is ready." );
			console.log( "Init git & install node modules..." );
		} )
		.chain( initDir )
		.success( function() {
			console.log( "Success! Everything is properly set up." );
			console.log( "\nYou can start coding now!" );
		} )
		.failure( function( error ) {
			console.error( "ERROR: " + error );
		} );
};


text:
require "rspec/core/formatters/base_text_formatter"

module Autospec; end

class Autospec::Formatter < RSpec::Core::Formatters::BaseTextFormatter

  RSPEC_RESULT = "./tmp/rspec_result"

  def initialize(output)
    super
    FileUtils.mkdir_p("tmp") unless Dir.exists?("tmp")
  end

  def start(example_count)
    super
    File.delete(RSPEC_RESULT) if File.exists?(RSPEC_RESULT)
    @fail_file = File.open(RSPEC_RESULT,"w")
  end

  def example_passed(example)
    super
    output.print success_color(".")
  end

  def example_pending(example)
    super
    output.print pending_color("*")
  end

  def example_failed(example)
    super
    output.print failure_color("F")
    @fail_file.puts(example.metadata[:location] + " ")
    @fail_file.flush
  end

  def start_dump
    super
    output.puts
  end

  def close
    @fail_file.close
  end

end


text:
class GoogleServiceAuthError;
class OAuth2MintTokenFlowTest;

namespace net {
class URLRequestContextGetter;
}

// This class implements the OAuth2 flow to Google to mint an OAuth2
// token for the given client and the given set of scopes from the
// OAuthLogin scoped "master" OAuth2 token for the user logged in to
// Chrome.
class OAuth2MintTokenFlow
    : public OAuth2AccessTokenConsumer,
      public OAuth2MintTokenConsumer {
 public:
  class Delegate {
   public:
    virtual void OnMintTokenSuccess(const std::string& access_token) { }
    virtual void OnMintTokenFailure(const GoogleServiceAuthError& error) { }
  };

  // An interceptor for tests.
  class InterceptorForTests {
   public:
    // Returns true if the success callback should be called and false for
    // failures.
    virtual bool DoIntercept(const OAuth2MintTokenFlow* flow,
                             std::string* access_token,
                             GoogleServiceAuthError* error) = 0;
  };
  static void SetInterceptorForTests(InterceptorForTests* interceptor);

  OAuth2MintTokenFlow(net::URLRequestContextGetter* context,
                      Delegate* delegate);
  virtual ~OAuth2MintTokenFlow();

  // Start the process to mint a token.
  void Start(const std::string& login_refresh_token,
             const std::string& extension_id,
             const std::string& client_id,
             const std::vector<std::string>& scopes);

  // OAuth2AccessTokenConsumer implementation.
  virtual void OnGetTokenSuccess(const std::string& access_token) OVERRIDE;
  virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
  // OAuth2MintTokenConsumer implementation.
  virtual void OnMintTokenSuccess(const std::string& access_token) OVERRIDE;
  virtual void OnMintTokenFailure(const GoogleServiceAuthError& error) OVERRIDE;

  // Getters for various members.
  const std::string& extension_id() const { return extension_id_; }
  const std::string& client_id() const { return client_id_; }

 protected:
  // Helper to create an instance of access token fetcher.
  // Caller owns the returned instance.
  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher();

  // Helper to create an instance of mint token fetcher.
  // Caller owns the returned instance.
  virtual OAuth2MintTokenFetcher* CreateMintTokenFetcher();

 private:
  // The steps this class performs are:
  // 1. Create a login scoped access token from login scoped refresh token.
  // 2. Use login scoped access token to call the API to mint an access token
  //    for the app.
  enum State {
    INITIAL,
    FETCH_LOGIN_ACCESS_TOKEN_STARTED,
    FETCH_LOGIN_ACCESS_TOKEN_DONE,
    MINT_ACCESS_TOKEN_STARTED,
    MINT_ACCESS_TOKEN_DONE,
    ERROR_STATE
  };

  enum SetupError {
    NONE,
    AUTH_ERROR,
    INTERNAL_ERROR,
    USER_CANCELLED,

    // This is used for histograms, and should always be the last value.
    SETUP_ERROR_BOUNDARY
  };

  friend class OAuth2MintTokenFlowTest;

  // Creates an instance of URLFetcher that does not send or save cookies.
  // The URLFether's method will be GET if body is empty, POST otherwise.
  // Caller owns the returned instance.
  content::URLFetcher* CreateURLFetcher(
      const GURL& url, const std::string& body, const std::string& auth_token);
  void BeginGetLoginAccessToken();
  void EndGetLoginAccessToken(const GoogleServiceAuthError* error);
  void BeginMintAccessToken();
  void EndMintAccessToken(const GoogleServiceAuthError* error);

  void ReportSuccess();
  void ReportFailure(const GoogleServiceAuthError& error);

  static std::string GetErrorString(SetupError error);

  net::URLRequestContextGetter* context_;
  Delegate* delegate_;
  State state_;

  std::string login_refresh_token_;
  std::string extension_id_;
  std::string client_id_;
  std::vector<std::string> scopes_;

  scoped_ptr<OAuth2AccessTokenFetcher> oauth2_access_token_fetcher_;
  scoped_ptr<OAuth2MintTokenFetcher> oauth2_mint_token_fetcher_;
  std::string login_access_token_;
  std::string app_access_token_;

  DISALLOW_COPY_AND_ASSIGN(OAuth2MintTokenFlow);
};

#endif  // CHROME_COMMON_NET_GAIA_OAUTH2_MINT_TOKEN_FLOW_H_


text:
Uses [inline-style-prefixer/static](https://github.com/rofrischmann/inline-style-prefix-all) to add vendor prefixes to both property and value.

**Requires to use [alef-plugin-fallback-value](../alef-plugin-fallback-value/) afterwards** in order to resolve alternative prefix values which get returned as an array by default.

## Installation
```sh
yarn add alef-plugin-prefixer
```
You may alternatively use `npm i --save alef-plugin-prefixer`.

## Usage
Make sure to read the documentation on [how to use plugins](http://alef.js.org/docs/advanced/Plugins.html).

```javascript
import { createRenderer } from 'alef'
import prefixer from 'alef-plugin-prefixer'

const renderer = createRenderer({
  plugins: [ prefixer() ]
})
```

## Example

#### Input
```javascript
{
  display: 'flex',
  appearance: 'none'
}
```
#### Output
```javascript
{
  display: [ 'webkit-box', '-moz-box', '-ms-flexbox', '-webkit-flex', 'flex' ],
  WebkitAppearance: 'none',
  MozAppearance: 'none',
  appearance: 'none'
}
```

## License
Alef is licensed under the [MIT License](http://opensource.org/licenses/MIT).

Documentation is licensed under [Creative Common License](http://creativecommons.org/licenses/by/4.0/).

Created with ♥ by [@rofrischmann](http://rofrischmann.de) and all the great contributors.


text:
// ==========================================================================
//                 seqan - the library for sequence analysis
// ==========================================================================
// Copyright (c) 2006-2013, Knut Reinert, FU Berlin
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Knut Reinert or the FU Berlin nor the names of
//       its contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
//
// ==========================================================================
// Author: Jochen Singer <jochen.singer@fu-berlin.de>
// ==========================================================================

#ifndef TEST_INDEX_FM_SENTINEL_RANK_DICTIONARY
#define TEST_INDEX_FM_SENTINEL_RANK_DICTIONARY

#include <seqan/basic.h>
#include <seqan/sequence.h>
#include <seqan/index.h>

template <typename TAlphabetSpecPair>
class SentinelRankDictionaryTest : public seqan::Test
{
public:
    typedef typename seqan::TagListValue<TAlphabetSpecPair, 0>::Type TSentinelRankDictionarySpec;
};

typedef seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::Dna> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::Dna5> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::AminoAcid> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<char> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<unsigned char> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<signed char> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::Dna> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::Dna5> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::AminoAcid> >, Sentinel> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::Dna> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::Dna5> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<seqan::AminoAcid> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<char> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<unsigned char> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::WaveletTree<signed char> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::Dna> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::Dna5> >, Sentinels> >, seqan::TagList<
            seqan::TagList<SentinelRankDictionary<RankDictionary<seqan::SequenceBitMask<seqan::AminoAcid> >, Sentinels> >
            > > > > > >
            > > >
            > > > > > >
            > > >
        SentinelRankDictionaryTestTypes;

template <typename T>
class SentinelRankDictionaryTestCommon : public SentinelRankDictionaryTest<T>
{};

SEQAN_TYPED_TEST_CASE(SentinelRankDictionaryTestCommon, SentinelRankDictionaryTestTypes);

using namespace seqan;

template <typename TRankDictionary>
void sentinelRankDictionaryConstructor(TRankDictionary & /*tag*/)
{
	{
		TRankDictionary sentinelRankDictionary;
	}
	{
		String<typename Value<TRankDictionary>::Type> text;
        generateText(text);
		TRankDictionary sentinelRankDictionary(text);
		TRankDictionary sentinelRankDictionary2(sentinelRankDictionary);

        SEQAN_ASSERT(sentinelRankDictionary == sentinelRankDictionary2);

		for (unsigned i = 0; i < length(text); ++i)
        {
		    SEQAN_ASSERT_EQ(getValue(sentinelRankDictionary, i), text[i]);
		    SEQAN_ASSERT_EQ(getValue(sentinelRankDictionary2, i), text[i]);
        }
    }
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, Constuctor)
{
    using namespace seqan;

    typename TestFixture::TSentinelRankDictionarySpec dictionay;
    sentinelRankDictionaryConstructor(dictionay);
}

template <typename TRankDictionary>
void sentinelDictionaryClear(TRankDictionary & /*tag*/)
{
	String<typename Value<TRankDictionary>::Type> text = "ACGTNACGTNACGTN";
	TRankDictionary sentinelDictionary(text);

    clear(sentinelDictionary);

	SEQAN_ASSERT_EQ(empty(sentinelDictionary), true);
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, Clear)
{
    using namespace seqan;

    typename TestFixture::TSentinelRankDictionarySpec dictionay;
    sentinelDictionaryClear(dictionay);
}

template <typename TRankDictionary>
void sentinelDictionarySentinelPosition(TRankDictionary & /*tag*/)
{
	String<typename Value<TRankDictionary>::Type> text = "ACGTNACGTNACGTN";
	TRankDictionary sentinelDictionary(text);

    SEQAN_ASSERT_EQ(_getSentinelPosition(sentinelDictionary), length(text));

    setSentinelPosition(sentinelDictionary, 2u);
    SEQAN_ASSERT_EQ(_getSentinelPosition(sentinelDictionary), 2u);
}

template <typename TRankDictionary>
void sentinelDictionarySentinelPosition(SentinelRankDictionary<TRankDictionary, Sentinels> & /*tag*/)
{
	String<typename Value<SentinelRankDictionary<TRankDictionary, Sentinels> >::Type> text = "ACGTNACGTNACGTN";
	SentinelRankDictionary<TRankDictionary, Sentinels> sentinelDictionary(text);

    String<unsigned> sentinelPos;

    SEQAN_ASSERT_EQ(_getSentinelPosition(sentinelDictionary), sentinelPos);

    RankSupportBitString<> bitString;
    resize(bitString, length(text), 0);
    setBitTo(bitString, 2u, 1);
    setSentinelPosition(sentinelDictionary, bitString);
    String<unsigned> temp;
    appendValue(temp, 2);
    SEQAN_ASSERT_EQ(_getSentinelPosition(sentinelDictionary), temp);
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, SentinelPosition)
{
    using namespace seqan;

    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelDictionarySentinelPosition(dictionay);
    }
}

template <typename TRankDictionary>
void sentinelRankDictionaryEmpty(TRankDictionary & /*tag*/)
{
    {
        TRankDictionary sentinelRankDictionary;

        SEQAN_ASSERT_EQ(empty(sentinelRankDictionary), true);
    }
    {
        String<typename Value<TRankDictionary>::Type> text = "ACGTNACGTNACGTN";
        TRankDictionary sentinelRankDictionary(text);

        SEQAN_ASSERT_EQ(empty(sentinelRankDictionary), false);
    }
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, Empty)
{
    using namespace seqan;

    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryEmpty(dictionay);
    }
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryEmpty(dictionay);
    }
}

template <typename TRankDictionary>
void sentinelRankDictionaryGetValue(TRankDictionary & /*tag*/)
{
    String<typename Value<TRankDictionary>::Type> text;
    generateText(text);

    TRankDictionary sentinelRankDictionary(text);

    for (unsigned i = 0; i < length(text); ++i)
    {
        SEQAN_ASSERT_EQ(getValue(sentinelRankDictionary, i), text[i]);
    }
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, GetValue)
{
    using namespace seqan;

    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryGetValue(dictionay);
    }
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryGetValue(dictionay);
    }
}

template <typename TRankDictionary>
void sentinelRankDictionaryGetFibre(TRankDictionary & /*tag*/)
{
	String<typename Value<TRankDictionary>::Type> text = "ACGTNACGTNACGTN";
	TRankDictionary sentinelRankDictionary(text);

    typename Fibre<TRankDictionary, FibreRankDictionary>::Type & dictionary = getFibre(sentinelRankDictionary, FibreRankDictionary());

	SEQAN_ASSERT_EQ(empty(getFibre(sentinelRankDictionary, FibreRankDictionary())), false);

    clear(dictionary);

	SEQAN_ASSERT_EQ(empty(getFibre(sentinelRankDictionary, FibreRankDictionary())), true);
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, GetFibre)
{
    using namespace seqan;

    using namespace seqan;
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryGetFibre(dictionay);
    }
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryGetFibre(dictionay);
    }
}

template <typename TRankDictionary>
void sentinelRankDictionaryCountOcc(TRankDictionary & /*tag*/)
{
    typedef typename Value<TRankDictionary>::Type TChar;
    String<TChar> text;
    generateText(text);
    text[0] = 'A';

    resize(text, 1000);

    TRankDictionary sentinelRankDictionary(text);
    setSentinelSubstitute(sentinelRankDictionary, 'A');
    setSentinelPosition(sentinelRankDictionary, 0);

    for (int i = MinValue<TChar>::VALUE; i <= MaxValue<TChar>::VALUE; ++i)
    {
        unsigned counter = 0;
        for (unsigned j = 0; j < length(text); ++j)
        {
            if (text[j] == (TChar)i)
                ++counter;
            if ((TChar)i == 'A' && j == 0)
                --counter;
            SEQAN_ASSERT_EQ(countOccurrences(sentinelRankDictionary, (TChar)i, j), counter);
        }
    }
}
template <typename TRankDictionary>
void sentinelRankDictionaryCountOcc(SentinelRankDictionary<TRankDictionary, Sentinels> & /*tag*/)
{
    typedef typename Value<TRankDictionary>::Type TChar;
    String<TChar> text;
    generateText(text);
    text[0] = 'A';
    text[99] = 'A';
    text[999] = 'A';

    resize(text, 1000);

    SentinelRankDictionary<TRankDictionary, Sentinels> sentinelRankDictionary(text);
    setSentinelSubstitute(sentinelRankDictionary, 'A');
    setBitTo(sentinelRankDictionary.sentinelPosition, 0, 1);
    setBitTo(sentinelRankDictionary.sentinelPosition, 99, 1);
    setBitTo(sentinelRankDictionary.sentinelPosition, 999, 1);
    _updateRanks(sentinelRankDictionary.sentinelPosition);

    for (int i = MinValue<TChar>::VALUE; i <= MaxValue<TChar>::VALUE; ++i)
    {
        unsigned counter = 0;
        for (unsigned j = 0; j < length(text); ++j)
        {
            if (text[j] == (TChar)i)
                ++counter;
            if ((TChar)i == 'A' && (j == 0 || j == 99 || j == 999))
                --counter;
            SEQAN_ASSERT_EQ(countOccurrences(sentinelRankDictionary, (TChar)i, j), counter);
        }
    }
}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, CountOcc)
{
    using namespace seqan;
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryCountOcc(dictionay);
    }
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryCountOcc(dictionay);
    }
}

// // template <typename TString, typename TSpec>
// // void sentinelRankDictionaryCountOcc(WaveletTree<TString, FmiDollarSubstituted<TSpec> > & /*tag*/)
// // {
// //     typedef WaveletTree<TString, FmiDollarSubstituted<TSpec> > TRankDictionary;
// // 	typedef typename Fibre<TRankDictionary, FibreTreeStructure>::Type TRankDictionaryStructure;
// // 	typedef typename Fibre<TRankDictionaryStructure, FibreTreeStructureEncoding>::Type TRankDictionaryVertices;
// // 	typedef typename Value<TRankDictionaryVertices>::Type TRankDictionaryVertex;
// // 	typedef typename Value<TRankDictionary>::Type TChar;
// // 	typedef typename Value<TRankDictionaryVertex, 2>::Type TPos;
// //
// // 	{
// // 		String<TChar> text;
// //  		generateText(text);
// //  		resize(text, 1000);
// //
// // 		TRankDictionary sentinelRankDictionary(text);
// // 		setDollarSubstitute(sentinelRankDictionary, getCharacter(sentinelRankDictionary, 0u));
// // 		setDollarPosition(sentinelRankDictionary, 0u);
// //
// //         for (int i = MinValue<TChar>::VALUE; i <= MaxValue<TChar>::VALUE; ++i)
// //         {
// //             unsigned counter = 0;
// //             for (unsigned j = 0; j < length(text); ++j)
// //             {
// //                 if(text[j] == (TChar)i)
// //                 {
// //                     ++counter;
// //                     if(text[j] == getDollarSubstitute(sentinelRankDictionary) && j == getDollarPosition(sentinelRankDictionary))
// //                         --counter;
// //                 }
// // 		        SEQAN_ASSERT_EQ(countOccurrences(sentinelRankDictionary, (TChar)i, j), counter);
// //             }
// //         }
// //     }
// // }
//

template <typename TRankDictionary>
void sentinelRankDictionaryOpenSave(TRankDictionary & /*tag*/)
{
	String<typename Value<TRankDictionary>::Type> text;
    generateText(text);
    resize(text, 1000);

    CharString tempFilename = SEQAN_TEMP_FILENAME();

    TRankDictionary sentinelRankDictionary(text);
    sentinelRankDictionary.sentinelSubstitute = 'A';
    save(sentinelRankDictionary, toCString(tempFilename));

    TRankDictionary sentinelRankDictionaryOpen;
    open(sentinelRankDictionaryOpen, toCString(tempFilename));
    SEQAN_ASSERT(sentinelRankDictionary == sentinelRankDictionaryOpen);
}

template <typename TValue>
void sentinelRankDictionaryOpenSave(RankDictionary<SequenceBitMask<TValue> > & /*tag*/) {}

SEQAN_TYPED_TEST(SentinelRankDictionaryTestCommon, OpenSave)
{
    using namespace seqan;
    {
        typename TestFixture::TSentinelRankDictionarySpec dictionay;
        sentinelRankDictionaryOpenSave(dictionay);
    }
}

//
// SEQAN_DEFINE_TEST(test_wavelet_tree_clear)
// {
//     using namespace seqan;
//
//     RankDictionary<WaveletTree<String<Dna> > > dnaTag;
//     WaveletTree<String<Dna5>, void> dna5Tag;
//     WaveletTree<String<AminoAcid>, void> asTag;
//     WaveletTree<String<char>, void> charTag;
//     WaveletTree<String<unsigned char>, void> uCharTag;
//     sentinelRankDictionaryClear(dnaTag);
//     sentinelRankDictionaryClear(dna5Tag);
//     sentinelRankDictionaryClear(asTag);
//     sentinelRankDictionaryClear(charTag);
//     sentinelRankDictionaryClear(uCharTag);
// }
//
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_constructor)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, void> dnaTag;
//     WaveletTree<String<Dna5>, void> dna5Tag;
//     WaveletTree<String<AminoAcid>, void> asTag;
//     WaveletTree<String<char>, void> charTag;
//     WaveletTree<String<unsigned char>, void> uCharTag;
//     WaveletTree<String<unsigned char>, FmiDollarSubstituted<SingleDollar<void> > > uCharDollarTag;
//     sentinelRankDictionaryConstructor(dnaTag);
//     sentinelRankDictionaryConstructor(dna5Tag);
//     sentinelRankDictionaryConstructor(asTag);
//     sentinelRankDictionaryConstructor(charTag);
//     sentinelRankDictionaryConstructor(uCharTag);
//     sentinelRankDictionaryConstructor(uCharDollarTag);
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_dollar_position)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, FmiDollarSubstituted<SingleDollar<void> > > dnaTag;
//     WaveletTree<String<Dna5>, FmiDollarSubstituted<SingleDollar<void> > > dna5Tag;
//     WaveletTree<String<AminoAcid>, FmiDollarSubstituted<SingleDollar<void> > > asTag;
//     WaveletTree<String<char>, FmiDollarSubstituted<SingleDollar<void> > > charTag;
//     WaveletTree<String<unsigned char>, FmiDollarSubstituted<SingleDollar<void> > > uCharTag;
//     sentinelRankDictionaryDollarPosition(dnaTag);
//     sentinelRankDictionaryDollarPosition(dna5Tag);
//     sentinelRankDictionaryDollarPosition(asTag);
//     sentinelRankDictionaryDollarPosition(charTag);
//     sentinelRankDictionaryDollarPosition(uCharTag);
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_dollar_substitute)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, FmiDollarSubstituted<SingleDollar<void> > > dnaTag;
//     WaveletTree<String<Dna5>, FmiDollarSubstituted<SingleDollar<void> > > dna5Tag;
//     WaveletTree<String<AminoAcid>, FmiDollarSubstituted<SingleDollar<void> > > asTag;
//     WaveletTree<String<char>, FmiDollarSubstituted<SingleDollar<void> > > charTag;
//     WaveletTree<String<unsigned char>, FmiDollarSubstituted<SingleDollar<void> > > uCharTag;
//     sentinelRankDictionaryDollarSubstitute(dnaTag);
//     sentinelRankDictionaryDollarSubstitute(dna5Tag);
//     sentinelRankDictionaryDollarSubstitute(asTag);
//     sentinelRankDictionaryDollarSubstitute(charTag);
//     sentinelRankDictionaryDollarSubstitute(uCharTag);
// }
//
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_empty)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, void> dnaTag;
//     WaveletTree<String<Dna5>, void> dna5Tag;
//     WaveletTree<String<AminoAcid>, void> asTag;
//     WaveletTree<String<char>, void> charTag;
//     WaveletTree<String<unsigned char>, void> uCharTag;
//     sentinelRankDictionaryEmpty(dnaTag);
//     sentinelRankDictionaryEmpty(dna5Tag);
//     sentinelRankDictionaryEmpty(asTag);
//     sentinelRankDictionaryEmpty(charTag);
//     sentinelRankDictionaryEmpty(uCharTag);
// }
//
//
//
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_get_character)
// {
//     using namespace seqan;
//     {
//         WaveletTree<String<Dna>, void> dnaTag;
//         WaveletTree<String<Dna5>, void> dna5Tag;
//         WaveletTree<String<AminoAcid>, void> asTag;
//         WaveletTree<String<signed char>, void> charTag;
//         WaveletTree<String<unsigned char>, void> uCharTag;
//
//         sentinelRankDictionaryGetCharacter(dnaTag);
//         sentinelRankDictionaryGetCharacter(dna5Tag);
//         sentinelRankDictionaryGetCharacter(asTag);
//         sentinelRankDictionaryGetCharacter(charTag);
//         sentinelRankDictionaryGetCharacter(uCharTag);
//     }
//     {
//         WaveletTree<String<Dna>, FmiDollarSubstituted<SingleDollar<void> > > dnaTag;
//         WaveletTree<String<Dna5>, FmiDollarSubstituted<SingleDollar<void> > > dna5Tag;
//         WaveletTree<String<AminoAcid>, FmiDollarSubstituted<SingleDollar<void> > > asTag;
//         WaveletTree<String<signed char>, FmiDollarSubstituted<SingleDollar<void> > > charTag;
//         WaveletTree<String<unsigned char>, FmiDollarSubstituted<SingleDollar<void> > > uCharTag;
//
//         sentinelRankDictionaryGetCharacter(dnaTag);
//         sentinelRankDictionaryGetCharacter(dna5Tag);
//         sentinelRankDictionaryGetCharacter(asTag);
//         sentinelRankDictionaryGetCharacter(charTag);
//         sentinelRankDictionaryGetCharacter(uCharTag);
//     }
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_get_fibre)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, void> dnaTag;
//     WaveletTree<String<Dna5>, void> dna5Tag;
//     WaveletTree<String<AminoAcid>, void> asTag;
//     WaveletTree<String<char>, void> charTag;
//     WaveletTree<String<unsigned char>, void> uCharTag;
//     sentinelRankDictionaryGetFibre(dnaTag);
//     sentinelRankDictionaryGetFibre(dna5Tag);
//     sentinelRankDictionaryGetFibre(asTag);
//     sentinelRankDictionaryGetFibre(charTag);
//     sentinelRankDictionaryGetFibre(uCharTag);
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_get_occ)
// {
//     using namespace seqan;
//
//     {
//         WaveletTree<String<Dna>, void> dnaTag;
//         WaveletTree<String<Dna5>, void> dna5Tag;
//         WaveletTree<String<AminoAcid>, void> asTag;
//         WaveletTree<String<signed char>, void> charTag;
//         WaveletTree<String<unsigned char>, void> uCharTag;
//
//         sentinelRankDictionaryCountOcc(dnaTag);
//         sentinelRankDictionaryCountOcc(dna5Tag);
//         sentinelRankDictionaryCountOcc(asTag);
//         sentinelRankDictionaryCountOcc(charTag);
//         sentinelRankDictionaryCountOcc(uCharTag);
//     }
// //     {
// //         WaveletTree<String<Dna>, FmiDollarSubstituted<SingleDollar<void> > > dnaTag;
// //         WaveletTree<String<Dna5>, FmiDollarSubstituted<SingleDollar<void> > > dna5Tag;
// //         WaveletTree<String<AminoAcid>, FmiDollarSubstituted<SingleDollar<void> > > asTag;
// //         WaveletTree<String<signed char>, FmiDollarSubstituted<SingleDollar<void> > > charTag;
// //         WaveletTree<String<unsigned char>, FmiDollarSubstituted<SingleDollar<void> > > uCharTag;
// //
// //         sentinelRankDictionaryCountOcc(dnaTag);
// //         sentinelRankDictionaryCountOcc(dna5Tag);
// //         sentinelRankDictionaryCountOcc(asTag);
// //         sentinelRankDictionaryCountOcc(charTag);
// //         sentinelRankDictionaryCountOcc(uCharTag);
// //     }
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_fill_wavelet_tree_)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna>, void> dnaTag;
//     WaveletTree<String<Dna5>, void> dna5Tag;
//     WaveletTree<String<AminoAcid>, void> asTag;
//     WaveletTree<String<signed char>, void> charTag;
//     WaveletTree<String<unsigned char>, void> uCharTag;
//
//     _sentinelRankDictionaryFillWaveletTree(dnaTag);
//     _sentinelRankDictionaryFillWaveletTree(dna5Tag);
//     _sentinelRankDictionaryFillWaveletTree(asTag);
//     _sentinelRankDictionaryFillWaveletTree(charTag);
//     _sentinelRankDictionaryFillWaveletTree(uCharTag);
// }
//
// SEQAN_DEFINE_TEST(test_wavelet_tree_open_save)
// {
//     using namespace seqan;
//
//     WaveletTree<String<Dna5>, void> dna5Tag;
//
//     sentinelRankDictionaryOpenSave(dna5Tag);
// }

#endif  // TEST_INDEX_FM_SENTINEL_RANK_DICTIONARY


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Bull. Soc. Path. Exot. 12: 350 (1924)

#### Original name
Microsporum muris Gluge & d'Ukedem ex Guég.

### Remarks
null


text:
package dms_enterprise

//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.
//
// Code generated by Alibaba Cloud SDK Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is regenerated.

import (
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
)

// ModifyDataCorrectExecSQL invokes the dms_enterprise.ModifyDataCorrectExecSQL API synchronously
func (client *Client) ModifyDataCorrectExecSQL(request *ModifyDataCorrectExecSQLRequest) (response *ModifyDataCorrectExecSQLResponse, err error) {
	response = CreateModifyDataCorrectExecSQLResponse()
	err = client.DoAction(request, response)
	return
}

// ModifyDataCorrectExecSQLWithChan invokes the dms_enterprise.ModifyDataCorrectExecSQL API asynchronously
func (client *Client) ModifyDataCorrectExecSQLWithChan(request *ModifyDataCorrectExecSQLRequest) (<-chan *ModifyDataCorrectExecSQLResponse, <-chan error) {
	responseChan := make(chan *ModifyDataCorrectExecSQLResponse, 1)
	errChan := make(chan error, 1)
	err := client.AddAsyncTask(func() {
		defer close(responseChan)
		defer close(errChan)
		response, err := client.ModifyDataCorrectExecSQL(request)
		if err != nil {
			errChan <- err
		} else {
			responseChan <- response
		}
	})
	if err != nil {
		errChan <- err
		close(responseChan)
		close(errChan)
	}
	return responseChan, errChan
}

// ModifyDataCorrectExecSQLWithCallback invokes the dms_enterprise.ModifyDataCorrectExecSQL API asynchronously
func (client *Client) ModifyDataCorrectExecSQLWithCallback(request *ModifyDataCorrectExecSQLRequest, callback func(response *ModifyDataCorrectExecSQLResponse, err error)) <-chan int {
	result := make(chan int, 1)
	err := client.AddAsyncTask(func() {
		var response *ModifyDataCorrectExecSQLResponse
		var err error
		defer close(result)
		response, err = client.ModifyDataCorrectExecSQL(request)
		callback(response, err)
		result <- 1
	})
	if err != nil {
		defer close(result)
		callback(nil, err)
		result <- 0
	}
	return result
}

// ModifyDataCorrectExecSQLRequest is the request struct for api ModifyDataCorrectExecSQL
type ModifyDataCorrectExecSQLRequest struct {
	*requests.RpcRequest
	ExecSQL string           `position:"Query" name:"ExecSQL"`
	Tid     requests.Integer `position:"Query" name:"Tid"`
	OrderId requests.Integer `position:"Query" name:"OrderId"`
}

// ModifyDataCorrectExecSQLResponse is the response struct for api ModifyDataCorrectExecSQL
type ModifyDataCorrectExecSQLResponse struct {
	*responses.BaseResponse
	RequestId    string `json:"RequestId" xml:"RequestId"`
	Success      bool   `json:"Success" xml:"Success"`
	ErrorMessage string `json:"ErrorMessage" xml:"ErrorMessage"`
	ErrorCode    string `json:"ErrorCode" xml:"ErrorCode"`
}

// CreateModifyDataCorrectExecSQLRequest creates a request to invoke ModifyDataCorrectExecSQL API
func CreateModifyDataCorrectExecSQLRequest() (request *ModifyDataCorrectExecSQLRequest) {
	request = &ModifyDataCorrectExecSQLRequest{
		RpcRequest: &requests.RpcRequest{},
	}
	request.InitWithApiInfo("dms-enterprise", "2018-11-01", "ModifyDataCorrectExecSQL", "dms-enterprise", "openAPI")
	request.Method = requests.POST
	return
}

// CreateModifyDataCorrectExecSQLResponse creates a response to parse from ModifyDataCorrectExecSQL response
func CreateModifyDataCorrectExecSQLResponse() (response *ModifyDataCorrectExecSQLResponse) {
	response = &ModifyDataCorrectExecSQLResponse{
		BaseResponse: &responses.BaseResponse{},
	}
	return
}