//
// NuGetProjectContext.cs
//
// Author:
//       Matt Ward <matt.ward@xamarin.com>
//
// Copyright (c) 2016 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

using System;
using System.Xml.Linq;
using NuGet.Configuration;
using NuGet.Common;
using NuGet.PackageManagement;
using NuGet.Packaging;
using NuGet.ProjectManagement;
using NuGet.Packaging.PackageExtraction;
using NuGet.Packaging.Signing;

namespace MonoDevelop.PackageManagement
{
	internal class NuGetProjectContext : INuGetProjectContext
	{
		IPackageManagementEvents packageManagementEvents;
		IDEExecutionContext executionContext;
		ISettings settings;
		PackageExtractionContext packageExtractionContext;
		PackageManagementLogger logger;

		public NuGetProjectContext (ISettings settings)
		{
			this.settings = settings;
			packageManagementEvents = PackageManagementServices.PackageManagementEvents;
			var commonOperations = new MonoDevelopCommonOperations ();
			executionContext = new IDEExecutionContext (commonOperations);
			logger = new PackageManagementLogger (packageManagementEvents);
		}

		public ExecutionContext ExecutionContext {
			get { return executionContext; }
		}

		public NuGetActionType ActionType { get; set; }
		public XDocument OriginalPackagesConfig { get; set; }
		public Guid OperationId { get; set; }

		public ISourceControlManagerProvider SourceControlManagerProvider {
			get { return null; }
		}

		public void Log (MessageLevel level, string message, params object [] args)
		{
			packageManagementEvents.OnPackageOperationMessageLogged (level, message, args);
		}

		public void ReportError (string message)
		{
			packageManagementEvents.OnPackageOperationMessageLogged (MessageLevel.Error, message);
		}

		public FileConflictAction? FileConflictResolution { get; set; }

		public FileConflictAction ResolveFileConflict (string message)
		{
			if (FileConflictResolution.HasValue && FileConflictResolution != FileConflictAction.PromptUser)
				return FileConflictResolution.Value;

			return packageManagementEvents.OnResolveFileConflict (message);
		}

		public void Log (ILogMessage message)
		{
			logger.Log (message);
		}

		public void ReportError (ILogMessage message)
		{
			logger.Log (message);
		}

		public PackageExtractionContext PackageExtractionContext {
			get {
				if (packageExtractionContext == null) {
					var loggerAdapter = new LoggerAdapter (this);
					packageExtractionContext = new PackageExtractionContext (
						PackageSaveMode.Defaultv2,
						PackageExtractionBehavior.XmlDocFileSaveMode,
						ClientPolicyContext.GetClientPolicy (settings, loggerAdapter),
						loggerAdapter);
				}
				return packageExtractionContext;
			}
			set { packageExtractionContext = value; }
		}
	}
}


/**
 * External dependencies
 */
import {
	BlockContainer,
	ButtonControlsHelper,
	ContentAlignControl,
	DesignPanelBody,
	PanelAdvancedSettings,
	ProControlButton,
	ButtonEditHelper,
	AdvancedRangeControl,
} from '~stackable/components'
import {
	withBlockStyles,
	withContentAlignReseter,
	withGoogleFont,
	withSetAttributeHook,
	withTabbedInspector,
	withUniqueClass,
	withClickOpenInspector,
} from '~stackable/higher-order'
import { createButtonAttributeNames } from '~stackable/util'

/**
 * Internal dependencies
 */
import createStyles from './style'
import ImageDesignBasic from './images/basic.png'
import ImageDesignFullWidth from './images/fullwidth.png'
import ImageDesignGrouped1 from './images/grouped-1.png'
import ImageDesignGrouped2 from './images/grouped-2.png'
import ImageDesignSpread from './images/spread.png'

/**
 * WordPress dependencies
 */
import { Fragment } from '@wordpress/element'
import { compose } from '@wordpress/compose'
import classnames from 'classnames'
import {
	PanelBody, SelectControl,
} from '@wordpress/components'
import {
	__, _x, sprintf,
} from '@wordpress/i18n'
import { i18n, showProNotice } from 'stackable'
import { addFilter, applyFilters } from '@wordpress/hooks'

addFilter( 'stackable.button.edit.inspector.layout.before', 'stackable/button', ( output, props ) => {
	const { setAttributes } = props
	const {
		design = 'basic',
	} = props.attributes

	return (
		<Fragment>
			{ output }
			<DesignPanelBody
				initialOpen={ true }
				selected={ design }
				options={ applyFilters( 'stackable.button.edit.layouts', [
					{
						label: __( 'Basic', i18n ), value: 'basic', image: ImageDesignBasic,
					},
					{
						label: __( 'Spread', i18n ), value: 'spread', image: ImageDesignSpread,
					},
					{
						label: __( 'Full Width', i18n ), value: 'fullwidth', image: ImageDesignFullWidth,
					},
					{
						label: sprintf( _x( '%s %d', 'Nth Title', i18n ), __( 'Grouped', i18n ), 1 ), value: 'grouped-1', image: ImageDesignGrouped1,
					},
					{
						label: sprintf( _x( '%s %d', 'Nth Title', i18n ), __( 'Grouped', i18n ), 2 ), value: 'grouped-2', image: ImageDesignGrouped2,
					},
				] ) }
				onChange={ design => setAttributes( { design } ) }
			>
				{ showProNotice && <ProControlButton /> }
			</DesignPanelBody>
		</Fragment>
	)
} )

addFilter( 'stackable.button.edit.inspector.style.before', 'stackable/button', ( output, props ) => {
	const { setAttributes } = props
	const {
		borderRadius = '',
		collapseOn = '',
		showButton2 = false,
		showButton3 = false,
	} = props.attributes

	return (
		<Fragment>
			{ output }
			<PanelBody title={ __( 'General', i18n ) } initialOpen={ false }>
				<AdvancedRangeControl
					label={ __( 'Border Radius', i18n ) }
					value={ borderRadius }
					min="0"
					max="70"
					onChange={ borderRadius => {
						const attrs = {
							button1BorderRadius: borderRadius,
							borderRadius,
						}
						if ( showButton2 ) {
							attrs.button2BorderRadius = borderRadius
						}
						if ( showButton3 ) {
							attrs.button3BorderRadius = borderRadius
						}
						setAttributes( attrs )
					} }
					allowReset={ true }
					placeholder="12"
					className="ugb--help-tip-button-border-radius"
				/>
				<ContentAlignControl
					setAttributes={ setAttributes }
					blockAttributes={ props.attributes }
				/>
				<SelectControl
					label={ __( 'Collapse Buttons On', i18n ) }
					value={ collapseOn }
					options={ [
						{ value: '', label: __( 'Don\'t collapse', i18n ) },
						{ value: 'tablet', label: __( 'Tablet', i18n ) },
						{ value: 'mobile', label: __( 'Mobile', i18n ) },
					] }
					onChange={ collapseOn => setAttributes( { collapseOn } ) }
					className="ugb--help-tip-button-collapse"
				/>
			</PanelBody>
			<PanelAdvancedSettings
				title={ sprintf( _x( '%s #%d', 'Panel title', i18n ), __( 'Button', i18n ), 1 ) }
				initialOpen={ true }
				id="button1"
			>
				<ButtonControlsHelper
					attrNameTemplate="button1%s"
					setAttributes={ setAttributes }
					blockAttributes={ props.attributes }
					placeholder="21"
				/>
			</PanelAdvancedSettings>
			<PanelAdvancedSettings
				title={ sprintf( _x( '%s #%d', 'Panel title', i18n ), __( 'Button', i18n ), 2 ) }
				id="button2"
				checked={ showButton2 }
				onChange={ showButton2 => setAttributes( { showButton2 } ) }
				toggleOnSetAttributes={ createButtonAttributeNames( 'button2%s' ) }
				toggleAttributeName="showButton2"
			>
				<ButtonControlsHelper
					attrNameTemplate="button2%s"
					setAttributes={ setAttributes }
					blockAttributes={ props.attributes }
					placeholder="21"
				/>
			</PanelAdvancedSettings>
			<PanelAdvancedSettings
				title={ sprintf( _x( '%s #%d', 'Panel title', i18n ), __( 'Button', i18n ), 3 ) }
				id="button3"
				checked={ showButton3 }
				onChange={ showButton3 => setAttributes( { showButton3 } ) }
				toggleOnSetAttributes={ createButtonAttributeNames( 'button3%s' ) }
				toggleAttributeName="showButton3"
			>
				<ButtonControlsHelper
					attrNameTemplate="button3%s"
					setAttributes={ setAttributes }
					blockAttributes={ props.attributes }
					placeholder="21"
				/>
			</PanelAdvancedSettings>
		</Fragment>
	)
} )

const edit = props => {
	const {
		setAttributes, className, attributes,
	} = props
	const {
		design = 'plain',
		tabletContentAlign = '',
		mobileContentAlign = '',
		collapseOn = '',
		showButton2 = false,
		showButton3 = false,
	} = attributes

	const mainClasses = classnames( [
		className,
	], applyFilters( 'stackable.button.mainclasses', {
		'ugb-button--tablet-aligned': tabletContentAlign !== '',
		'ugb-button--mobile-aligned': mobileContentAlign !== '',
		[ `ugb-button--collapse-${ collapseOn }` ]: collapseOn,
		[ `ugb-button--design-${ design }` ]: design !== 'basic',
	}, design, props ) )

	return (
		<BlockContainer.Edit className={ mainClasses } blockProps={ props } render={ () => (
			<Fragment>
				<ButtonEditHelper
					className="ugb-button1"
					attrNameTemplate="button1%s"
					setAttributes={ setAttributes }
					blockAttributes={ props.attributes }
				/>
				{ showButton2 &&
					<ButtonEditHelper
						className="ugb-button2"
						attrNameTemplate="button2%s"
						setAttributes={ setAttributes }
						blockAttributes={ props.attributes }
					/>
				}
				{ showButton3 &&
					<ButtonEditHelper
						className="ugb-button3"
						attrNameTemplate="button3%s"
						setAttributes={ setAttributes }
						blockAttributes={ props.attributes }
					/>
				}
			</Fragment>
		) } />
	)
}

export default compose(
	withUniqueClass,
	withSetAttributeHook,
	withGoogleFont,
	withTabbedInspector(),
	withContentAlignReseter(),
	withBlockStyles( createStyles, { editorMode: true } ),
	withClickOpenInspector( [
		[ '.ugb-button1', 'button1' ],
		[ '.ugb-button2', 'button2' ],
		[ '.ugb-button3', 'button3' ],
	] )
)( edit )


/*
 * DLCI		Implementation of Frame Relay protocol for Linux, according to
 *		RFC 1490.  This generic device provides en/decapsulation for an
 *		underlying hardware driver.  Routes & IPs are assigned to these
 *		interfaces.  Requires 'dlcicfg' program to create usable
 *		interfaces, the initial one, 'dlci' is for IOCTL use only.
 *
 * Version:	@(#)dlci.c	0.35	4 Jan 1997
 *
 * Author:	Mike McLagan <mike.mclagan@linux.org>
 *
 * Changes:
 *
 *		0.15	Mike Mclagan	Packet freeing, bug in kmalloc call
 *					DLCI_RET handling
 *		0.20	Mike McLagan	More conservative on which packets
 *					are returned for retry and which are
 *					are dropped.  If DLCI_RET_DROP is
 *					returned from the FRAD, the packet is
 *				 	sent back to Linux for re-transmission
 *		0.25	Mike McLagan	Converted to use SIOC IOCTL calls
 *		0.30	Jim Freeman	Fixed to allow IPX traffic
 *		0.35	Michael Elizabeth	Fixed incorrect memcpy_fromfs
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/if_frad.h>
#include <linux/bitops.h>

#include <net/sock.h>

#include <asm/io.h>
#include <asm/dma.h>
#include <asm/uaccess.h>

static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org";

static LIST_HEAD(dlci_devs);

static void dlci_setup(struct net_device *);

/*
 * these encapsulate the RFC 1490 requirements as well as
 * deal with packet transmission and reception, working with
 * the upper network layers
 */

static int dlci_header(struct sk_buff *skb, struct net_device *dev,
		       unsigned short type, const void *daddr,
		       const void *saddr, unsigned len)
{
	struct frhdr		hdr;
	unsigned int		hlen;
	char			*dest;

	hdr.control = FRAD_I_UI;
	switch (type)
	{
		case ETH_P_IP:
			hdr.IP_NLPID = FRAD_P_IP;
			hlen = sizeof(hdr.control) + sizeof(hdr.IP_NLPID);
			break;

		/* feel free to add other types, if necessary */

		default:
			hdr.pad = FRAD_P_PADDING;
			hdr.NLPID = FRAD_P_SNAP;
			memset(hdr.OUI, 0, sizeof(hdr.OUI));
			hdr.PID = htons(type);
			hlen = sizeof(hdr);
			break;
	}

	dest = skb_push(skb, hlen);
	if (!dest)
		return 0;

	memcpy(dest, &hdr, hlen);

	return hlen;
}

static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
{
	struct frhdr		*hdr;
	int					process, header;

	if (!pskb_may_pull(skb, sizeof(*hdr))) {
		netdev_notice(dev, "invalid data no header\n");
		dev->stats.rx_errors++;
		kfree_skb(skb);
		return;
	}

	hdr = (struct frhdr *) skb->data;
	process = 0;
	header = 0;
	skb->dev = dev;

	if (hdr->control != FRAD_I_UI)
	{
		netdev_notice(dev, "Invalid header flag 0x%02X\n",
			      hdr->control);
		dev->stats.rx_errors++;
	}
	else
		switch (hdr->IP_NLPID)
		{
			case FRAD_P_PADDING:
				if (hdr->NLPID != FRAD_P_SNAP)
				{
					netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
						      hdr->NLPID);
					dev->stats.rx_errors++;
					break;
				}

				if (hdr->OUI[0] + hdr->OUI[1] + hdr->OUI[2] != 0)
				{
					netdev_notice(dev, "Unsupported organizationally unique identifier 0x%02X-%02X-%02X\n",
						      hdr->OUI[0],
						      hdr->OUI[1],
						      hdr->OUI[2]);
					dev->stats.rx_errors++;
					break;
				}

				/* at this point, it's an EtherType frame */
				header = sizeof(struct frhdr);
				/* Already in network order ! */
				skb->protocol = hdr->PID;
				process = 1;
				break;

			case FRAD_P_IP:
				header = sizeof(hdr->control) + sizeof(hdr->IP_NLPID);
				skb->protocol = htons(ETH_P_IP);
				process = 1;
				break;

			case FRAD_P_SNAP:
			case FRAD_P_Q933:
			case FRAD_P_CLNP:
				netdev_notice(dev, "Unsupported NLPID 0x%02X\n",
					      hdr->pad);
				dev->stats.rx_errors++;
				break;

			default:
				netdev_notice(dev, "Invalid pad byte 0x%02X\n",
					      hdr->pad);
				dev->stats.rx_errors++;
				break;
		}

	if (process)
	{
		/* we've set up the protocol, so discard the header */
		skb_reset_mac_header(skb);
		skb_pull(skb, header);
		dev->stats.rx_bytes += skb->len;
		netif_rx(skb);
		dev->stats.rx_packets++;
	}
	else
		dev_kfree_skb(skb);
}

static netdev_tx_t dlci_transmit(struct sk_buff *skb, struct net_device *dev)
{
	struct dlci_local *dlp = netdev_priv(dev);

	if (skb) {
		struct netdev_queue *txq = skb_get_tx_queue(dev, skb);
		netdev_start_xmit(skb, dlp->slave, txq, false);
	}
	return NETDEV_TX_OK;
}

static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, int get)
{
	struct dlci_conf	config;
	struct dlci_local	*dlp;
	struct frad_local	*flp;
	int			err;

	dlp = netdev_priv(dev);

	flp = netdev_priv(dlp->slave);

	if (!get)
	{
		if (copy_from_user(&config, conf, sizeof(struct dlci_conf)))
			return -EFAULT;
		if (config.flags & ~DLCI_VALID_FLAGS)
			return -EINVAL;
		memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
		dlp->configured = 1;
	}

	err = (*flp->dlci_conf)(dlp->slave, dev, get);
	if (err)
		return err;

	if (get)
	{
		if (copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf)))
			return -EFAULT;
	}

	return 0;
}

static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct dlci_local *dlp;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	dlp = netdev_priv(dev);

	switch (cmd)
	{
		case DLCI_GET_SLAVE:
			if (!*(short *)(dev->dev_addr))
				return -EINVAL;

			strncpy(ifr->ifr_slave, dlp->slave->name, sizeof(ifr->ifr_slave));
			break;

		case DLCI_GET_CONF:
		case DLCI_SET_CONF:
			if (!*(short *)(dev->dev_addr))
				return -EINVAL;

			return dlci_config(dev, ifr->ifr_data, cmd == DLCI_GET_CONF);

		default:
			return -EOPNOTSUPP;
	}
	return 0;
}

static int dlci_change_mtu(struct net_device *dev, int new_mtu)
{
	struct dlci_local *dlp = netdev_priv(dev);

	return dev_set_mtu(dlp->slave, new_mtu);
}

static int dlci_open(struct net_device *dev)
{
	struct dlci_local	*dlp;
	struct frad_local	*flp;
	int			err;

	dlp = netdev_priv(dev);

	if (!*(short *)(dev->dev_addr))
		return -EINVAL;

	if (!netif_running(dlp->slave))
		return -ENOTCONN;

	flp = netdev_priv(dlp->slave);
	err = (*flp->activate)(dlp->slave, dev);
	if (err)
		return err;

	netif_start_queue(dev);

	return 0;
}

static int dlci_close(struct net_device *dev)
{
	struct dlci_local	*dlp;
	struct frad_local	*flp;
	int			err;

	netif_stop_queue(dev);

	dlp = netdev_priv(dev);

	flp = netdev_priv(dlp->slave);
	err = (*flp->deactivate)(dlp->slave, dev);

	return 0;
}

static int dlci_add(struct dlci_add *dlci)
{
	struct net_device	*master, *slave;
	struct dlci_local	*dlp;
	struct frad_local	*flp;
	int			err = -EINVAL;

	/* validate slave device */
	slave = dev_get_by_name(&init_net, dlci->devname);
	if (!slave)
		return -ENODEV;

	if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL)
		goto err1;

	/* create device name */
	master = alloc_netdev(sizeof(struct dlci_local), "dlci%d",
			      NET_NAME_UNKNOWN, dlci_setup);
	if (!master) {
		err = -ENOMEM;
		goto err1;
	}

	/* make sure same slave not already registered */
	rtnl_lock();
	list_for_each_entry(dlp, &dlci_devs, list) {
		if (dlp->slave == slave) {
			err = -EBUSY;
			goto err2;
		}
	}

	*(short *)(master->dev_addr) = dlci->dlci;

	dlp = netdev_priv(master);
	dlp->slave = slave;
	dlp->master = master;

	flp = netdev_priv(slave);
	err = (*flp->assoc)(slave, master);
	if (err < 0)
		goto err2;

	err = register_netdevice(master);
	if (err < 0)
		goto err2;

	strcpy(dlci->devname, master->name);

	list_add(&dlp->list, &dlci_devs);
	rtnl_unlock();

	return 0;

 err2:
	rtnl_unlock();
	free_netdev(master);
 err1:
	dev_put(slave);
	return err;
}

static int dlci_del(struct dlci_add *dlci)
{
	struct dlci_local	*dlp;
	struct frad_local	*flp;
	struct net_device	*master, *slave;
	int			err;
	bool			found = false;

	rtnl_lock();

	/* validate slave device */
	master = __dev_get_by_name(&init_net, dlci->devname);
	if (!master) {
		err = -ENODEV;
		goto out;
	}

	list_for_each_entry(dlp, &dlci_devs, list) {
		if (dlp->master == master) {
			found = true;
			break;
		}
	}
	if (!found) {
		err = -ENODEV;
		goto out;
	}

	if (netif_running(master)) {
		err = -EBUSY;
		goto out;
	}

	dlp = netdev_priv(master);
	slave = dlp->slave;
	flp = netdev_priv(slave);

	err = (*flp->deassoc)(slave, master);
	if (!err) {
		list_del(&dlp->list);

		unregister_netdevice(master);

		dev_put(slave);
	}
out:
	rtnl_unlock();
	return err;
}

static int dlci_ioctl(unsigned int cmd, void __user *arg)
{
	struct dlci_add add;
	int err;

	if (!capable(CAP_NET_ADMIN))
		return -EPERM;

	if (copy_from_user(&add, arg, sizeof(struct dlci_add)))
		return -EFAULT;

	switch (cmd)
	{
		case SIOCADDDLCI:
			err = dlci_add(&add);

			if (!err)
				if (copy_to_user(arg, &add, sizeof(struct dlci_add)))
					return -EFAULT;
			break;

		case SIOCDELDLCI:
			err = dlci_del(&add);
			break;

		default:
			err = -EINVAL;
	}

	return err;
}

static const struct header_ops dlci_header_ops = {
	.create	= dlci_header,
};

static const struct net_device_ops dlci_netdev_ops = {
	.ndo_open	= dlci_open,
	.ndo_stop	= dlci_close,
	.ndo_do_ioctl	= dlci_dev_ioctl,
	.ndo_start_xmit	= dlci_transmit,
	.ndo_change_mtu	= dlci_change_mtu,
};

static void dlci_setup(struct net_device *dev)
{
	struct dlci_local *dlp = netdev_priv(dev);

	dev->flags		= 0;
	dev->header_ops		= &dlci_header_ops;
	dev->netdev_ops		= &dlci_netdev_ops;
	dev->destructor		= free_netdev;

	dlp->receive		= dlci_receive;

	dev->type		= ARPHRD_DLCI;
	dev->hard_header_len	= sizeof(struct frhdr);
	dev->addr_len		= sizeof(short);

}

/* if slave is unregistering, then cleanup master */
static int dlci_dev_event(struct notifier_block *unused,
			  unsigned long event, void *ptr)
{
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);

	if (dev_net(dev) != &init_net)
		return NOTIFY_DONE;

	if (event == NETDEV_UNREGISTER) {
		struct dlci_local *dlp;

		list_for_each_entry(dlp, &dlci_devs, list) {
			if (dlp->slave == dev) {
				list_del(&dlp->list);
				unregister_netdevice(dlp->master);
				dev_put(dlp->slave);
				break;
			}
		}
	}
	return NOTIFY_DONE;
}

static struct notifier_block dlci_notifier = {
	.notifier_call = dlci_dev_event,
};

static int __init init_dlci(void)
{
	dlci_ioctl_set(dlci_ioctl);
	register_netdevice_notifier(&dlci_notifier);

	printk("%s.\n", version);

	return 0;
}

static void __exit dlci_exit(void)
{
	struct dlci_local	*dlp, *nxt;

	dlci_ioctl_set(NULL);
	unregister_netdevice_notifier(&dlci_notifier);

	rtnl_lock();
	list_for_each_entry_safe(dlp, nxt, &dlci_devs, list) {
		unregister_netdevice(dlp->master);
		dev_put(dlp->slave);
	}
	rtnl_unlock();
}

module_init(init_dlci);
module_exit(dlci_exit);

MODULE_AUTHOR("Mike McLagan");
MODULE_DESCRIPTION("Frame Relay DLCI layer");
MODULE_LICENSE("GPL");


package pflag

// -- string Value
type stringValue string

func newStringValue(val string, p *string) *stringValue {
	*p = val
	return (*stringValue)(p)
}

func (s *stringValue) Set(val string) error {
	*s = stringValue(val)
	return nil
}
func (s *stringValue) Type() string {
	return "string"
}

func (s *stringValue) String() string { return string(*s) }

func stringConv(sval string) (interface{}, error) {
	return sval, nil
}

// GetString return the string value of a flag with the given name
func (f *FlagSet) GetString(name string) (string, error) {
	val, err := f.getFlagType(name, "string", stringConv)
	if err != nil {
		return "", err
	}
	return val.(string), nil
}

// StringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
	f.VarP(newStringValue(value, p), name, "", usage)
}

// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) {
	f.VarP(newStringValue(value, p), name, shorthand, usage)
}

// StringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func StringVar(p *string, name string, value string, usage string) {
	CommandLine.VarP(newStringValue(value, p), name, "", usage)
}

// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
func StringVarP(p *string, name, shorthand string, value string, usage string) {
	CommandLine.VarP(newStringValue(value, p), name, shorthand, usage)
}

// String defines a string flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func (f *FlagSet) String(name string, value string, usage string) *string {
	p := new(string)
	f.StringVarP(p, name, "", value, usage)
	return p
}

// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string {
	p := new(string)
	f.StringVarP(p, name, shorthand, value, usage)
	return p
}

// String defines a string flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func String(name string, value string, usage string) *string {
	return CommandLine.StringP(name, "", value, usage)
}

// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
func StringP(name, shorthand string, value string, usage string) *string {
	return CommandLine.StringP(name, shorthand, value, usage)
}


/**
 * 弹出选择列表插件
 * 此组件依赖 listpcker ，请在页面中先引入 mui.picker.css + mui.picker.js
 * varstion 1.0.1
 * by Houfeng
 * Houfeng@DCloud.io
 */

(function($, document) {

	//创建 DOM
	$.dom = function(str) {
		if (typeof(str) !== 'string') {
			if ((str instanceof Array) || (str[0] && str.length)) {
				return [].slice.call(str);
			} else {
				return [str];
			}
		}
		if (!$.__create_dom_div__) {
			$.__create_dom_div__ = document.createElement('div');
		}
		$.__create_dom_div__.innerHTML = str;
		return [].slice.call($.__create_dom_div__.childNodes);
	};

	var panelBuffer = '
\

\
			<button class="mui-btn mui-poppicker-btn-cancel">取消</button>\
			<button class="mui-btn mui-btn-blue mui-poppicker-btn-ok">确定</button>\

\

\

\

\

';

	var pickerBuffer = '
\

\

\

\

\

\

\

';

	//定义弹出选择器类
	var PopPicker = $.PopPicker = $.Class.extend({
		//构造函数
		init: function(options) {
			var self = this;
			self.options = options || {};
			self.options.buttons = self.options.buttons || ['取消', '确定'];
			self.panel = $.dom(panelBuffer)[0];
			document.body.appendChild(self.panel);
			self.ok = self.panel.querySelector('.mui-poppicker-btn-ok');
			self.cancel = self.panel.querySelector('.mui-poppicker-btn-cancel');
			self.body = self.panel.querySelector('.mui-poppicker-body');
			self.mask = $.createMask();
			self.cancel.innerText = self.options.buttons[0];
			self.ok.innerText = self.options.buttons[1];
			self.cancel.addEventListener('tap', function(event) {
				self.hide();
			}, false);
			self.ok.addEventListener('tap', function(event) {
				if (self.callback) {
					var rs = self.callback(self.getSelectedItems());
					if (rs !== false) {
						self.hide();
					}
				}
			}, false);
			self.mask[0].addEventListener('tap', function() {
				self.hide();
			}, false);
			self._createPicker();
			//防止滚动穿透
			self.panel.addEventListener($.EVENT_START, function(event) {
				event.preventDefault();
			}, false);
			self.panel.addEventListener($.EVENT_MOVE, function(event) {
				event.preventDefault();
			}, false);
		},
		_createPicker: function() {
			var self = this;
			var layer = self.options.layer || 1;
			var width = (100 / layer) + '%';
			self.pickers = [];
			for (var i = 1; i <= layer; i++) {
				var pickerElement = $.dom(pickerBuffer)[0];
				pickerElement.style.width = width;
				self.body.appendChild(pickerElement);
				var picker = $(pickerElement).picker();
				self.pickers.push(picker);
				pickerElement.addEventListener('change', function(event) {
					var nextPickerElement = this.nextSibling;
					if (nextPickerElement && nextPickerElement.picker) {
						var eventData = event.detail || {};
						var preItem = eventData.item || {};
						nextPickerElement.picker.setItems(preItem.children);
					}
				}, false);
			}
		},
		//填充数据
		setData: function(data) {
			var self = this;
			data = data || [];
			self.pickers[0].setItems(data);
		},
		//获取选中的项（数组）
		getSelectedItems: function() {
			var self = this;
			var items = [];
			for (var i in self.pickers) {
				var picker = self.pickers[i];
				items.push(picker.getSelectedItem() || {});
			}
			return items;
		},
		//显示
		show: function(callback) {
			var self = this;
			self.callback = callback;
			self.mask.show();
			document.body.classList.add($.className('poppicker-active-for-page'));
			self.panel.classList.add($.className('active'));
			//处理物理返回键
			self.__back = $.back;
			$.back = function() {
				self.hide();
			};
		},
		//隐藏
		hide: function() {
			var self = this;
			if (self.disposed) return;
			self.panel.classList.remove($.className('active'));
			self.mask.close();
			document.body.classList.remove($.className('poppicker-active-for-page'));
			//处理物理返回键
			$.back=self.__back;
		},
		dispose: function() {
			var self = this;
			self.hide();
			setTimeout(function() {
				self.panel.parentNode.removeChild(self.panel);
				for (var name in self) {
					self[name] = null;
					delete self[name];
				};
				self.disposed = true;
			}, 300);
		}
	});

})(mui, document);


/*
 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */
/*
 * @OSF_COPYRIGHT@
 */
/*
 * Mach Operating System
 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 */
/*
 *	File:	vm/vm_kern.c
 *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
 *	Date:	1985
 *
 *	Kernel memory management.
 */

#include <mach/kern_return.h>
#include <mach/vm_param.h>
#include <kern/assert.h>
#include <kern/thread.h>
#include <vm/vm_kern.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_compressor.h>
#include <vm/vm_pageout.h>
#include <kern/misc_protos.h>
#include <vm/cpm.h>

#include <string.h>

#include <libkern/OSDebug.h>
#include <libkern/crypto/sha2.h>
#include <sys/kdebug.h>

#include <san/kasan.h>

/*
 *	Variables exported by this module.
 */

vm_map_t	kernel_map;
vm_map_t	kernel_pageable_map;

extern boolean_t vm_kernel_ready;

/*
 * Forward declarations for internal functions.
 */
extern kern_return_t kmem_alloc_pages(
	vm_object_t		object,
	vm_object_offset_t	offset,
	vm_object_size_t	size);

kern_return_t
kmem_alloc_contig(
	vm_map_t		map,
	vm_offset_t		*addrp,
	vm_size_t		size,
	vm_offset_t 		mask,
	ppnum_t			max_pnum,
	ppnum_t			pnum_mask,
	int 			flags,
	vm_tag_t                tag)
{
	vm_object_t		object;
	vm_object_offset_t	offset;
	vm_map_offset_t		map_addr;
	vm_map_offset_t		map_mask;
	vm_map_size_t		map_size, i;
	vm_map_entry_t		entry;
	vm_page_t		m, pages;
	kern_return_t		kr;

    assert(VM_KERN_MEMORY_NONE != tag);

	if (map == VM_MAP_NULL || (flags & ~(KMA_KOBJECT | KMA_LOMEM | KMA_NOPAGEWAIT)))
		return KERN_INVALID_ARGUMENT;

	map_size = vm_map_round_page(size,
				     VM_MAP_PAGE_MASK(map));
	map_mask = (vm_map_offset_t)mask;

	/* Check for zero allocation size (either directly or via overflow) */
	if (map_size == 0) {
		*addrp = 0;
		return KERN_INVALID_ARGUMENT;
	}

	/*
	 *	Allocate a new object (if necessary) and the reference we
	 *	will be donating to the map entry.  We must do this before
	 *	locking the map, or risk deadlock with the default pager.
	 */
	if ((flags & KMA_KOBJECT) != 0) {
		object = kernel_object;
		vm_object_reference(object);
	} else {
		object = vm_object_allocate(map_size);
	}

	kr = vm_map_find_space(map, &map_addr, map_size, map_mask, 0,
			       VM_MAP_KERNEL_FLAGS_NONE, tag, &entry);
	if (KERN_SUCCESS != kr) {
		vm_object_deallocate(object);
		return kr;
	}

	if (object == kernel_object) {
		offset = map_addr;
	} else {
		offset = 0;
	}
	VME_OBJECT_SET(entry, object);
	VME_OFFSET_SET(entry, offset);

	/* Take an extra object ref in case the map entry gets deleted */
	vm_object_reference(object);
	vm_map_unlock(map);

	kr = cpm_allocate(CAST_DOWN(vm_size_t, map_size), &pages, max_pnum, pnum_mask, FALSE, flags);

	if (kr != KERN_SUCCESS) {
		vm_map_remove(map,
			      vm_map_trunc_page(map_addr,
						VM_MAP_PAGE_MASK(map)),
			      vm_map_round_page(map_addr + map_size,
						VM_MAP_PAGE_MASK(map)),
			      VM_MAP_REMOVE_NO_FLAGS);
		vm_object_deallocate(object);
		*addrp = 0;
		return kr;
	}

	vm_object_lock(object);
	for (i = 0; i < map_size; i += PAGE_SIZE) {
		m = pages;
		pages = NEXT_PAGE(m);
		*(NEXT_PAGE_PTR(m)) = VM_PAGE_NULL;
		m->vmp_busy = FALSE;
		vm_page_insert(m, object, offset + i);
	}
	vm_object_unlock(object);

	kr = vm_map_wire_kernel(map,
			 vm_map_trunc_page(map_addr,
					   VM_MAP_PAGE_MASK(map)),
			 vm_map_round_page(map_addr + map_size,
					   VM_MAP_PAGE_MASK(map)),
			 VM_PROT_DEFAULT, tag,
			 FALSE);

	if (kr != KERN_SUCCESS) {
		if (object == kernel_object) {
			vm_object_lock(object);
			vm_object_page_remove(object, offset, offset + map_size);
			vm_object_unlock(object);
		}
		vm_map_remove(map,
			      vm_map_trunc_page(map_addr,
						VM_MAP_PAGE_MASK(map)),
			      vm_map_round_page(map_addr + map_size,
						VM_MAP_PAGE_MASK(map)),
			      VM_MAP_REMOVE_NO_FLAGS);
		vm_object_deallocate(object);
		return kr;
	}
	vm_object_deallocate(object);

	if (object == kernel_object) {
		vm_map_simplify(map, map_addr);
	    vm_tag_update_size(tag, map_size);
    }
	*addrp = (vm_offset_t) map_addr;
	assert((vm_map_offset_t) *addrp == map_addr);

	return KERN_SUCCESS;
}

/*
 * Master entry point for allocating kernel memory.
 * NOTE: this routine is _never_ interrupt safe.
 *
 * map		: map to allocate into
 * addrp	: pointer to start address of new memory
 * size		: size of memory requested
 * flags	: options
 *		  KMA_HERE		*addrp is base address, else "anywhere"
 *		  KMA_NOPAGEWAIT	don't wait for pages if unavailable
 *		  KMA_KOBJECT		use kernel_object
 *		  KMA_LOMEM		support for 32 bit devices in a 64 bit world
 *					if set and a lomemory pool is available
 *					grab pages from it... this also implies
 *					KMA_NOPAGEWAIT
 */

kern_return_t
kernel_memory_allocate(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_offset_t	mask,
	int			flags,
	vm_tag_t                tag)
{
	vm_object_t 		object;
	vm_object_offset_t 	offset;
	vm_object_offset_t 	pg_offset;
	vm_map_entry_t 		entry = NULL;
	vm_map_offset_t 	map_addr, fill_start;
	vm_map_offset_t		map_mask;
	vm_map_size_t		map_size, fill_size;
	kern_return_t 		kr, pe_result;
	vm_page_t		mem;
	vm_page_t		guard_page_list = NULL;
	vm_page_t		wired_page_list = NULL;
	int			guard_page_count = 0;
	int			wired_page_count = 0;
	int			page_grab_count = 0;
	int			i;
	int			vm_alloc_flags;
	vm_map_kernel_flags_t	vmk_flags;
	vm_prot_t		kma_prot;

	if (! vm_kernel_ready) {
		panic("kernel_memory_allocate: VM is not ready");
	}

	map_size = vm_map_round_page(size,
				     VM_MAP_PAGE_MASK(map));
	map_mask = (vm_map_offset_t) mask;

	vm_alloc_flags = 0; //VM_MAKE_TAG(tag);
	vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;

	/* Check for zero allocation size (either directly or via overflow) */
	if (map_size == 0) {
		*addrp = 0;
		return KERN_INVALID_ARGUMENT;
	}

	/*
	 * limit the size of a single extent of wired memory
	 * to try and limit the damage to the system if
	 * too many pages get wired down
	 * limit raised to 2GB with 128GB max physical limit,
	 * but scaled by installed memory above this
	 */
        if (!(flags & (KMA_VAONLY | KMA_PAGEABLE)) &&
	    map_size > MAX(1ULL<<31, sane_size/64)) {
                return KERN_RESOURCE_SHORTAGE;
        }

	/*
	 * Guard pages:
	 *
	 * Guard pages are implemented as ficticious pages.  By placing guard pages
	 * on either end of a stack, they can help detect cases where a thread walks
	 * off either end of its stack.  They are allocated and set up here and attempts
	 * to access those pages are trapped in vm_fault_page().
	 *
	 * The map_size we were passed may include extra space for
	 * guard pages.  If those were requested, then back it out of fill_size
	 * since vm_map_find_space() takes just the actual size not including
	 * guard pages.  Similarly, fill_start indicates where the actual pages
	 * will begin in the range.
	 */

	fill_start = 0;
	fill_size = map_size;

	if (flags & KMA_GUARD_FIRST) {
		vmk_flags.vmkf_guard_before = TRUE;
		fill_start += PAGE_SIZE_64;
		fill_size -= PAGE_SIZE_64;
		if (map_size < fill_start + fill_size) {
			/* no space for a guard page */
			*addrp = 0;
			return KERN_INVALID_ARGUMENT;
		}
		guard_page_count++;
	}
	if (flags & KMA_GUARD_LAST) {
		vmk_flags.vmkf_guard_after = TRUE;
		fill_size -= PAGE_SIZE_64;
		if (map_size <= fill_start + fill_size) {
			/* no space for a guard page */
			*addrp = 0;
			return KERN_INVALID_ARGUMENT;
		}
		guard_page_count++;
	}
	wired_page_count = (int) (fill_size / PAGE_SIZE_64);
	assert(wired_page_count * PAGE_SIZE_64 == fill_size);

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_START, size, 0, 0, 0);
#endif

	for (i = 0; i < guard_page_count; i++) {
		for (;;) {
			mem = vm_page_grab_guard();

			if (mem != VM_PAGE_NULL)
				break;
			if (flags & KMA_NOPAGEWAIT) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			vm_page_more_fictitious();
		}
		mem->vmp_snext = guard_page_list;
		guard_page_list = mem;
	}

	if (!(flags & (KMA_VAONLY | KMA_PAGEABLE))) {
	for (i = 0; i < wired_page_count; i++) {
		uint64_t	unavailable;

		for (;;) {
		        if (flags & KMA_LOMEM)
			        mem = vm_page_grablo();
			else
			        mem = vm_page_grab();

		        if (mem != VM_PAGE_NULL)
			        break;

			if (flags & KMA_NOPAGEWAIT) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			if ((flags & KMA_LOMEM) && (vm_lopage_needed == TRUE)) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			unavailable = (vm_page_wire_count + vm_page_free_target) * PAGE_SIZE;

			if (unavailable > max_mem || map_size > (max_mem - unavailable)) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			VM_PAGE_WAIT();
		}
		page_grab_count++;
		if (KMA_ZERO & flags) vm_page_zero_fill(mem);
		mem->vmp_snext = wired_page_list;
		wired_page_list = mem;
	}
	}

	/*
	 *	Allocate a new object (if necessary).  We must do this before
	 *	locking the map, or risk deadlock with the default pager.
	 */
	if ((flags & KMA_KOBJECT) != 0) {
		object = kernel_object;
		vm_object_reference(object);
	} else if ((flags & KMA_COMPRESSOR) != 0) {
		object = compressor_object;
		vm_object_reference(object);
	} else {
		object = vm_object_allocate(map_size);
	}

	if (flags & KMA_ATOMIC)
		vmk_flags.vmkf_atomic_entry = TRUE;

	kr = vm_map_find_space(map, &map_addr,
			       fill_size, map_mask,
			       vm_alloc_flags, vmk_flags, tag, &entry);
	if (KERN_SUCCESS != kr) {
		vm_object_deallocate(object);
		goto out;
	}

	if (object == kernel_object || object == compressor_object) {
		offset = map_addr;
	} else {
		offset = 0;
	}
	VME_OBJECT_SET(entry, object);
	VME_OFFSET_SET(entry, offset);

	if (!(flags & (KMA_COMPRESSOR | KMA_PAGEABLE)))
		entry->wired_count++;

	if (flags & KMA_PERMANENT)
		entry->permanent = TRUE;

	if (object != kernel_object && object != compressor_object)
		vm_object_reference(object);

	vm_object_lock(object);
	vm_map_unlock(map);

	pg_offset = 0;

	if (fill_start) {
		if (guard_page_list == NULL)
			panic("kernel_memory_allocate: guard_page_list == NULL");

		mem = guard_page_list;
		guard_page_list = mem->vmp_snext;
		mem->vmp_snext = NULL;

		vm_page_insert(mem, object, offset + pg_offset);

		mem->vmp_busy = FALSE;
		pg_offset += PAGE_SIZE_64;
	}

	kma_prot = VM_PROT_READ | VM_PROT_WRITE;

#if KASAN
	if (!(flags & KMA_VAONLY)) {
		/* for VAONLY mappings we notify in populate only */
		kasan_notify_address(map_addr, size);
	}
#endif

	if (flags & (KMA_VAONLY | KMA_PAGEABLE)) {
		pg_offset = fill_start + fill_size;
	} else {
	for (pg_offset = fill_start; pg_offset < fill_start + fill_size; pg_offset += PAGE_SIZE_64) {
		if (wired_page_list == NULL)
			panic("kernel_memory_allocate: wired_page_list == NULL");

		mem = wired_page_list;
		wired_page_list = mem->vmp_snext;
		mem->vmp_snext = NULL;

		assert(mem->vmp_wire_count == 0);
		assert(mem->vmp_q_state == VM_PAGE_NOT_ON_Q);

		mem->vmp_q_state = VM_PAGE_IS_WIRED;
		mem->vmp_wire_count++;
		if (__improbable(mem->vmp_wire_count == 0)) {
			panic("kernel_memory_allocate(%p): wire_count overflow",
			      mem);
		}

		vm_page_insert_wired(mem, object, offset + pg_offset, tag);

		mem->vmp_busy = FALSE;
		mem->vmp_pmapped = TRUE;
		mem->vmp_wpmapped = TRUE;

		PMAP_ENTER_OPTIONS(kernel_pmap, map_addr + pg_offset, mem,
				   kma_prot, VM_PROT_NONE, ((flags & KMA_KSTACK) ? VM_MEM_STACK : 0), TRUE,
				   PMAP_OPTIONS_NOWAIT, pe_result);

		if (pe_result == KERN_RESOURCE_SHORTAGE) {
			vm_object_unlock(object);

			PMAP_ENTER(kernel_pmap, map_addr + pg_offset, mem,
				   kma_prot, VM_PROT_NONE, ((flags & KMA_KSTACK) ? VM_MEM_STACK : 0), TRUE,
				   pe_result);

			vm_object_lock(object);
		}

		assert(pe_result == KERN_SUCCESS);

		if (flags & KMA_NOENCRYPT) {
			bzero(CAST_DOWN(void *, (map_addr + pg_offset)), PAGE_SIZE);

			pmap_set_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem));
		}
	}
	if (kernel_object == object) vm_tag_update_size(tag, fill_size);
	}
	if ((fill_start + fill_size) < map_size) {
		if (guard_page_list == NULL)
			panic("kernel_memory_allocate: guard_page_list == NULL");

		mem = guard_page_list;
		guard_page_list = mem->vmp_snext;
		mem->vmp_snext = NULL;

		vm_page_insert(mem, object, offset + pg_offset);

		mem->vmp_busy = FALSE;
	}
	if (guard_page_list || wired_page_list)
		panic("kernel_memory_allocate: non empty list\n");

	if (!(flags & (KMA_VAONLY | KMA_PAGEABLE))) {
	vm_page_lockspin_queues();
	vm_page_wire_count += wired_page_count;
	vm_page_unlock_queues();
	}

	vm_object_unlock(object);

	/*
	 * now that the pages are wired, we no longer have to fear coalesce
	 */
	if (object == kernel_object || object == compressor_object)
		vm_map_simplify(map, map_addr);
	else
		vm_object_deallocate(object);

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_END, page_grab_count, 0, 0, 0);
#endif

	/*
	 *	Return the memory, not zeroed.
	 */
	*addrp = CAST_DOWN(vm_offset_t, map_addr);
	return KERN_SUCCESS;

out:
	if (guard_page_list)
		vm_page_free_list(guard_page_list, FALSE);

	if (wired_page_list)
		vm_page_free_list(wired_page_list, FALSE);

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_END, page_grab_count, 0, 0, 0);
#endif

	return kr;
}

kern_return_t
kernel_memory_populate(
	vm_map_t	map,
	vm_offset_t	addr,
	vm_size_t	size,
	int		flags,
	vm_tag_t        tag)
{
	vm_object_t		object;
	vm_object_offset_t	offset, pg_offset;
	kern_return_t		kr, pe_result;
	vm_page_t		mem;
	vm_page_t		page_list = NULL;
	int			page_count = 0;
	int			page_grab_count = 0;
	int			i;

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_START, size, 0, 0, 0);
#endif

	page_count = (int) (size / PAGE_SIZE_64);

	assert((flags & (KMA_COMPRESSOR|KMA_KOBJECT)) != (KMA_COMPRESSOR|KMA_KOBJECT));

	if (flags & KMA_COMPRESSOR) {

		pg_offset = page_count * PAGE_SIZE_64;

		do {
			for (;;) {
				mem = vm_page_grab();

				if (mem != VM_PAGE_NULL)
					break;

				VM_PAGE_WAIT();
			}
			page_grab_count++;
			if (KMA_ZERO & flags) vm_page_zero_fill(mem);
			mem->vmp_snext = page_list;
			page_list = mem;

			pg_offset -= PAGE_SIZE_64;

			kr = pmap_enter_options(kernel_pmap,
						  addr + pg_offset, VM_PAGE_GET_PHYS_PAGE(mem),
						  VM_PROT_READ | VM_PROT_WRITE, VM_PROT_NONE, 0, TRUE,
						  PMAP_OPTIONS_INTERNAL, NULL);
			assert(kr == KERN_SUCCESS);

		} while (pg_offset);

		offset = addr;
		object = compressor_object;

		vm_object_lock(object);

		for (pg_offset = 0;
		     pg_offset < size;
		     pg_offset += PAGE_SIZE_64) {

			mem = page_list;
			page_list = mem->vmp_snext;
			mem->vmp_snext = NULL;

			vm_page_insert(mem, object, offset + pg_offset);
			assert(mem->vmp_busy);

			mem->vmp_busy = FALSE;
			mem->vmp_pmapped = TRUE;
			mem->vmp_wpmapped = TRUE;
			mem->vmp_q_state = VM_PAGE_USED_BY_COMPRESSOR;
		}
		vm_object_unlock(object);

#if KASAN
		if (map == compressor_map) {
			kasan_notify_address_nopoison(addr, size);
		} else {
			kasan_notify_address(addr, size);
		}
#endif

#if DEBUG || DEVELOPMENT
		VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_END, page_grab_count, 0, 0, 0);
#endif
		return KERN_SUCCESS;
	}

	for (i = 0; i < page_count; i++) {
		for (;;) {
			if (flags & KMA_LOMEM)
				mem = vm_page_grablo();
			else
				mem = vm_page_grab();

			if (mem != VM_PAGE_NULL)
				break;

			if (flags & KMA_NOPAGEWAIT) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			if ((flags & KMA_LOMEM) &&
			    (vm_lopage_needed == TRUE)) {
				kr = KERN_RESOURCE_SHORTAGE;
				goto out;
			}
			VM_PAGE_WAIT();
		}
		page_grab_count++;
		if (KMA_ZERO & flags) vm_page_zero_fill(mem);
		mem->vmp_snext = page_list;
		page_list = mem;
	}
	if (flags & KMA_KOBJECT) {
		offset = addr;
		object = kernel_object;

		vm_object_lock(object);
	} else {
		/*
		 * If it's not the kernel object, we need to:
		 *      lock map;
		 *      lookup entry;
		 *      lock object;
		 *	take reference on object;
		 *      unlock map;
		 */
		panic("kernel_memory_populate(%p,0x%llx,0x%llx,0x%x): "
		      "!KMA_KOBJECT",
		      map, (uint64_t) addr, (uint64_t) size, flags);
	}

	for (pg_offset = 0;
	     pg_offset < size;
	     pg_offset += PAGE_SIZE_64) {

		if (page_list == NULL)
			panic("kernel_memory_populate: page_list == NULL");

		mem = page_list;
		page_list = mem->vmp_snext;
		mem->vmp_snext = NULL;

		assert(mem->vmp_q_state == VM_PAGE_NOT_ON_Q);
		mem->vmp_q_state = VM_PAGE_IS_WIRED;
		mem->vmp_wire_count++;
		if (__improbable(mem->vmp_wire_count == 0)) {
			panic("kernel_memory_populate(%p): wire_count overflow", mem);
		}

		vm_page_insert_wired(mem, object, offset + pg_offset, tag);

		mem->vmp_busy = FALSE;
		mem->vmp_pmapped = TRUE;
		mem->vmp_wpmapped = TRUE;

		PMAP_ENTER_OPTIONS(kernel_pmap, addr + pg_offset, mem,
				   VM_PROT_READ | VM_PROT_WRITE, VM_PROT_NONE,
				   ((flags & KMA_KSTACK) ? VM_MEM_STACK : 0), TRUE,
				   PMAP_OPTIONS_NOWAIT, pe_result);

		if (pe_result == KERN_RESOURCE_SHORTAGE) {

			vm_object_unlock(object);

			PMAP_ENTER(kernel_pmap, addr + pg_offset, mem,
				   VM_PROT_READ | VM_PROT_WRITE, VM_PROT_NONE,
				   ((flags & KMA_KSTACK) ? VM_MEM_STACK : 0), TRUE,
				   pe_result);

			vm_object_lock(object);
		}

		assert(pe_result == KERN_SUCCESS);

		if (flags & KMA_NOENCRYPT) {
			bzero(CAST_DOWN(void *, (addr + pg_offset)), PAGE_SIZE);
			pmap_set_noencrypt(VM_PAGE_GET_PHYS_PAGE(mem));
		}
	}
	vm_page_lockspin_queues();
	vm_page_wire_count += page_count;
	vm_page_unlock_queues();

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_END, page_grab_count, 0, 0, 0);
#endif

	if (kernel_object == object) vm_tag_update_size(tag, size);

	vm_object_unlock(object);

#if KASAN
	if (map == compressor_map) {
		kasan_notify_address_nopoison(addr, size);
	} else {
		kasan_notify_address(addr, size);
	}
#endif
	return KERN_SUCCESS;

out:
	if (page_list)
		vm_page_free_list(page_list, FALSE);

#if DEBUG || DEVELOPMENT
	VM_DEBUG_CONSTANT_EVENT(vm_kern_request, VM_KERN_REQUEST, DBG_FUNC_END, page_grab_count, 0, 0, 0);
#endif

	return kr;
}

void
kernel_memory_depopulate(
	vm_map_t	map,
	vm_offset_t	addr,
	vm_size_t	size,
	int		flags)
{
	vm_object_t		object;
	vm_object_offset_t	offset, pg_offset;
	vm_page_t		mem;
	vm_page_t		local_freeq = NULL;

	assert((flags & (KMA_COMPRESSOR|KMA_KOBJECT)) != (KMA_COMPRESSOR|KMA_KOBJECT));

	if (flags & KMA_COMPRESSOR) {
		offset = addr;
		object = compressor_object;

		vm_object_lock(object);
	} else if (flags & KMA_KOBJECT) {
		offset = addr;
		object = kernel_object;
		vm_object_lock(object);
	} else {
		offset = 0;
		object = NULL;
                /*
                 * If it's not the kernel object, we need to:
                 *      lock map;
                 *      lookup entry;
                 *      lock object;
                 *      unlock map;
                 */
		panic("kernel_memory_depopulate(%p,0x%llx,0x%llx,0x%x): "
		      "!KMA_KOBJECT",
		      map, (uint64_t) addr, (uint64_t) size, flags);
	}
	pmap_protect(kernel_map->pmap, offset, offset + size, VM_PROT_NONE);

	for (pg_offset = 0;
	     pg_offset < size;
	     pg_offset += PAGE_SIZE_64) {

		mem = vm_page_lookup(object, offset + pg_offset);

		assert(mem);

		if (mem->vmp_q_state != VM_PAGE_USED_BY_COMPRESSOR)
			pmap_disconnect(VM_PAGE_GET_PHYS_PAGE(mem));

		mem->vmp_busy = TRUE;

		assert(mem->vmp_tabled);
		vm_page_remove(mem, TRUE);
		assert(mem->vmp_busy);

		assert(mem->vmp_pageq.next == 0 && mem->vmp_pageq.prev == 0);
		assert((mem->vmp_q_state == VM_PAGE_USED_BY_COMPRESSOR) ||
		       (mem->vmp_q_state == VM_PAGE_NOT_ON_Q));

		mem->vmp_q_state = VM_PAGE_NOT_ON_Q;
		mem->vmp_snext = local_freeq;
		local_freeq = mem;
	}
	vm_object_unlock(object);

	if (local_freeq)
		vm_page_free_list(local_freeq, TRUE);
}

/*
 *	kmem_alloc:
 *
 *	Allocate wired-down memory in the kernel's address map
 *	or a submap.  The memory is not zero-filled.
 */

kern_return_t
kmem_alloc_external(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size)
{
    return (kmem_alloc(map, addrp, size, vm_tag_bt()));
}

kern_return_t
kmem_alloc(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_tag_t 	tag)
{
	return kmem_alloc_flags(map, addrp, size, tag, 0);
}

kern_return_t
kmem_alloc_flags(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_tag_t 	tag,
	int 		flags)
{
	kern_return_t kr = kernel_memory_allocate(map, addrp, size, 0, flags, tag);
	TRACE_MACHLEAKS(KMEM_ALLOC_CODE, KMEM_ALLOC_CODE_2, size, *addrp);
	return kr;
}

/*
 *	kmem_realloc:
 *
 *	Reallocate wired-down memory in the kernel's address map
 *	or a submap.  Newly allocated pages are not zeroed.
 *	This can only be used on regions allocated with kmem_alloc.
 *
 *	If successful, the pages in the old region are mapped twice.
 *	The old region is unchanged.  Use kmem_free to get rid of it.
 */
kern_return_t
kmem_realloc(
	vm_map_t		map,
	vm_offset_t		oldaddr,
	vm_size_t		oldsize,
	vm_offset_t		*newaddrp,
	vm_size_t		newsize,
	vm_tag_t		tag)
{
	vm_object_t		object;
	vm_object_offset_t	offset;
	vm_map_offset_t		oldmapmin;
	vm_map_offset_t		oldmapmax;
	vm_map_offset_t		newmapaddr;
	vm_map_size_t		oldmapsize;
	vm_map_size_t		newmapsize;
	vm_map_entry_t		oldentry;
	vm_map_entry_t		newentry;
	vm_page_t		mem;
	kern_return_t		kr;

	oldmapmin = vm_map_trunc_page(oldaddr,
				      VM_MAP_PAGE_MASK(map));
	oldmapmax = vm_map_round_page(oldaddr + oldsize,
				      VM_MAP_PAGE_MASK(map));
	oldmapsize = oldmapmax - oldmapmin;
	newmapsize = vm_map_round_page(newsize,
				       VM_MAP_PAGE_MASK(map));
	if (newmapsize < newsize) {
		/* overflow */
		*newaddrp = 0;
		return KERN_INVALID_ARGUMENT;
	}

	/*
	 *	Find the VM object backing the old region.
	 */

	vm_map_lock(map);

	if (!vm_map_lookup_entry(map, oldmapmin, &oldentry))
		panic("kmem_realloc");
	object = VME_OBJECT(oldentry);

	/*
	 *	Increase the size of the object and
	 *	fill in the new region.
	 */

	vm_object_reference(object);
	/* by grabbing the object lock before unlocking the map */
	/* we guarantee that we will panic if more than one     */
	/* attempt is made to realloc a kmem_alloc'd area       */
	vm_object_lock(object);
	vm_map_unlock(map);
	if (object->vo_size != oldmapsize)
		panic("kmem_realloc");
	object->vo_size = newmapsize;
	vm_object_unlock(object);

	/* allocate the new pages while expanded portion of the */
	/* object is still not mapped */
	kmem_alloc_pages(object, vm_object_round_page(oldmapsize),
			 vm_object_round_page(newmapsize-oldmapsize));

	/*
	 *	Find space for the new region.
	 */

	kr = vm_map_find_space(map, &newmapaddr, newmapsize,
			       (vm_map_offset_t) 0, 0,
			       VM_MAP_KERNEL_FLAGS_NONE,
			       tag,
			       &newentry);
	if (kr != KERN_SUCCESS) {
		vm_object_lock(object);
		for(offset = oldmapsize;
		    offset < newmapsize; offset += PAGE_SIZE) {
	    		if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
				VM_PAGE_FREE(mem);
			}
		}
		object->vo_size = oldmapsize;
		vm_object_unlock(object);
		vm_object_deallocate(object);
		return kr;
	}
	VME_OBJECT_SET(newentry, object);
	VME_OFFSET_SET(newentry, 0);
	assert(newentry->wired_count == 0);

	/* add an extra reference in case we have someone doing an */
	/* unexpected deallocate */
	vm_object_reference(object);
	vm_map_unlock(map);

	kr = vm_map_wire_kernel(map, newmapaddr, newmapaddr + newmapsize,
			 VM_PROT_DEFAULT, tag, FALSE);
	if (KERN_SUCCESS != kr) {
		vm_map_remove(map, newmapaddr, newmapaddr + newmapsize, VM_MAP_REMOVE_NO_FLAGS);
		vm_object_lock(object);
		for(offset = oldsize; offset < newmapsize; offset += PAGE_SIZE) {
	    		if ((mem = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
				VM_PAGE_FREE(mem);
			}
		}
		object->vo_size = oldmapsize;
		vm_object_unlock(object);
		vm_object_deallocate(object);
		return (kr);
	}
	vm_object_deallocate(object);

	if (kernel_object == object) vm_tag_update_size(tag, newmapsize);

	*newaddrp = CAST_DOWN(vm_offset_t, newmapaddr);
	return KERN_SUCCESS;
}

/*
 *	kmem_alloc_kobject:
 *
 *	Allocate wired-down memory in the kernel's address map
 *	or a submap.  The memory is not zero-filled.
 *
 *	The memory is allocated in the kernel_object.
 *	It may not be copied with vm_map_copy, and
 *	it may not be reallocated with kmem_realloc.
 */

kern_return_t
kmem_alloc_kobject_external(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size)
{
    return (kmem_alloc_kobject(map, addrp, size, vm_tag_bt()));
}

kern_return_t
kmem_alloc_kobject(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_tag_t        tag)
{
	return kernel_memory_allocate(map, addrp, size, 0, KMA_KOBJECT, tag);
}

/*
 *	kmem_alloc_aligned:
 *
 *	Like kmem_alloc_kobject, except that the memory is aligned.
 *	The size should be a power-of-2.
 */

kern_return_t
kmem_alloc_aligned(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_tag_t        tag)
{
	if ((size & (size - 1)) != 0)
		panic("kmem_alloc_aligned: size not aligned");
	return kernel_memory_allocate(map, addrp, size, size - 1, KMA_KOBJECT, tag);
}

/*
 *	kmem_alloc_pageable:
 *
 *	Allocate pageable memory in the kernel's address map.
 */

kern_return_t
kmem_alloc_pageable_external(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size)
{
    return (kmem_alloc_pageable(map, addrp, size, vm_tag_bt()));
}

kern_return_t
kmem_alloc_pageable(
	vm_map_t	map,
	vm_offset_t	*addrp,
	vm_size_t	size,
	vm_tag_t        tag)
{
	vm_map_offset_t map_addr;
	vm_map_size_t	map_size;
	kern_return_t kr;

#ifndef normal
	map_addr = (vm_map_min(map)) + PAGE_SIZE;
#else
	map_addr = vm_map_min(map);
#endif
	map_size = vm_map_round_page(size,
				     VM_MAP_PAGE_MASK(map));
	if (map_size < size) {
		/* overflow */
		*addrp = 0;
		return KERN_INVALID_ARGUMENT;
	}

	kr = vm_map_enter(map, &map_addr, map_size,
			  (vm_map_offset_t) 0,
			  VM_FLAGS_ANYWHERE,
			  VM_MAP_KERNEL_FLAGS_NONE,
			  tag,
			  VM_OBJECT_NULL, (vm_object_offset_t) 0, FALSE,
			  VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);

	if (kr != KERN_SUCCESS)
		return kr;

#if KASAN
	kasan_notify_address(map_addr, map_size);
#endif
	*addrp = CAST_DOWN(vm_offset_t, map_addr);
	return KERN_SUCCESS;
}

/*
 *	kmem_free:
 *
 *	Release a region of kernel virtual memory allocated
 *	with kmem_alloc, kmem_alloc_kobject, or kmem_alloc_pageable,
 *	and return the physical pages associated with that region.
 */

void
kmem_free(
	vm_map_t	map,
	vm_offset_t	addr,
	vm_size_t	size)
{
	kern_return_t kr;

	assert(addr >= VM_MIN_KERNEL_AND_KEXT_ADDRESS);

	TRACE_MACHLEAKS(KMEM_FREE_CODE, KMEM_FREE_CODE_2, size, addr);

	if(size == 0) {
#if MACH_ASSERT
		printf("kmem_free called with size==0 for map: %p with addr: 0x%llx\n",map,(uint64_t)addr);
#endif
		return;
	}

	kr = vm_map_remove(map,
			   vm_map_trunc_page(addr,
					     VM_MAP_PAGE_MASK(map)),
			   vm_map_round_page(addr + size,
					     VM_MAP_PAGE_MASK(map)),
			   VM_MAP_REMOVE_KUNWIRE);
	if (kr != KERN_SUCCESS)
		panic("kmem_free");
}

/*
 *	Allocate new pages in an object.
 */

kern_return_t
kmem_alloc_pages(
	vm_object_t		object,
	vm_object_offset_t	offset,
	vm_object_size_t	size)
{
	vm_object_size_t		alloc_size;

	alloc_size = vm_object_round_page(size);
        vm_object_lock(object);
	while (alloc_size) {
	    vm_page_t	mem;

	    /*
	     *	Allocate a page
	     */
	    while (VM_PAGE_NULL ==
		  (mem = vm_page_alloc(object, offset))) {
		vm_object_unlock(object);
		VM_PAGE_WAIT();
		vm_object_lock(object);
	    }
	    mem->vmp_busy = FALSE;

	    alloc_size -= PAGE_SIZE;
	    offset += PAGE_SIZE;
	}
	vm_object_unlock(object);
	return KERN_SUCCESS;
}

/*
 *	kmem_suballoc:
 *
 *	Allocates a map to manage a subrange
 *	of the kernel virtual address space.
 *
 *	Arguments are as follows:
 *
 *	parent		Map to take range from
 *	addr		Address of start of range (IN/OUT)
 *	size		Size of range to find
 *	pageable	Can region be paged
 *	anywhere	Can region be located anywhere in map
 *	new_map		Pointer to new submap
 */
kern_return_t
kmem_suballoc(
	vm_map_t	parent,
	vm_offset_t	*addr,
	vm_size_t	size,
	boolean_t	pageable,
	int		flags,
	vm_map_kernel_flags_t vmk_flags,
	vm_tag_t    tag,
	vm_map_t	*new_map)
{
	vm_map_t	map;
	vm_map_offset_t	map_addr;
	vm_map_size_t	map_size;
	kern_return_t	kr;

	map_size = vm_map_round_page(size,
				     VM_MAP_PAGE_MASK(parent));
	if (map_size < size) {
		/* overflow */
		*addr = 0;
		return KERN_INVALID_ARGUMENT;
	}

	/*
	 *	Need reference on submap object because it is internal
	 *	to the vm_system.  vm_object_enter will never be called
	 *	on it (usual source of reference for vm_map_enter).
	 */
	vm_object_reference(vm_submap_object);

	map_addr = ((flags & VM_FLAGS_ANYWHERE)
		    ? vm_map_min(parent)
		    : vm_map_trunc_page(*addr,
					VM_MAP_PAGE_MASK(parent)));

	kr = vm_map_enter(parent, &map_addr, map_size,
			  (vm_map_offset_t) 0, flags, vmk_flags, tag,
			  vm_submap_object, (vm_object_offset_t) 0, FALSE,
			  VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
	if (kr != KERN_SUCCESS) {
		vm_object_deallocate(vm_submap_object);
		return (kr);
	}

	pmap_reference(vm_map_pmap(parent));
	map = vm_map_create(vm_map_pmap(parent), map_addr, map_addr + map_size, pageable);
	if (map == VM_MAP_NULL)
		panic("kmem_suballoc: vm_map_create failed");	/* "can't happen" */
	/* inherit the parent map's page size */
	vm_map_set_page_shift(map, VM_MAP_PAGE_SHIFT(parent));

	kr = vm_map_submap(parent, map_addr, map_addr + map_size, map, map_addr, FALSE);
	if (kr != KERN_SUCCESS) {
		/*
		 * See comment preceding vm_map_submap().
		 */
		vm_map_remove(parent, map_addr, map_addr + map_size,
			      VM_MAP_REMOVE_NO_FLAGS);
		vm_map_deallocate(map);	/* also removes ref to pmap */
		vm_object_deallocate(vm_submap_object);
		return (kr);
	}
	*addr = CAST_DOWN(vm_offset_t, map_addr);
	*new_map = map;
	return (KERN_SUCCESS);
}

/*
 *	kmem_init:
 *
 *	Initialize the kernel's virtual memory map, taking
 *	into account all memory allocated up to this time.
 */
void
kmem_init(
	vm_offset_t	start,
	vm_offset_t	end)
{
	vm_map_offset_t map_start;
	vm_map_offset_t map_end;
	vm_map_kernel_flags_t vmk_flags;

	vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
	vmk_flags.vmkf_permanent = TRUE;
	vmk_flags.vmkf_no_pmap_check = TRUE;

	map_start = vm_map_trunc_page(start,
				      VM_MAP_PAGE_MASK(kernel_map));
	map_end = vm_map_round_page(end,
				    VM_MAP_PAGE_MASK(kernel_map));

#if	defined(__arm__) || defined(__arm64__)
	kernel_map = vm_map_create(pmap_kernel(),VM_MIN_KERNEL_AND_KEXT_ADDRESS,
			    VM_MAX_KERNEL_ADDRESS, FALSE);
	/*
	 *	Reserve virtual memory allocated up to this time.
	 */
	{
		unsigned int	region_select = 0;
		vm_map_offset_t	region_start;
		vm_map_size_t	region_size;
		vm_map_offset_t map_addr;
		kern_return_t kr;

		while (pmap_virtual_region(region_select, &region_start, &region_size)) {

			map_addr = region_start;
			kr = vm_map_enter(kernel_map, &map_addr,
					  vm_map_round_page(region_size,
							    VM_MAP_PAGE_MASK(kernel_map)),
					  (vm_map_offset_t) 0,
			                  VM_FLAGS_FIXED,
					  vmk_flags,
					  VM_KERN_MEMORY_NONE,
					  VM_OBJECT_NULL,
			                  (vm_object_offset_t) 0, FALSE, VM_PROT_NONE, VM_PROT_NONE,
			                  VM_INHERIT_DEFAULT);

			if (kr != KERN_SUCCESS) {
				panic("kmem_init(0x%llx,0x%llx): vm_map_enter(0x%llx,0x%llx) error 0x%x\n",
				       (uint64_t) start, (uint64_t) end, (uint64_t) region_start,
				       (uint64_t) region_size, kr);
			}

			region_select++;
		}
	}
#else
	kernel_map = vm_map_create(pmap_kernel(),VM_MIN_KERNEL_AND_KEXT_ADDRESS,
			    map_end, FALSE);
	/*
	 *	Reserve virtual memory allocated up to this time.
	 */
	if (start != VM_MIN_KERNEL_AND_KEXT_ADDRESS) {
		vm_map_offset_t map_addr;
		kern_return_t kr;

		vmk_flags = VM_MAP_KERNEL_FLAGS_NONE;
		vmk_flags.vmkf_no_pmap_check = TRUE;

		map_addr = VM_MIN_KERNEL_AND_KEXT_ADDRESS;
		kr = vm_map_enter(kernel_map,
				  &map_addr,
				  (vm_map_size_t)(map_start - VM_MIN_KERNEL_AND_KEXT_ADDRESS),
				  (vm_map_offset_t) 0,
				  VM_FLAGS_FIXED,
				  vmk_flags,
				  VM_KERN_MEMORY_NONE,
				  VM_OBJECT_NULL,
				  (vm_object_offset_t) 0, FALSE,
				  VM_PROT_NONE, VM_PROT_NONE,
				  VM_INHERIT_DEFAULT);

		if (kr != KERN_SUCCESS) {
			panic("kmem_init(0x%llx,0x%llx): vm_map_enter(0x%llx,0x%llx) error 0x%x\n",
			      (uint64_t) start, (uint64_t) end,
			      (uint64_t) VM_MIN_KERNEL_AND_KEXT_ADDRESS,
			      (uint64_t) (map_start - VM_MIN_KERNEL_AND_KEXT_ADDRESS),
			      kr);
		}
	}
#endif

	/*
	 * Set the default global user wire limit which limits the amount of
	 * memory that can be locked via mlock().  We set this to the total
	 * amount of memory that are potentially usable by a user app (max_mem)
	 * minus a certain amount.  This can be overridden via a sysctl.
	 */
	vm_global_no_user_wire_amount = MIN(max_mem*20/100,
					    VM_NOT_USER_WIREABLE);
	vm_global_user_wire_limit = max_mem - vm_global_no_user_wire_amount;

	/* the default per user limit is the same as the global limit */
	vm_user_wire_limit = vm_global_user_wire_limit;
}

/*
 *	Routine:	copyinmap
 *	Purpose:
 *		Like copyin, except that fromaddr is an address
 *		in the specified VM map.  This implementation
 *		is incomplete; it handles the current user map
 *		and the kernel map/submaps.
 */
kern_return_t
copyinmap(
	vm_map_t		map,
	vm_map_offset_t		fromaddr,
	void			*todata,
	vm_size_t		length)
{
	kern_return_t	kr = KERN_SUCCESS;
	vm_map_t oldmap;

	if (vm_map_pmap(map) == pmap_kernel())
	{
		/* assume a correct copy */
		memcpy(todata, CAST_DOWN(void *, fromaddr), length);
	}
	else if (current_map() == map)
	{
		if (copyin(fromaddr, todata, length) != 0)
			kr = KERN_INVALID_ADDRESS;
	}
	else
	{
		vm_map_reference(map);
		oldmap = vm_map_switch(map);
		if (copyin(fromaddr, todata, length) != 0)
			kr = KERN_INVALID_ADDRESS;
		vm_map_switch(oldmap);
		vm_map_deallocate(map);
	}
	return kr;
}

/*
 *	Routine:	copyoutmap
 *	Purpose:
 *		Like copyout, except that toaddr is an address
 *		in the specified VM map.  This implementation
 *		is incomplete; it handles the current user map
 *		and the kernel map/submaps.
 */
kern_return_t
copyoutmap(
	vm_map_t		map,
	void			*fromdata,
	vm_map_address_t	toaddr,
	vm_size_t		length)
{
	if (vm_map_pmap(map) == pmap_kernel()) {
		/* assume a correct copy */
		memcpy(CAST_DOWN(void *, toaddr), fromdata, length);
		return KERN_SUCCESS;
	}

	if (current_map() != map)
		return KERN_NOT_SUPPORTED;

	if (copyout(fromdata, toaddr, length) != 0)
		return KERN_INVALID_ADDRESS;

	return KERN_SUCCESS;
}

/*
 *
 *	The following two functions are to be used when exposing kernel
 *	addresses to userspace via any of the various debug or info
 *	facilities that exist. These are basically the same as VM_KERNEL_ADDRPERM()
 *	and VM_KERNEL_UNSLIDE_OR_PERM() except they use a different random seed and
 *	are exported to KEXTs.
 *
 *	NOTE: USE THE MACRO VERSIONS OF THESE FUNCTIONS (in vm_param.h) FROM WITHIN THE KERNEL
 */

static void
vm_kernel_addrhash_internal(
	vm_offset_t addr,
	vm_offset_t *hash_addr,
	uint64_t salt)
{
	assert(salt != 0);

	if (addr == 0) {
		*hash_addr = 0;
		return;
	}

	if (VM_KERNEL_IS_SLID(addr)) {
		*hash_addr = VM_KERNEL_UNSLIDE(addr);
		return;
	}

	vm_offset_t sha_digest[SHA256_DIGEST_LENGTH/sizeof(vm_offset_t)];
	SHA256_CTX sha_ctx;

	SHA256_Init(&sha_ctx);
	SHA256_Update(&sha_ctx, &salt, sizeof(salt));
	SHA256_Update(&sha_ctx, &addr, sizeof(addr));
	SHA256_Final(sha_digest, &sha_ctx);

	*hash_addr = sha_digest[0];
}

void
vm_kernel_addrhash_external(
	vm_offset_t addr,
	vm_offset_t *hash_addr)
{
	return vm_kernel_addrhash_internal(addr, hash_addr, vm_kernel_addrhash_salt_ext);
}

vm_offset_t
vm_kernel_addrhash(vm_offset_t addr)
{
	vm_offset_t hash_addr;
	vm_kernel_addrhash_internal(addr, &hash_addr, vm_kernel_addrhash_salt);
	return hash_addr;
}

void
vm_kernel_addrhide(
	vm_offset_t addr,
	vm_offset_t *hide_addr)
{
	*hide_addr = VM_KERNEL_ADDRHIDE(addr);
}

/*
 *	vm_kernel_addrperm_external:
 *	vm_kernel_unslide_or_perm_external:
 *
 *	Use these macros when exposing an address to userspace that could come from
 *	either kernel text/data *or* the heap.
 */
void
vm_kernel_addrperm_external(
	vm_offset_t addr,
	vm_offset_t *perm_addr)
{
	if (VM_KERNEL_IS_SLID(addr)) {
		*perm_addr = VM_KERNEL_UNSLIDE(addr);
	} else if (VM_KERNEL_ADDRESS(addr)) {
		*perm_addr = addr + vm_kernel_addrperm_ext;
	} else {
		*perm_addr = addr;
	}
}

void
vm_kernel_unslide_or_perm_external(
	vm_offset_t addr,
	vm_offset_t *up_addr)
{
	vm_kernel_addrperm_external(addr, up_addr);
}


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

package internal

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io/ioutil"

	"golang.org/x/oauth2/google"
	"golang.org/x/oauth2/jwt"

	"go.chromium.org/luci/common/logging"
	"go.chromium.org/luci/common/retry/transient"
)

type serviceAccountTokenProvider struct {
	ctx     context.Context // only for logging
	jsonKey []byte
	path    string
	scopes  []string
}

// NewServiceAccountTokenProvider returns TokenProvider that uses service
// account private key (on disk or in memory) to make access tokens.
func NewServiceAccountTokenProvider(ctx context.Context, jsonKey []byte, path string, scopes []string) (TokenProvider, error) {
	return &serviceAccountTokenProvider{
		ctx:     ctx,
		jsonKey: jsonKey,
		path:    path,
		scopes:  scopes,
	}, nil
}

func (p *serviceAccountTokenProvider) jwtConfig(ctx context.Context) (*jwt.Config, error) {
	jsonKey := p.jsonKey
	if p.path != "" {
		var err error
		logging.Debugf(ctx, "Reading private key from %s", p.path)
		jsonKey, err = ioutil.ReadFile(p.path)
		if err != nil {
			return nil, err
		}
	}
	return google.JWTConfigFromJSON(jsonKey, p.scopes...)
}

func (p *serviceAccountTokenProvider) RequiresInteraction() bool {
	return false
}

func (p *serviceAccountTokenProvider) Lightweight() bool {
	return false
}

func (p *serviceAccountTokenProvider) Email() string {
	switch cfg, err := p.jwtConfig(p.ctx); {
	case err != nil:
		// Return UnknownEmail since we couldn't load it. This will trigger a code
		// path that attempts to refresh the token, where this error will be hit
		// again and properly reported.
		return UnknownEmail
	case cfg.Email == "":
		// Service account JSON file doesn't have 'email' field. Assume the email
		// is not available in that case. Strictly speaking we may try to generate
		// an OAuth token and then ask token info endpoint for an email, but this is
		// too much work. We require 'email' field to be present instead.
		return NoEmail
	default:
		return cfg.Email
	}
}

func (p *serviceAccountTokenProvider) CacheKey(ctx context.Context) (*CacheKey, error) {
	cfg, err := p.jwtConfig(ctx)
	if err != nil {
		logging.Errorf(ctx, "Failed to load private key JSON - %s", err)
		return nil, ErrBadCredentials
	}
	// PrivateKeyID is optional part of the private key JSON. If not given, use
	// a digest of the private key itself. This ID is used strictly locally, it
	// doesn't matter how we get it as long as it is repeatable between process
	// invocations.
	pkeyID := cfg.PrivateKeyID
	if pkeyID == "" {
		h := sha256.New()
		h.Write(cfg.PrivateKey)
		pkeyID = "custom:" + hex.EncodeToString(h.Sum(nil))
	}
	return &CacheKey{
		Key:    fmt.Sprintf("service_account/%s/%s", cfg.Email, pkeyID),
		Scopes: p.scopes,
	}, nil
}

func (p *serviceAccountTokenProvider) MintToken(ctx context.Context, base *Token) (*Token, error) {
	cfg, err := p.jwtConfig(ctx)
	if err != nil {
		logging.Errorf(ctx, "Failed to load private key JSON - %s", err)
		return nil, ErrBadCredentials
	}
	switch newTok, err := grabToken(cfg.TokenSource(ctx)); {
	case err == nil:
		email := cfg.Email
		if email == "" {
			email = NoEmail
		}
		return &Token{
			Token: *newTok,
			Email: email,
		}, nil
	case transient.Tag.In(err):
		logging.Warningf(ctx, "Error when creating access token - %s", err)
		return nil, err
	default:
		logging.Warningf(ctx, "Invalid or revoked service account key - %s", err)
		return nil, ErrBadCredentials
	}
}

func (p *serviceAccountTokenProvider) RefreshToken(ctx context.Context, prev, base *Token) (*Token, error) {
	// JWT tokens are self sufficient, there's no need for refresh_token. Minting
	// a token and "refreshing" it is a same thing.
	return p.MintToken(ctx, base)
}


/*
**********************************************************************
*   Copyright (C) 1999-2011, International Business Machines
*   Corporation and others.  All Rights Reserved.
**********************************************************************
*   file name:  ustr_imp.h
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 2001jan30
*   created by: Markus W. Scherer
*/

#ifndef __USTR_IMP_H__
#define __USTR_IMP_H__

#include "unicode/utypes.h"
#include "unicode/uiter.h"
#include "ucase.h"

/** Simple declaration to avoid including unicode/ubrk.h. */
#ifndef UBRK_TYPEDEF_UBREAK_ITERATOR
#   define UBRK_TYPEDEF_UBREAK_ITERATOR
    typedef struct UBreakIterator UBreakIterator;
#endif

#ifndef U_COMPARE_IGNORE_CASE
/* see also unorm.h */
/**
 * Option bit for unorm_compare:
 * Perform case-insensitive comparison.
 */
#define U_COMPARE_IGNORE_CASE       0x10000
#endif

/**
 * Internal option for unorm_cmpEquivFold() for strncmp style.
 * If set, checks for both string length and terminating NUL.
 */
#define _STRNCMP_STYLE 0x1000

/**
 * Compare two strings in code point order or code unit order.
 * Works in strcmp style (both lengths -1),
 * strncmp style (lengths equal and >=0, flag TRUE),
 * and memcmp/UnicodeString style (at least one length >=0).
 */
U_CFUNC int32_t U_EXPORT2
uprv_strCompare(const UChar *s1, int32_t length1,
                const UChar *s2, int32_t length2,
                UBool strncmpStyle, UBool codePointOrder);

/**
 * Internal API, used by u_strcasecmp() etc.
 * Compare strings case-insensitively,
 * in code point order or code unit order.
 */
U_CFUNC int32_t
u_strcmpFold(const UChar *s1, int32_t length1,
             const UChar *s2, int32_t length2,
             uint32_t options,
             UErrorCode *pErrorCode);

/**
 * Are the Unicode properties loaded?
 * This must be used before internal functions are called that do
 * not perform this check.
 * Generate a debug assertion failure if data is not loaded.
 */
U_CFUNC UBool
uprv_haveProperties(UErrorCode *pErrorCode);

/**
  * Load the Unicode property data.
  * Intended primarily for use from u_init().
  * Has no effect if property data is already loaded.
  * NOT thread safe.
  */
/*U_CFUNC int8_t
uprv_loadPropsData(UErrorCode *errorCode);*/

/*
 * Internal string casing functions implementing
 * ustring.h/ustrcase.c and UnicodeString case mapping functions.
 */

struct UCaseMap {
    const UCaseProps *csp;
#if !UCONFIG_NO_BREAK_ITERATION
    UBreakIterator *iter;  /* We adopt the iterator, so we own it. */
#endif
    char locale[32];
    int32_t locCache;
    uint32_t options;
};

#ifndef __UCASEMAP_H__
typedef struct UCaseMap UCaseMap;
#endif

#if UCONFIG_NO_BREAK_ITERATION
#   define UCASEMAP_INITIALIZER { NULL, { 0 }, 0, 0 }
#else
#   define UCASEMAP_INITIALIZER { NULL, NULL, { 0 }, 0, 0 }
#endif

U_CFUNC void
ustrcase_setTempCaseMapLocale(UCaseMap *csm, const char *locale);

#ifndef U_STRING_CASE_MAPPER_DEFINED
#define U_STRING_CASE_MAPPER_DEFINED

/**
 * String case mapping function type, used by ustrcase_map().
 * All error checking must be done.
 * The UCaseMap must be fully initialized, with locale and/or iter set as needed.
 * src and dest must not overlap.
 */
typedef int32_t U_CALLCONV
UStringCaseMapper(const UCaseMap *csm,
                  UChar *dest, int32_t destCapacity,
                  const UChar *src, int32_t srcLength,
                  UErrorCode *pErrorCode);

#endif

/** Implements UStringCaseMapper. */
U_CFUNC int32_t U_CALLCONV
ustrcase_internalToLower(const UCaseMap *csm,
                         UChar *dest, int32_t destCapacity,
                         const UChar *src, int32_t srcLength,
                         UErrorCode *pErrorCode);

/** Implements UStringCaseMapper. */
U_CFUNC int32_t U_CALLCONV
ustrcase_internalToUpper(const UCaseMap *csm,
                         UChar *dest, int32_t destCapacity,
                         const UChar *src, int32_t srcLength,
                         UErrorCode *pErrorCode);

#if !UCONFIG_NO_BREAK_ITERATION

/** Implements UStringCaseMapper. */
U_CFUNC int32_t U_CALLCONV
ustrcase_internalToTitle(const UCaseMap *csm,
                         UChar *dest, int32_t destCapacity,
                         const UChar *src, int32_t srcLength,
                         UErrorCode *pErrorCode);

#endif

/** Implements UStringCaseMapper. */
U_CFUNC int32_t U_CALLCONV
ustrcase_internalFold(const UCaseMap *csm,
                      UChar *dest, int32_t destCapacity,
                      const UChar *src, int32_t srcLength,
                      UErrorCode *pErrorCode);

/**
 * Implements argument checking and buffer handling
 * for string case mapping as a common function.
 */
U_CFUNC int32_t
ustrcase_map(const UCaseMap *csm,
             UChar *dest, int32_t destCapacity,
             const UChar *src, int32_t srcLength,
             UStringCaseMapper *stringCaseMapper,
             UErrorCode *pErrorCode);

/**
 * UTF-8 string case mapping function type, used by ucasemap_mapUTF8().
 * UTF-8 version of UStringCaseMapper.
 * All error checking must be done.
 * The UCaseMap must be fully initialized, with locale and/or iter set as needed.
 * src and dest must not overlap.
 */
typedef int32_t U_CALLCONV
UTF8CaseMapper(const UCaseMap *csm,
               uint8_t *dest, int32_t destCapacity,
               const uint8_t *src, int32_t srcLength,
               UErrorCode *pErrorCode);

/** Implements UTF8CaseMapper. */
U_CFUNC int32_t U_CALLCONV
ucasemap_internalUTF8ToTitle(const UCaseMap *csm,
         uint8_t *dest, int32_t destCapacity,
         const uint8_t *src, int32_t srcLength,
         UErrorCode *pErrorCode);

/**
 * Implements argument checking and buffer handling
 * for UTF-8 string case mapping as a common function.
 */
U_CFUNC int32_t
ucasemap_mapUTF8(const UCaseMap *csm,
                 uint8_t *dest, int32_t destCapacity,
                 const uint8_t *src, int32_t srcLength,
                 UTF8CaseMapper *stringCaseMapper,
                 UErrorCode *pErrorCode);

U_CAPI int32_t U_EXPORT2
ustr_hashUCharsN(const UChar *str, int32_t length);

U_CAPI int32_t U_EXPORT2
ustr_hashCharsN(const char *str, int32_t length);

U_CAPI int32_t U_EXPORT2
ustr_hashICharsN(const char *str, int32_t length);

/**
 * NUL-terminate a UChar * string if possible.
 * If length  < destCapacity then NUL-terminate.
 * If length == destCapacity then do not terminate but set U_STRING_NOT_TERMINATED_WARNING.
 * If length  > destCapacity then do not terminate but set U_BUFFER_OVERFLOW_ERROR.
 *
 * @param dest Destination buffer, can be NULL if destCapacity==0.
 * @param destCapacity Number of UChars available at dest.
 * @param length Number of UChars that were (to be) written to dest.
 * @param pErrorCode ICU error code.
 * @return length
 */
U_CAPI int32_t U_EXPORT2
u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode);

/**
 * NUL-terminate a char * string if possible.
 * Same as u_terminateUChars() but for a different string type.
 */
U_CAPI int32_t U_EXPORT2
u_terminateChars(char *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode);

/**
 * NUL-terminate a UChar32 * string if possible.
 * Same as u_terminateUChars() but for a different string type.
 */
U_CAPI int32_t U_EXPORT2
u_terminateUChar32s(UChar32 *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode);

/**
 * NUL-terminate a wchar_t * string if possible.
 * Same as u_terminateUChars() but for a different string type.
 */
U_CAPI int32_t U_EXPORT2
u_terminateWChars(wchar_t *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode);

#endif


/*
 * Copyright 2020 Spotify AB
 *
 * 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.
 */

export * from './apis';
export * from './app';
export * from './icons';
export * from './plugin';
export * from './routing';
export * from './types';


module.exports = {
  'chunk': require('./chunk'),
  'compact': require('./compact'),
  'concat': require('./concat'),
  'difference': require('./difference'),
  'differenceBy': require('./differenceBy'),
  'differenceWith': require('./differenceWith'),
  'drop': require('./drop'),
  'dropRight': require('./dropRight'),
  'dropRightWhile': require('./dropRightWhile'),
  'dropWhile': require('./dropWhile'),
  'fill': require('./fill'),
  'findIndex': require('./findIndex'),
  'findLastIndex': require('./findLastIndex'),
  'first': require('./first'),
  'flatten': require('./flatten'),
  'flattenDeep': require('./flattenDeep'),
  'flattenDepth': require('./flattenDepth'),
  'fromPairs': require('./fromPairs'),
  'head': require('./head'),
  'indexOf': require('./indexOf'),
  'initial': require('./initial'),
  'intersection': require('./intersection'),
  'intersectionBy': require('./intersectionBy'),
  'intersectionWith': require('./intersectionWith'),
  'join': require('./join'),
  'last': require('./last'),
  'lastIndexOf': require('./lastIndexOf'),
  'nth': require('./nth'),
  'pull': require('./pull'),
  'pullAll': require('./pullAll'),
  'pullAllBy': require('./pullAllBy'),
  'pullAllWith': require('./pullAllWith'),
  'pullAt': require('./pullAt'),
  'remove': require('./remove'),
  'reverse': require('./reverse'),
  'slice': require('./slice'),
  'sortedIndex': require('./sortedIndex'),
  'sortedIndexBy': require('./sortedIndexBy'),
  'sortedIndexOf': require('./sortedIndexOf'),
  'sortedLastIndex': require('./sortedLastIndex'),
  'sortedLastIndexBy': require('./sortedLastIndexBy'),
  'sortedLastIndexOf': require('./sortedLastIndexOf'),
  'sortedUniq': require('./sortedUniq'),
  'sortedUniqBy': require('./sortedUniqBy'),
  'tail': require('./tail'),
  'take': require('./take'),
  'takeRight': require('./takeRight'),
  'takeRightWhile': require('./takeRightWhile'),
  'takeWhile': require('./takeWhile'),
  'union': require('./union'),
  'unionBy': require('./unionBy'),
  'unionWith': require('./unionWith'),
  'uniq': require('./uniq'),
  'uniqBy': require('./uniqBy'),
  'uniqWith': require('./uniqWith'),
  'unzip': require('./unzip'),
  'unzipWith': require('./unzipWith'),
  'without': require('./without'),
  'xor': require('./xor'),
  'xorBy': require('./xorBy'),
  'xorWith': require('./xorWith'),
  'zip': require('./zip'),
  'zipObject': require('./zipObject'),
  'zipObjectDeep': require('./zipObjectDeep'),
  'zipWith': require('./zipWith')
};


package com.googlecode.bshforandroid;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class BshPreferences extends PreferenceActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Load the preferences from an XML resource
    addPreferencesFromResource(R.xml.preferences);
  }
}


//
//     Generated by class-dump 3.5 (64 bit).
//
//     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//

#import "CDStructures.h"
#import "DVTLibraryDetailEditorController-Protocol.h"

#import "DVTSourceTextViewDelegate-Protocol.h"

@class DVTStackView_ML, IDECodeSnippet, NSArray, NSMutableArray, NSString;

@interface IDECodeSnippetLibraryDetailEditorController : DVTLibraryDetailEditorController <DVTSourceTextViewDelegate>
{
    DVTStackView_ML *_completionScopesStackView;
    NSMutableArray *_scopeRowControllers;
    NSArray *_platformFamilies;
    NSArray *_languages;
}

+ (id)keyPathsForValuesAffectingCanRemoveCompletionScope;
+ (id)keyPathsForValuesAffectingCanAddCompletionScope;
+ (id)keyPathsForValuesAffectingCompletionScopeRowValues;
+ (void)initialize;
- (void)didChangeCurrentDetailController;
- (void)willChangeCurrentDetailController;
- (void)_fixKeyViewLoop;
- (void)_updateScopesStackWithInsertHint:(unsigned long long)arg1;
- (BOOL)replaceCompletionScope:(id)arg1 withScope:(id)arg2;
- (BOOL)removeCompletionScope:(id)arg1;
- (BOOL)addCompletionScopeAfterScope:(id)arg1;
@property(readonly) BOOL canRemoveCompletionScope;
@property(readonly) BOOL canAddCompletionScope;
- (void)awakeFromNib;
- (void)textDidChange:(id)arg1;
@property(readonly) IDECodeSnippet *editedCodeSnippet;
- (void)setEditedAsset:(id)arg1;
- (id)sourceTextStorage;
- (id)sourceTextView;
- (id)currentDetailController;
@property(readonly) NSArray *completionScopeRowValues;
- (id)_completionScopesForCurrentLanguage;
@property(readonly) NSArray *platformFamilies;
@property(readonly) NSArray *languages;
- (void)primitiveInvalidate;
- (void)viewWillUninstall;
- (id)initWithDidEditHandlerBlock:(dispatch_block_t)arg1;

// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;

@end


<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="generator" content="Apache Maven Doxia Site Renderer 1.9.2" />
    <title>Permazen RocksDB Key/Value Store – Project Plugin Management</title>
    <link rel="stylesheet" href="./css/maven-base.css" />
    <link rel="stylesheet" href="./css/maven-theme.css" />
    <link rel="stylesheet" href="./css/site.css" />
    <link rel="stylesheet" href="./css/print.css" media="print" />

Permazen RocksDB Key/Value Store

        Last Published: 2020-04-14
           | Version: 4.1.6

Permazen RocksDB Key/Value Store

Parent Project

Permazen

Project Documentation

Project Information

Dependencies

Dependency Information

Dependency Management

Distribution Management

About

Issue Management

Licenses

Plugin Management

Plugins

Source Code Management

Summary

Team

Project Plugin Management

GroupId
ArtifactId
Version

org.apache.maven.plugins
maven-antrun-plugin
1.3

org.apache.maven.plugins
maven-assembly-plugin
2.2-beta-5

org.apache.maven.plugins
maven-dependency-plugin
2.8

org.apache.maven.plugins
maven-release-plugin
2.5.3

        Copyright ©      2020..


package appcli

import (
	"bytes"
	"os"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/rliebz/tusk/marshal"
	"github.com/rliebz/tusk/runner"
	"github.com/urfave/cli"
)

func TestDefaultComplete(t *testing.T) {
	tests := []struct {
		name     string
		narg     int
		trailing string
		flagsSet []string
		want     string
	}{
		{
			name:     "invalid input",
			narg:     1,
			want:     ``,
			trailing: "foo",
		},
		{
			name: "default completion",
			want: `normal
foo:a foo command
--bool:a boolean value
--string:a string value
`,
			trailing: "tusk",
		},
		{
			name: "ignores set values",
			want: `normal
foo:a foo command
--string:a string value
`,
			trailing: "--bool",
			flagsSet: []string{"bool"},
		},
		{
			name: "flag completion",
			want: `file
`,
			trailing: "--string",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			defer func(args []string) {
				os.Args = args
			}(os.Args)
			// We only care about the "trailing" arg, second from last
			os.Args = []string{tt.trailing, "--"}

			var buf bytes.Buffer
			app := cli.NewApp()
			app.Commands = []cli.Command{
				{
					Name:  "foo",
					Usage: "a foo command",
					Flags: []cli.Flag{
						cli.BoolFlag{
							Name:  "foo-flag",
							Usage: "a flag for foo",
						},
					},
				},
			}
			app.Flags = []cli.Flag{
				cli.BoolFlag{
					Name:  "bool",
					Usage: "a boolean value",
				},
				cli.StringFlag{
					Name:  "string",
					Usage: "a string value",
				},
			}

			c := mockContext{
				narg:  tt.narg,
				flags: tt.flagsSet,
			}
			defaultComplete(&buf, c, app)

			if diff := cmp.Diff(tt.want, buf.String()); diff != "" {
				t.Errorf("completion output differs:\n%s", diff)
			}
		})
	}
}

func TestCommandComplete(t *testing.T) {
	tests := []struct {
		name     string
		command  *cli.Command
		narg     int
		taskArgs runner.Args
		flagsSet []string
		trailing string
		want     string
	}{
		{
			name: "default",
			want: `task-no-args
--bool:a boolean flag
--string:a string flag
--values:a flag with limited allowed values
`,
			trailing: "my-cmd",
		},
		{
			name: "first arg",
			want: `task-args
foo
bar
--bool:a boolean flag
--string:a string flag
--values:a flag with limited allowed values
`,
			taskArgs: runner.Args{
				{
					Name: "first",
					ValueWithList: runner.ValueWithList{
						ValuesAllowed: []string{"foo", "bar"},
					},
				},
				{
					Name: "second",
					ValueWithList: runner.ValueWithList{
						ValuesAllowed: []string{"baz"},
					},
				},
			},
			trailing: "my-cmd",
		},
		{
			name: "second arg",
			want: `task-args
baz
--bool:a boolean flag
--string:a string flag
--values:a flag with limited allowed values
`,
			taskArgs: runner.Args{
				{
					Name: "first",
					ValueWithList: runner.ValueWithList{
						ValuesAllowed: []string{"foo", "bar"},
					},
				},
				{
					Name: "second",
					ValueWithList: runner.ValueWithList{
						ValuesAllowed: []string{"baz"},
					},
				},
			},
			narg:     1,
			trailing: "my-cmd",
		},
		{
			name: "args with a flag set",
			want: `task-args
foo
bar
baz
--bool:a boolean flag
--values:a flag with limited allowed values
`,
			taskArgs: runner.Args{
				{
					Name: "foo",
					ValueWithList: runner.ValueWithList{
						ValuesAllowed: []string{"foo", "bar", "baz"},
					},
				},
			},
			flagsSet: []string{"string"},
			trailing: "my-cmd",
		},
		{
			name:     "string option",
			want:     "file\n",
			trailing: "--string",
		},
		{
			name: "string option with values",
			want: `value
foo
bar
baz
`,
			trailing: "--values",
		},
		{
			name: "boolean no values",
			want: `task-no-args
--string:a string flag
--values:a flag with limited allowed values
`,
			flagsSet: []string{"bool"},
			trailing: "--bool",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			defer func(args []string) {
				os.Args = args
			}(os.Args)
			// We only care about the "trailing" arg, second from last
			os.Args = []string{tt.trailing, "--"}

			var buf bytes.Buffer

			cmd := &cli.Command{
				Name:  "my-cmd",
				Usage: "a command",
				Flags: []cli.Flag{
					cli.BoolFlag{
						Name:  "bool",
						Usage: "a boolean flag",
					},
					cli.StringFlag{
						Name:  "string",
						Usage: "a string flag",
					},
					cli.StringFlag{
						Name:  "values",
						Usage: "a flag with limited allowed values",
					},
				},
			}

			cfg := &runner.Config{
				Tasks: map[string]*runner.Task{
					cmd.Name: {
						Args: tt.taskArgs,
						Options: runner.Options{
							{Name: "bool", Type: "bool"},
							{Name: "string"},
							{
								Name: "values",
								ValueWithList: runner.ValueWithList{
									ValuesAllowed: marshal.StringList{"foo", "bar", "baz"},
								},
							},
						},
					},
				},
			}

			c := mockContext{
				narg:  tt.narg,
				flags: tt.flagsSet,
			}

			commandComplete(&buf, c, cmd, cfg)

			if diff := cmp.Diff(tt.want, buf.String()); diff != "" {
				t.Errorf("completion output differs:\n%v", diff)
			}
		})
	}
}

func TestPrintCommand(t *testing.T) {
	tests := []struct {
		name    string
		command *cli.Command
		want    string
	}{
		{
			name: "arg without usage",
			command: &cli.Command{
				Name: "my-cmd",
			},
			want: "my-cmd\n",
		},
		{
			name: "arg with usage",
			command: &cli.Command{
				Name:  "my-cmd",
				Usage: "My description",
			},
			want: "my-cmd:My description\n",
		},
		{
			name: "arg without usage escapes colon",
			command: &cli.Command{
				Name: "my:cmd",
			},
			want: "my\\:cmd\n",
		},
		{
			name: "arg with usage escapes colon",
			command: &cli.Command{
				Name:  "my:cmd",
				Usage: "My description",
			},
			want: "my\\:cmd:My description\n",
		},
		{
			name: "hidden",
			command: &cli.Command{
				Name:   "my-cmd",
				Usage:  "My description",
				Hidden: true,
			},
			want: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var buf bytes.Buffer

			printCommand(&buf, tt.command)

			if diff := cmp.Diff(tt.want, buf.String()); diff != "" {
				t.Errorf("completion output differs:\n%v", diff)
			}
		})
	}
}

func TestPrintFlag(t *testing.T) {
	tests := []struct {
		name string
		flag cli.Flag
		want string
	}{
		{
			name: "flag without usage",
			flag: &cli.BoolFlag{
				Name: "my-flag",
			},
			want: "--my-flag\n",
		},
		{
			name: "arg with usage",
			flag: &cli.BoolFlag{
				Name:  "my-flag",
				Usage: "My description",
			},
			want: "--my-flag:My description\n",
		},
		{
			name: "arg without usage escapes colon",
			flag: &cli.BoolFlag{
				Name: "my:flag",
			},
			want: "--my\\:flag\n",
		},
		{
			name: "arg with usage escapes colon",
			flag: &cli.BoolFlag{
				Name:  "my:flag",
				Usage: "My description",
			},
			want: "--my\\:flag:My description\n",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			var buf bytes.Buffer
			var c mockContext

			printFlag(&buf, c, tt.flag)

			if diff := cmp.Diff(tt.want, buf.String()); diff != "" {
				t.Errorf("completion output differs:\n%v", diff)
			}
		})
	}
}

func TestIsCompletingFlagArg(t *testing.T) {
	tests := []struct {
		flags    []cli.Flag
		arg      string
		expected bool
	}{
		{[]cli.Flag{}, "foo", false},
		{[]cli.Flag{}, "-f", false},
		{[]cli.Flag{}, "--foo", false},
		{[]cli.Flag{cli.BoolFlag{Name: "f, foo"}}, "-f", false},
		{[]cli.Flag{cli.BoolFlag{Name: "f, foo"}}, "--foo", false},
		{[]cli.Flag{cli.BoolTFlag{Name: "f, foo"}}, "-f", false},
		{[]cli.Flag{cli.BoolTFlag{Name: "f, foo"}}, "--foo", false},
		{[]cli.Flag{cli.StringFlag{Name: "f, foo"}}, "-f", true},
		{[]cli.Flag{cli.StringFlag{Name: "f, foo"}}, "--foo", true},
		{[]cli.Flag{cli.StringFlag{Name: "f, foo"}}, "--f", false},
		{[]cli.Flag{cli.StringFlag{Name: "b, bar"}}, "-f", false},
		{[]cli.Flag{cli.StringFlag{Name: "b, bar"}}, "--foo", false},
		{[]cli.Flag{cli.StringFlag{Name: "f, foo"}, cli.StringFlag{Name: "b, bar"}}, "-f", true},
		{[]cli.Flag{cli.StringFlag{Name: "f, foo"}, cli.StringFlag{Name: "b, bar"}}, "--foo", true},
	}

	for _, tt := range tests {
		actual := isCompletingFlagArg(tt.flags, tt.arg)
		if tt.expected != actual {
			t.Errorf(
				"isCompletingFlagArg(%#v, %s) => %t, want %t",
				tt.flags, tt.arg, actual, tt.expected,
			)
		}
	}
}

type mockContext struct {
	narg  int
	flags []string
}

func (m mockContext) NArg() int {
	return m.narg
}

func (m mockContext) IsSet(name string) bool {
	for _, flag := range m.flags {
		if flag == name {
			return true
		}
	}

	return false
}