/*-
 * Copyright (c) 2003-2007 Tim Kientzle
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "archive_platform.h"
__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_pax.c,v 1.49 2008/09/30 03:57:07 kientzle Exp $");

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include "archive.h"
#include "archive_entry.h"
#include "archive_private.h"
#include "archive_write_private.h"

struct pax {
	uint64_t	entry_bytes_remaining;
	uint64_t	entry_padding;
	struct archive_string	pax_header;
};

static void		 add_pax_attr(struct archive_string *, const char *key,
			     const char *value);
static void		 add_pax_attr_int(struct archive_string *,
			     const char *key, int64_t value);
static void		 add_pax_attr_time(struct archive_string *,
			     const char *key, int64_t sec,
			     unsigned long nanos);
static void		 add_pax_attr_w(struct archive_string *,
			     const char *key, const wchar_t *wvalue);
static ssize_t		 archive_write_pax_data(struct archive_write *,
			     const void *, size_t);
static int		 archive_write_pax_data_skip(struct archive_write *,
			     off_t);
static int		 archive_write_pax_finish(struct archive_write *);
static int		 archive_write_pax_destroy(struct archive_write *);
static int		 archive_write_pax_finish_entry(struct archive_write *);
static int		 archive_write_pax_header(struct archive_write *,
			     struct archive_entry *);
static char		*base64_encode(const char *src, size_t len);
static char		*build_pax_attribute_name(char *dest, const char *src);
static char		*build_ustar_entry_name(char *dest, const char *src,
			     size_t src_length, const char *insert);
static char		*format_int(char *dest, int64_t);
static int		 has_non_ASCII(const wchar_t *);
static char		*url_encode(const char *in);
static int		 write_nulls(struct archive_write *, size_t);

static void
errmsg(const char *m)
{
	size_t s = strlen(m);
	ssize_t written;

	while (s > 0) {
		written = write(2, m, strlen(m));
		if (written <= 0)
			return;
		m += written;
		s -= written;
	}
}

/*
 * Set output format to 'restricted pax' format.
 *
 * This is the same as normal 'pax', but tries to suppress
 * the pax header whenever possible.  This is the default for
 * bsdtar, for instance.
 */
int
archive_write_set_format_pax_restricted(struct archive *_a)
{
	struct archive_write *a = (struct archive_write *)_a;
	int r;
	r = archive_write_set_format_pax(&a->archive);
	a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
	a->archive.archive_format_name = "restricted POSIX pax interchange";
	return (r);
}

/*
 * Set output format to 'pax' format.
 */
int
archive_write_set_format_pax(struct archive *_a)
{
	struct archive_write *a = (struct archive_write *)_a;
	struct pax *pax;

	if (a->format_destroy != NULL)
		(a->format_destroy)(a);

	pax = (struct pax *)malloc(sizeof(*pax));
	if (pax == NULL) {
		archive_set_error(&a->archive, ENOMEM, "Can't allocate pax data");
		return (ARCHIVE_FATAL);
	}
	memset(pax, 0, sizeof(*pax));
	a->format_data = pax;

	a->pad_uncompressed = 1;
	a->format_name = "pax";
	a->format_write_header = archive_write_pax_header;
	a->format_write_data = archive_write_pax_data;
	a->format_finish = archive_write_pax_finish;
	a->format_destroy = archive_write_pax_destroy;
	a->format_finish_entry = archive_write_pax_finish_entry;
	a->format_skip_data = archive_write_pax_data_skip;
	a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
	a->archive.archive_format_name = "POSIX pax interchange";
	return (ARCHIVE_OK);
}

/*
 * Note: This code assumes that 'nanos' has the same sign as 'sec',
 * which implies that sec=-1, nanos=200000000 represents -1.2 seconds
 * and not -0.8 seconds.  This is a pretty pedantic point, as we're
 * unlikely to encounter many real files created before Jan 1, 1970,
 * much less ones with timestamps recorded to sub-second resolution.
 */
static void
add_pax_attr_time(struct archive_string *as, const char *key,
    int64_t sec, unsigned long nanos)
{
	int digit, i;
	char *t;
	/*
	 * Note that each byte contributes fewer than 3 base-10
	 * digits, so this will always be big enough.
	 */
	char tmp[1 + 3*sizeof(sec) + 1 + 3*sizeof(nanos)];

	tmp[sizeof(tmp) - 1] = 0;
	t = tmp + sizeof(tmp) - 1;

	/* Skip trailing zeros in the fractional part. */
	for (digit = 0, i = 10; i > 0 && digit == 0; i--) {
		digit = nanos % 10;
		nanos /= 10;
	}

	/* Only format the fraction if it's non-zero. */
	if (i > 0) {
		while (i > 0) {
			*--t = "0123456789"[digit];
			digit = nanos % 10;
			nanos /= 10;
			i--;
		}
		*--t = '.';
	}
	t = format_int(t, sec);

	add_pax_attr(as, key, t);
}

static char *
format_int(char *t, int64_t i)
{
	uint64_t ui;

	if (i < 0)
		ui = (i == INT64_MIN) ? (uint64_t)(INT64_MAX) + 1 : (uint64_t)(-i);
	else
		ui = i;

	do {
		*--t = "0123456789"[ui % 10];
	} while (ui /= 10);
	if (i < 0)
		*--t = '-';
	return (t);
}

static void
add_pax_attr_int(struct archive_string *as, const char *key, int64_t value)
{
	char tmp[1 + 3 * sizeof(value)];

	tmp[sizeof(tmp) - 1] = 0;
	add_pax_attr(as, key, format_int(tmp + sizeof(tmp) - 1, value));
}

static char *
utf8_encode(const wchar_t *wval)
{
	int utf8len;
	const wchar_t *wp;
	unsigned long wc;
	char *utf8_value, *p;

	utf8len = 0;
	for (wp = wval; *wp != L'\0'; ) {
		wc = *wp++;

		if (wc >= 0xd800 && wc <= 0xdbff
		    && *wp >= 0xdc00 && *wp <= 0xdfff) {
			/* This is a surrogate pair.  Combine into a
			 * full Unicode value before encoding into
			 * UTF-8. */
			wc = (wc - 0xd800) << 10; /* High 10 bits */
			wc += (*wp++ - 0xdc00); /* Low 10 bits */
			wc += 0x10000; /* Skip BMP */
		}
		if (wc <= 0x7f)
			utf8len++;
		else if (wc <= 0x7ff)
			utf8len += 2;
		else if (wc <= 0xffff)
			utf8len += 3;
		else if (wc <= 0x1fffff)
			utf8len += 4;
		else if (wc <= 0x3ffffff)
			utf8len += 5;
		else if (wc <= 0x7fffffff)
			utf8len += 6;
		/* Ignore larger values; UTF-8 can't encode them. */
	}

	utf8_value = (char *)malloc(utf8len + 1);
	if (utf8_value == NULL) {
		__archive_errx(1, "Not enough memory for attributes");
		return (NULL);
	}

	for (wp = wval, p = utf8_value; *wp != L'\0'; ) {
		wc = *wp++;
		if (wc >= 0xd800 && wc <= 0xdbff
		    && *wp >= 0xdc00 && *wp <= 0xdfff) {
			/* Combine surrogate pair. */
			wc = (wc - 0xd800) << 10;
			wc += *wp++ - 0xdc00 + 0x10000;
		}
		if (wc <= 0x7f) {
			*p++ = (char)wc;
		} else if (wc <= 0x7ff) {
			p[0] = 0xc0 | ((wc >> 6) & 0x1f);
			p[1] = 0x80 | (wc & 0x3f);
			p += 2;
		} else if (wc <= 0xffff) {
			p[0] = 0xe0 | ((wc >> 12) & 0x0f);
			p[1] = 0x80 | ((wc >> 6) & 0x3f);
			p[2] = 0x80 | (wc & 0x3f);
			p += 3;
		} else if (wc <= 0x1fffff) {
			p[0] = 0xf0 | ((wc >> 18) & 0x07);
			p[1] = 0x80 | ((wc >> 12) & 0x3f);
			p[2] = 0x80 | ((wc >> 6) & 0x3f);
			p[3] = 0x80 | (wc & 0x3f);
			p += 4;
		} else if (wc <= 0x3ffffff) {
			p[0] = 0xf8 | ((wc >> 24) & 0x03);
			p[1] = 0x80 | ((wc >> 18) & 0x3f);
			p[2] = 0x80 | ((wc >> 12) & 0x3f);
			p[3] = 0x80 | ((wc >> 6) & 0x3f);
			p[4] = 0x80 | (wc & 0x3f);
			p += 5;
		} else if (wc <= 0x7fffffff) {
			p[0] = 0xfc | ((wc >> 30) & 0x01);
			p[1] = 0x80 | ((wc >> 24) & 0x3f);
			p[1] = 0x80 | ((wc >> 18) & 0x3f);
			p[2] = 0x80 | ((wc >> 12) & 0x3f);
			p[3] = 0x80 | ((wc >> 6) & 0x3f);
			p[4] = 0x80 | (wc & 0x3f);
			p += 6;
		}
		/* Ignore larger values; UTF-8 can't encode them. */
	}
	*p = '\0';

	return (utf8_value);
}

static void
add_pax_attr_w(struct archive_string *as, const char *key, const wchar_t *wval)
{
	char *utf8_value = utf8_encode(wval);
	if (utf8_value == NULL)
		return;
	add_pax_attr(as, key, utf8_value);
	free(utf8_value);
}

/*
 * Add a key/value attribute to the pax header.  This function handles
 * the length field and various other syntactic requirements.
 */
static void
add_pax_attr(struct archive_string *as, const char *key, const char *value)
{
	int digits, i, len, next_ten;
	char tmp[1 + 3 * sizeof(int)];	/* < 3 base-10 digits per byte */

	/*-
	 * PAX attributes have the following layout:
	 *     <len> <space> <key> <=> <value> <nl>
	 */
	len = 1 + strlen(key) + 1 + strlen(value) + 1;

	/*
	 * The <len> field includes the length of the <len> field, so
	 * computing the correct length is tricky.  I start by
	 * counting the number of base-10 digits in 'len' and
	 * computing the next higher power of 10.
	 */
	next_ten = 1;
	digits = 0;
	i = len;
	while (i > 0) {
		i = i / 10;
		digits++;
		next_ten = next_ten * 10;
	}
	/*
	 * For example, if string without the length field is 99
	 * chars, then adding the 2 digit length "99" will force the
	 * total length past 100, requiring an extra digit.  The next
	 * statement adjusts for this effect.
	 */
	if (len + digits >= next_ten)
		digits++;

	/* Now, we have the right length so we can build the line. */
	tmp[sizeof(tmp) - 1] = 0;	/* Null-terminate the work area. */
	archive_strcat(as, format_int(tmp + sizeof(tmp) - 1, len + digits));
	archive_strappend_char(as, ' ');
	archive_strcat(as, key);
	archive_strappend_char(as, '=');
	archive_strcat(as, value);
	archive_strappend_char(as, '\n');
}

static void
archive_write_pax_header_xattrs(struct pax *pax, struct archive_entry *entry)
{
	struct archive_string s;
	int i = archive_entry_xattr_reset(entry);

	while (i--) {
		const char *name;
		const void *value;
		char *encoded_value;
		char *url_encoded_name = NULL, *encoded_name = NULL;
		wchar_t *wcs_name = NULL;
		size_t size;

		archive_entry_xattr_next(entry, &name, &value, &size);
		/* Name is URL-encoded, then converted to wchar_t,
		 * then UTF-8 encoded. */
		url_encoded_name = url_encode(name);
		if (url_encoded_name != NULL) {
			/* Convert narrow-character to wide-character. */
			int wcs_length = strlen(url_encoded_name);
			wcs_name = (wchar_t *)malloc((wcs_length + 1) * sizeof(wchar_t));
			if (wcs_name == NULL)
				__archive_errx(1, "No memory for xattr conversion");
			mbstowcs(wcs_name, url_encoded_name, wcs_length);
			wcs_name[wcs_length] = 0;
			free(url_encoded_name); /* Done with this. */
		}
		if (wcs_name != NULL) {
			encoded_name = utf8_encode(wcs_name);
			free(wcs_name); /* Done with wchar_t name. */
		}

		encoded_value = base64_encode((const char *)value, size);

		if (encoded_name != NULL && encoded_value != NULL) {
			archive_string_init(&s);
			archive_strcpy(&s, "LIBARCHIVE.xattr.");
			archive_strcat(&s, encoded_name);
			add_pax_attr(&(pax->pax_header), s.s, encoded_value);
			archive_string_free(&s);
		}
		free(encoded_name);
		free(encoded_value);
	}
}

/*
 * TODO: Consider adding 'comment' and 'charset' fields to
 * archive_entry so that clients can specify them.  Also, consider
 * adding generic key/value tags so clients can add arbitrary
 * key/value data.
 */
static int
archive_write_pax_header(struct archive_write *a,
    struct archive_entry *entry_original)
{
	struct archive_entry *entry_main;
	const char *p;
	char *t;
	const wchar_t *wp;
	const char *suffix;
	int need_extension, r, ret;
	struct pax *pax;
	const char *hdrcharset = NULL;
	const char *hardlink;
	const char *path = NULL, *linkpath = NULL;
	const char *uname = NULL, *gname = NULL;
	const wchar_t *path_w = NULL, *linkpath_w = NULL;
	const wchar_t *uname_w = NULL, *gname_w = NULL;

	char paxbuff[512];
	char ustarbuff[512];
	char ustar_entry_name[256];
	char pax_entry_name[256];

	ret = ARCHIVE_OK;
	need_extension = 0;
	pax = (struct pax *)a->format_data;

	hardlink = archive_entry_hardlink(entry_original);

	/* Make sure this is a type of entry that we can handle here */
	if (hardlink == NULL) {
		switch (archive_entry_filetype(entry_original)) {
		case AE_IFBLK:
		case AE_IFCHR:
		case AE_IFIFO:
		case AE_IFLNK:
		case AE_IFREG:
			break;
		case AE_IFDIR:
			/*
			 * Ensure a trailing '/'.  Modify the original
			 * entry so the client sees the change.
			 */
			p = archive_entry_pathname(entry_original);
			if (p[strlen(p) - 1] != '/') {
				t = (char *)malloc(strlen(p) + 2);
				if (t == NULL) {
					archive_set_error(&a->archive, ENOMEM,
					"Can't allocate pax data");
					return(ARCHIVE_FATAL);
				}
				strcpy(t, p);
				strcat(t, "/");
				archive_entry_copy_pathname(entry_original, t);
				free(t);
			}
			break;
		default:
			archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
			    "tar format cannot archive this (type=0%lo)",
			    (unsigned long)archive_entry_filetype(entry_original));
			return (ARCHIVE_WARN);
		}
	}

	/* Copy entry so we can modify it as needed. */
	entry_main = archive_entry_clone(entry_original);
	archive_string_empty(&(pax->pax_header)); /* Blank our work area. */

	/*
	 * First, check the name fields and see if any of them
	 * require binary coding.  If any of them does, then all of
	 * them do.
	 */
	hdrcharset = NULL;
	path = archive_entry_pathname(entry_main);
	path_w = archive_entry_pathname_w(entry_main);
	if (path != NULL && path_w == NULL) {
		archive_set_error(&a->archive, EILSEQ,
		    "Can't translate pathname '%s' to UTF-8", path);
		ret = ARCHIVE_WARN;
		hdrcharset = "BINARY";
	}
	uname = archive_entry_uname(entry_main);
	uname_w = archive_entry_uname_w(entry_main);
	if (uname != NULL && uname_w == NULL) {
		archive_set_error(&a->archive, EILSEQ,
		    "Can't translate uname '%s' to UTF-8", uname);
		ret = ARCHIVE_WARN;
		hdrcharset = "BINARY";
	}
	gname = archive_entry_gname(entry_main);
	gname_w = archive_entry_gname_w(entry_main);
	if (gname != NULL && gname_w == NULL) {
		archive_set_error(&a->archive, EILSEQ,
		    "Can't translate gname '%s' to UTF-8", gname);
		ret = ARCHIVE_WARN;
		hdrcharset = "BINARY";
	}
	linkpath = hardlink;
	if (linkpath != NULL) {
		linkpath_w = archive_entry_hardlink_w(entry_main);
	} else {
		linkpath = archive_entry_symlink(entry_main);
		if (linkpath != NULL)
			linkpath_w = archive_entry_symlink_w(entry_main);
	}
	if (linkpath != NULL && linkpath_w == NULL) {
		archive_set_error(&a->archive, EILSEQ,
		    "Can't translate linkpath '%s' to UTF-8", linkpath);
		ret = ARCHIVE_WARN;
		hdrcharset = "BINARY";
	}

	/* Store the header encoding first, to be nice to readers. */
	if (hdrcharset != NULL)
		add_pax_attr(&(pax->pax_header), "hdrcharset", hdrcharset);

	/*
	 * If name is too long, or has non-ASCII characters, add
	 * 'path' to pax extended attrs.  (Note that an unconvertible
	 * name must have non-ASCII characters.)
	 */
	if (path == NULL) {
		/* We don't have a narrow version, so we have to store
		 * the wide version. */
		add_pax_attr_w(&(pax->pax_header), "path", path_w);
		archive_entry_set_pathname(entry_main, "@WidePath");
		need_extension = 1;
	} else if (has_non_ASCII(path_w)) {
		/* We have non-ASCII characters. */
		if (path_w == NULL || hdrcharset != NULL) {
			/* Can't do UTF-8, so store it raw. */
			add_pax_attr(&(pax->pax_header), "path", path);
		} else {
			/* Store UTF-8 */
			add_pax_attr_w(&(pax->pax_header),
			    "path", path_w);
		}
		archive_entry_set_pathname(entry_main,
		    build_ustar_entry_name(ustar_entry_name,
			path, strlen(path), NULL));
		need_extension = 1;
	} else {
		/* We have an all-ASCII path; we'd like to just store
		 * it in the ustar header if it will fit.  Yes, this
		 * duplicates some of the logic in
		 * archive_write_set_format_ustar.c
		 */
		if (strlen(path) <= 100) {
			/* Fits in the old 100-char tar name field. */
		} else {
			/* Find largest suffix that will fit. */
			/* Note: strlen() > 100, so strlen() - 100 - 1 >= 0 */
			suffix = strchr(path + strlen(path) - 100 - 1, '/');
			/* Don't attempt an empty prefix. */
			if (suffix == path)
				suffix = strchr(suffix + 1, '/');
			/* We can put it in the ustar header if it's
			 * all ASCII and it's either <= 100 characters
			 * or can be split at a '/' into a prefix <=
			 * 155 chars and a suffix <= 100 chars.  (Note
			 * the strchr() above will return NULL exactly
			 * when the path can't be split.)
			 */
			if (suffix == NULL       /* Suffix > 100 chars. */
			    || suffix[1] == '\0'    /* empty suffix */
			    || suffix - path > 155)  /* Prefix > 155 chars */
			{
				if (path_w == NULL || hdrcharset != NULL) {
					/* Can't do UTF-8, so store it raw. */
					add_pax_attr(&(pax->pax_header),
					    "path", path);
				} else {
					/* Store UTF-8 */
					add_pax_attr_w(&(pax->pax_header),
					    "path", path_w);
				}
				archive_entry_set_pathname(entry_main,
				    build_ustar_entry_name(ustar_entry_name,
					path, strlen(path), NULL));
				need_extension = 1;
			}
		}
	}

	if (linkpath != NULL) {
		/* If link name is too long or has non-ASCII characters, add
		 * 'linkpath' to pax extended attrs. */
		if (strlen(linkpath) > 100 || linkpath_w == NULL
		    || linkpath_w == NULL || has_non_ASCII(linkpath_w)) {
			if (linkpath_w == NULL || hdrcharset != NULL)
				/* If the linkpath is not convertible
				 * to wide, or we're encoding in
				 * binary anyway, store it raw. */
				add_pax_attr(&(pax->pax_header),
				    "linkpath", linkpath);
			else
				/* If the link is long or has a
				 * non-ASCII character, store it as a
				 * pax extended attribute. */
				add_pax_attr_w(&(pax->pax_header),
				    "linkpath", linkpath_w);
			if (strlen(linkpath) > 100) {
				if (hardlink != NULL)
					archive_entry_set_hardlink(entry_main,
					    "././@LongHardLink");
				else
					archive_entry_set_symlink(entry_main,
					    "././@LongSymLink");
			}
			need_extension = 1;
		}
	}

	/* If file size is too large, add 'size' to pax extended attrs. */
	if (archive_entry_size(entry_main) >= (((int64_t)1) << 33)) {
		add_pax_attr_int(&(pax->pax_header), "size",
		    archive_entry_size(entry_main));
		need_extension = 1;
	}

	/* If numeric GID is too large, add 'gid' to pax extended attrs. */
	if (archive_entry_gid(entry_main) >= (1 << 18)) {
		add_pax_attr_int(&(pax->pax_header), "gid",
		    archive_entry_gid(entry_main));
		need_extension = 1;
	}

	/* If group name is too large or has non-ASCII characters, add
	 * 'gname' to pax extended attrs. */
	if (gname != NULL) {
		if (strlen(gname) > 31
		    || gname_w == NULL
		    || has_non_ASCII(gname_w))
		{
			if (gname_w == NULL || hdrcharset != NULL) {
				add_pax_attr(&(pax->pax_header),
				    "gname", gname);
			} else  {
				add_pax_attr_w(&(pax->pax_header),
				    "gname", gname_w);
			}
			need_extension = 1;
		}
	}

	/* If numeric UID is too large, add 'uid' to pax extended attrs. */
	if (archive_entry_uid(entry_main) >= (1 << 18)) {
		add_pax_attr_int(&(pax->pax_header), "uid",
		    archive_entry_uid(entry_main));
		need_extension = 1;
	}

	/* Add 'uname' to pax extended attrs if necessary. */
	if (uname != NULL) {
		if (strlen(uname) > 31
		    || uname_w == NULL
		    || has_non_ASCII(uname_w))
		{
			if (uname_w == NULL || hdrcharset != NULL) {
				add_pax_attr(&(pax->pax_header),
				    "uname", uname);
			} else {
				add_pax_attr_w(&(pax->pax_header),
				    "uname", uname_w);
			}
			need_extension = 1;
		}
	}

	/*
	 * POSIX/SUSv3 doesn't provide a standard key for large device
	 * numbers.  I use the same keys here that Joerg Schilling
	 * used for 'star.'  (Which, somewhat confusingly, are called
	 * "devXXX" even though they code "rdev" values.)  No doubt,
	 * other implementations use other keys.  Note that there's no
	 * reason we can't write the same information into a number of
	 * different keys.
	 *
	 * Of course, this is only needed for block or char device entries.
	 */
	if (archive_entry_filetype(entry_main) == AE_IFBLK
	    || archive_entry_filetype(entry_main) == AE_IFCHR) {
		/*
		 * If rdevmajor is too large, add 'SCHILY.devmajor' to
		 * extended attributes.
		 */
		dev_t rdevmajor, rdevminor;
		rdevmajor = archive_entry_rdevmajor(entry_main);
		rdevminor = archive_entry_rdevminor(entry_main);
		if (rdevmajor >= (1 << 18)) {
			add_pax_attr_int(&(pax->pax_header), "SCHILY.devmajor",
			    rdevmajor);
			/*
			 * Non-strict formatting below means we don't
			 * have to truncate here.  Not truncating improves
			 * the chance that some more modern tar archivers
			 * (such as GNU tar 1.13) can restore the full
			 * value even if they don't understand the pax
			 * extended attributes.  See my rant below about
			 * file size fields for additional details.
			 */
			/* archive_entry_set_rdevmajor(entry_main,
			   rdevmajor & ((1 << 18) - 1)); */
			need_extension = 1;
		}

		/*
		 * If devminor is too large, add 'SCHILY.devminor' to
		 * extended attributes.
		 */
		if (rdevminor >= (1 << 18)) {
			add_pax_attr_int(&(pax->pax_header), "SCHILY.devminor",
			    rdevminor);
			/* Truncation is not necessary here, either. */
			/* archive_entry_set_rdevminor(entry_main,
			   rdevminor & ((1 << 18) - 1)); */
			need_extension = 1;
		}
	}

	/*
	 * Technically, the mtime field in the ustar header can
	 * support 33 bits, but many platforms use signed 32-bit time
	 * values.  The cutoff of 0x7fffffff here is a compromise.
	 * Yes, this check is duplicated just below; this helps to
	 * avoid writing an mtime attribute just to handle a
	 * high-resolution timestamp in "restricted pax" mode.
	 */
	if (!need_extension &&
	    ((archive_entry_mtime(entry_main) < 0)
		|| (archive_entry_mtime(entry_main) >= 0x7fffffff)))
		need_extension = 1;

	/* I use a star-compatible file flag attribute. */
	p = archive_entry_fflags_text(entry_main);
	if (!need_extension && p != NULL  &&  *p != '\0')
		need_extension = 1;

	/* If there are non-trivial ACL entries, we need an extension. */
	if (!need_extension && archive_entry_acl_count(entry_original,
		ARCHIVE_ENTRY_ACL_TYPE_ACCESS) > 0)
		need_extension = 1;

	/* If there are non-trivial ACL entries, we need an extension. */
	if (!need_extension && archive_entry_acl_count(entry_original,
		ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) > 0)
		need_extension = 1;

	/* If there are extended attributes, we need an extension */
	if (!need_extension && archive_entry_xattr_count(entry_original) > 0)
		need_extension = 1;

	/*
	 * The following items are handled differently in "pax
	 * restricted" format.  In particular, in "pax restricted"
	 * format they won't be added unless need_extension is
	 * already set (we're already generating an extended header, so
	 * may as well include these).
	 */
	if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_RESTRICTED ||
	    need_extension) {

		if (archive_entry_mtime(entry_main) < 0  ||
		    archive_entry_mtime(entry_main) >= 0x7fffffff  ||
		    archive_entry_mtime_nsec(entry_main) != 0)
			add_pax_attr_time(&(pax->pax_header), "mtime",
			    archive_entry_mtime(entry_main),
			    archive_entry_mtime_nsec(entry_main));

		if (archive_entry_ctime(entry_main) != 0  ||
		    archive_entry_ctime_nsec(entry_main) != 0)
			add_pax_attr_time(&(pax->pax_header), "ctime",
			    archive_entry_ctime(entry_main),
			    archive_entry_ctime_nsec(entry_main));

		if (archive_entry_atime(entry_main) != 0 ||
		    archive_entry_atime_nsec(entry_main) != 0)
			add_pax_attr_time(&(pax->pax_header), "atime",
			    archive_entry_atime(entry_main),
			    archive_entry_atime_nsec(entry_main));

		/* Store birth/creationtime only if it's earlier than mtime */
		if (archive_entry_birthtime_is_set(entry_main) &&
		    archive_entry_birthtime(entry_main)
		    < archive_entry_mtime(entry_main))
			add_pax_attr_time(&(pax->pax_header),
			    "LIBARCHIVE.creationtime",
			    archive_entry_birthtime(entry_main),
			    archive_entry_birthtime_nsec(entry_main));

		/* I use a star-compatible file flag attribute. */
		p = archive_entry_fflags_text(entry_main);
		if (p != NULL  &&  *p != '\0')
			add_pax_attr(&(pax->pax_header), "SCHILY.fflags", p);

		/* I use star-compatible ACL attributes. */
		wp = archive_entry_acl_text_w(entry_original,
		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
		    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID);
		if (wp != NULL && *wp != L'\0')
			add_pax_attr_w(&(pax->pax_header),
			    "SCHILY.acl.access", wp);
		wp = archive_entry_acl_text_w(entry_original,
		    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
		    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID);
		if (wp != NULL && *wp != L'\0')
			add_pax_attr_w(&(pax->pax_header),
			    "SCHILY.acl.default", wp);

		/* Include star-compatible metadata info. */
		/* Note: "SCHILY.dev{major,minor}" are NOT the
		 * major/minor portions of "SCHILY.dev". */
		add_pax_attr_int(&(pax->pax_header), "SCHILY.dev",
		    archive_entry_dev(entry_main));
		add_pax_attr_int(&(pax->pax_header), "SCHILY.ino",
		    archive_entry_ino(entry_main));
		add_pax_attr_int(&(pax->pax_header), "SCHILY.nlink",
		    archive_entry_nlink(entry_main));

		/* Store extended attributes */
		archive_write_pax_header_xattrs(pax, entry_original);
	}

	/* Only regular files have data. */
	if (archive_entry_filetype(entry_main) != AE_IFREG)
		archive_entry_set_size(entry_main, 0);

	/*
	 * Pax-restricted does not store data for hardlinks, in order
	 * to improve compatibility with ustar.
	 */
	if (a->archive.archive_format != ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE &&
	    hardlink != NULL)
		archive_entry_set_size(entry_main, 0);

	/*
	 * XXX Full pax interchange format does permit a hardlink
	 * entry to have data associated with it.  I'm not supporting
	 * that here because the client expects me to tell them whether
	 * or not this format expects data for hardlinks.  If I
	 * don't check here, then every pax archive will end up with
	 * duplicated data for hardlinks.  Someday, there may be
	 * need to select this behavior, in which case the following
	 * will need to be revisited. XXX
	 */
	if (hardlink != NULL)
		archive_entry_set_size(entry_main, 0);

	/* Format 'ustar' header for main entry.
	 *
	 * The trouble with file size: If the reader can't understand
	 * the file size, they may not be able to locate the next
	 * entry and the rest of the archive is toast.  Pax-compliant
	 * readers are supposed to ignore the file size in the main
	 * header, so the question becomes how to maximize portability
	 * for readers that don't support pax attribute extensions.
	 * For maximum compatibility, I permit numeric extensions in
	 * the main header so that the file size stored will always be
	 * correct, even if it's in a format that only some
	 * implementations understand.  The technique used here is:
	 *
	 *  a) If possible, follow the standard exactly.  This handles
	 *  files up to 8 gigabytes minus 1.
	 *
	 *  b) If that fails, try octal but omit the field terminator.
	 *  That handles files up to 64 gigabytes minus 1.
	 *
	 *  c) Otherwise, use base-256 extensions.  That handles files
	 *  up to 2^63 in this implementation, with the potential to
	 *  go up to 2^94.  That should hold us for a while. ;-)
	 *
	 * The non-strict formatter uses similar logic for other
	 * numeric fields, though they're less critical.
	 */
	__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0);

	/* If we built any extended attributes, write that entry first. */
	if (archive_strlen(&(pax->pax_header)) > 0) {
		struct archive_entry *pax_attr_entry;
		time_t s;
		uid_t uid;
		gid_t gid;
		mode_t mode;
		long ns;

		pax_attr_entry = archive_entry_new();
		p = archive_entry_pathname(entry_main);
		archive_entry_set_pathname(pax_attr_entry,
		    build_pax_attribute_name(pax_entry_name, p));
		archive_entry_set_size(pax_attr_entry,
		    archive_strlen(&(pax->pax_header)));
		/* Copy uid/gid (but clip to ustar limits). */
		uid = archive_entry_uid(entry_main);
		if (uid >= 1 << 18)
			uid = (1 << 18) - 1;
		archive_entry_set_uid(pax_attr_entry, uid);
		gid = archive_entry_gid(entry_main);
		if (gid >= 1 << 18)
			gid = (1 << 18) - 1;
		archive_entry_set_gid(pax_attr_entry, gid);
		/* Copy mode over (but not setuid/setgid bits) */
		mode = archive_entry_mode(entry_main);
#ifdef S_ISUID
		mode &= ~S_ISUID;
#endif
#ifdef S_ISGID
		mode &= ~S_ISGID;
#endif
#ifdef S_ISVTX
		mode &= ~S_ISVTX;
#endif
		archive_entry_set_mode(pax_attr_entry, mode);

		/* Copy uname/gname. */
		archive_entry_set_uname(pax_attr_entry,
		    archive_entry_uname(entry_main));
		archive_entry_set_gname(pax_attr_entry,
		    archive_entry_gname(entry_main));

		/* Copy mtime, but clip to ustar limits. */
		s = archive_entry_mtime(entry_main);
		ns = archive_entry_mtime_nsec(entry_main);
		if (s < 0) { s = 0; ns = 0; }
		if (s > 0x7fffffff) { s = 0x7fffffff; ns = 0; }
		archive_entry_set_mtime(pax_attr_entry, s, ns);

		/* Ditto for atime. */
		s = archive_entry_atime(entry_main);
		ns = archive_entry_atime_nsec(entry_main);
		if (s < 0) { s = 0; ns = 0; }
		if (s > 0x7fffffff) { s = 0x7fffffff; ns = 0; }
		archive_entry_set_atime(pax_attr_entry, s, ns);

		/* Standard ustar doesn't support ctime. */
		archive_entry_set_ctime(pax_attr_entry, 0, 0);

		r = __archive_write_format_header_ustar(a, paxbuff,
		    pax_attr_entry, 'x', 1);

		archive_entry_free(pax_attr_entry);

		/* Note that the 'x' header shouldn't ever fail to format */
		if (r != 0) {
			const char *msg = "archive_write_pax_header: "
			    "'x' header failed?!  This can't happen.\n";
			errmsg(msg);
			exit(1);
		}
		r = (a->compressor.write)(a, paxbuff, 512);
		if (r != ARCHIVE_OK) {
			pax->entry_bytes_remaining = 0;
			pax->entry_padding = 0;
			return (ARCHIVE_FATAL);
		}

		pax->entry_bytes_remaining = archive_strlen(&(pax->pax_header));
		pax->entry_padding = 0x1ff & (-(int64_t)pax->entry_bytes_remaining);

		r = (a->compressor.write)(a, pax->pax_header.s,
		    archive_strlen(&(pax->pax_header)));
		if (r != ARCHIVE_OK) {
			/* If a write fails, we're pretty much toast. */
			return (ARCHIVE_FATAL);
		}
		/* Pad out the end of the entry. */
		r = write_nulls(a, pax->entry_padding);
		if (r != ARCHIVE_OK) {
			/* If a write fails, we're pretty much toast. */
			return (ARCHIVE_FATAL);
		}
		pax->entry_bytes_remaining = pax->entry_padding = 0;
	}

	/* Write the header for main entry. */
	r = (a->compressor.write)(a, ustarbuff, 512);
	if (r != ARCHIVE_OK)
		return (r);

	/*
	 * Inform the client of the on-disk size we're using, so
	 * they can avoid unnecessarily writing a body for something
	 * that we're just going to ignore.
	 */
	archive_entry_set_size(entry_original, archive_entry_size(entry_main));
	pax->entry_bytes_remaining = archive_entry_size(entry_main);
	pax->entry_padding = 0x1ff & (-(int64_t)pax->entry_bytes_remaining);
	archive_entry_free(entry_main);

	return (ret);
}

/*
 * We need a valid name for the regular 'ustar' entry.  This routine
 * tries to hack something more-or-less reasonable.
 *
 * The approach here tries to preserve leading dir names.  We do so by
 * working with four sections:
 *   1) "prefix" directory names,
 *   2) "suffix" directory names,
 *   3) inserted dir name (optional),
 *   4) filename.
 *
 * These sections must satisfy the following requirements:
 *   * Parts 1 & 2 together form an initial portion of the dir name.
 *   * Part 3 is specified by the caller.  (It should not contain a leading
 *     or trailing '/'.)
 *   * Part 4 forms an initial portion of the base filename.
 *   * The filename must be <= 99 chars to fit the ustar 'name' field.
 *   * Parts 2, 3, 4 together must be <= 99 chars to fit the ustar 'name' fld.
 *   * Part 1 must be <= 155 chars to fit the ustar 'prefix' field.
 *   * If the original name ends in a '/', the new name must also end in a '/'
 *   * Trailing '/.' sequences may be stripped.
 *
 * Note: Recall that the ustar format does not store the '/' separating
 * parts 1 & 2, but does store the '/' separating parts 2 & 3.
 */
static char *
build_ustar_entry_name(char *dest, const char *src, size_t src_length,
    const char *insert)
{
	const char *prefix, *prefix_end;
	const char *suffix, *suffix_end;
	const char *filename, *filename_end;
	char *p;
	int need_slash = 0; /* Was there a trailing slash? */
	size_t suffix_length = 99;
	int insert_length;

	/* Length of additional dir element to be added. */
	if (insert == NULL)
		insert_length = 0;
	else
		/* +2 here allows for '/' before and after the insert. */
		insert_length = strlen(insert) + 2;

	/* Step 0: Quick bailout in a common case. */
	if (src_length < 100 && insert == NULL) {
		strncpy(dest, src, src_length);
		dest[src_length] = '\0';
		return (dest);
	}

	/* Step 1: Locate filename and enforce the length restriction. */
	filename_end = src + src_length;
	/* Remove trailing '/' chars and '/.' pairs. */
	for (;;) {
		if (filename_end > src && filename_end[-1] == '/') {
			filename_end --;
			need_slash = 1; /* Remember to restore trailing '/'. */
			continue;
		}
		if (filename_end > src + 1 && filename_end[-1] == '.'
		    && filename_end[-2] == '/') {
			filename_end -= 2;
			need_slash = 1; /* "foo/." will become "foo/" */
			continue;
		}
		break;
	}
	if (need_slash)
		suffix_length--;
	/* Find start of filename. */
	filename = filename_end - 1;
	while ((filename > src) && (*filename != '/'))
		filename --;
	if ((*filename == '/') && (filename < filename_end - 1))
		filename ++;
	/* Adjust filename_end so that filename + insert fits in 99 chars. */
	suffix_length -= insert_length;
	if (filename_end > filename + suffix_length)
		filename_end = filename + suffix_length;
	/* Calculate max size for "suffix" section (#3 above). */
	suffix_length -= filename_end - filename;

	/* Step 2: Locate the "prefix" section of the dirname, including
	 * trailing '/'. */
	prefix = src;
	prefix_end = prefix + 155;
	if (prefix_end > filename)
		prefix_end = filename;
	while (prefix_end > prefix && *prefix_end != '/')
		prefix_end--;
	if ((prefix_end < filename) && (*prefix_end == '/'))
		prefix_end++;

	/* Step 3: Locate the "suffix" section of the dirname,
	 * including trailing '/'. */
	suffix = prefix_end;
	suffix_end = suffix + suffix_length; /* Enforce limit. */
	if (suffix_end > filename)
		suffix_end = filename;
	if (suffix_end < suffix)
		suffix_end = suffix;
	while (suffix_end > suffix && *suffix_end != '/')
		suffix_end--;
	if ((suffix_end < filename) && (*suffix_end == '/'))
		suffix_end++;

	/* Step 4: Build the new name. */
	/* The OpenBSD strlcpy function is safer, but less portable. */
	/* Rather than maintain two versions, just use the strncpy version. */
	p = dest;
	if (prefix_end > prefix) {
		strncpy(p, prefix, prefix_end - prefix);
		p += prefix_end - prefix;
	}
	if (suffix_end > suffix) {
		strncpy(p, suffix, suffix_end - suffix);
		p += suffix_end - suffix;
	}
	if (insert != NULL) {
		/* Note: assume insert does not have leading or trailing '/' */
		strcpy(p, insert);
		p += strlen(insert);
		*p++ = '/';
	}
	strncpy(p, filename, filename_end - filename);
	p += filename_end - filename;
	if (need_slash)
		*p++ = '/';
	*p++ = '\0';

	return (dest);
}

/*
 * The ustar header for the pax extended attributes must have a
 * reasonable name:  SUSv3 requires 'dirname'/PaxHeader.'pid'/'filename'
 * where 'pid' is the PID of the archiving process.  Unfortunately,
 * that makes testing a pain since the output varies for each run,
 * so I'm sticking with the simpler 'dirname'/PaxHeader/'filename'
 * for now.  (Someday, I'll make this settable.  Then I can use the
 * SUS recommendation as default and test harnesses can override it
 * to get predictable results.)
 *
 * Joerg Schilling has argued that this is unnecessary because, in
 * practice, if the pax extended attributes get extracted as regular
 * files, no one is going to bother reading those attributes to
 * manually restore them.  Based on this, 'star' uses
 * /tmp/PaxHeader/'basename' as the ustar header name.  This is a
 * tempting argument, in part because it's simpler than the SUSv3
 * recommendation, but I'm not entirely convinced.  I'm also
 * uncomfortable with the fact that "/tmp" is a Unix-ism.
 *
 * The following routine leverages build_ustar_entry_name() above and
 * so is simpler than you might think.  It just needs to provide the
 * additional path element and handle a few pathological cases).
 */
static char *
build_pax_attribute_name(char *dest, const char *src)
{
	char buff[64];
	const char *p;

	/* Handle the null filename case. */
	if (src == NULL || *src == '\0') {
		strcpy(dest, "PaxHeader/blank");
		return (dest);
	}

	/* Prune final '/' and other unwanted final elements. */
	p = src + strlen(src);
	for (;;) {
		/* Ends in "/", remove the '/' */
		if (p > src && p[-1] == '/') {
			--p;
			continue;
		}
		/* Ends in "/.", remove the '.' */
		if (p > src + 1 && p[-1] == '.'
		    && p[-2] == '/') {
			--p;
			continue;
		}
		break;
	}

	/* Pathological case: After above, there was nothing left.
	 * This includes "/." "/./." "/.//./." etc. */
	if (p == src) {
		strcpy(dest, "/PaxHeader/rootdir");
		return (dest);
	}

	/* Convert unadorned "." into a suitable filename. */
	if (*src == '.' && p == src + 1) {
		strcpy(dest, "PaxHeader/currentdir");
		return (dest);
	}

	/*
	 * TODO: Push this string into the 'pax' structure to avoid
	 * recomputing it every time.  That will also open the door
	 * to having clients override it.
	 */
#if HAVE_GETPID && 0  /* Disable this for now; see above comment. */
	sprintf(buff, "PaxHeader.%d", getpid());
#else
	/* If the platform can't fetch the pid, don't include it. */
	strcpy(buff, "PaxHeader");
#endif
	/* General case: build a ustar-compatible name adding "/PaxHeader/". */
	build_ustar_entry_name(dest, src, p - src, buff);

	return (dest);
}

/* Write two null blocks for the end of archive */
static int
archive_write_pax_finish(struct archive_write *a)
{

	if (a->compressor.write == NULL)
		return (ARCHIVE_OK);

	return (write_nulls(a, 512 * 2));
}

static int
archive_write_pax_destroy(struct archive_write *a)
{
	struct pax *pax;

	pax = (struct pax *)a->format_data;
	if (pax == NULL)
		return (ARCHIVE_OK);

	archive_string_free(&pax->pax_header);
	free(pax);
	a->format_data = NULL;
	return (ARCHIVE_OK);
}

static int
archive_write_pax_finish_entry(struct archive_write *a)
{
	struct pax *pax;
	int ret;

	pax = (struct pax *)a->format_data;
	ret = write_nulls(a, pax->entry_bytes_remaining + pax->entry_padding);
	pax->entry_bytes_remaining = pax->entry_padding = 0;
	return (ret);
}

static int
write_nulls(struct archive_write *a, size_t padding)
{
	int ret, to_write;

	while (padding > 0) {
		to_write = padding < a->null_length ? padding : a->null_length;
		ret = (a->compressor.write)(a, a->nulls, to_write);
		if (ret != ARCHIVE_OK)
			return (ret);
		padding -= to_write;
	}
	return (ARCHIVE_OK);
}

static ssize_t
archive_write_pax_data(struct archive_write *a, const void *buff, size_t s)
{
	struct pax *pax;
	int ret;

	pax = (struct pax *)a->format_data;
	if (s > pax->entry_bytes_remaining)
		s = pax->entry_bytes_remaining;

	ret = (a->compressor.write)(a, buff, s);
	pax->entry_bytes_remaining -= s;
	if (ret == ARCHIVE_OK)
		return (s);
	else
		return (ret);
}

static int
archive_write_pax_data_skip(struct archive_write *a, off_t s)
{
	struct pax *pax;
	off_t skiplen;

	pax = (struct pax *)a->format_data;

	/* Skip entry bytes. */
	if (s > (off_t)(pax->entry_bytes_remaining))
		skiplen = pax->entry_bytes_remaining;
	else
		skiplen = s;
	pax->entry_bytes_remaining -= skiplen;
	s -= skiplen;

	/* Skip padding bytes. */
	if (s > (off_t)(pax->entry_padding))
		skiplen = pax->entry_padding;
	else
		skiplen = s;
	pax->entry_padding -= skiplen;
	s -= skiplen;

	/* Anything left is an error. */
	if (s > 0) {
		archive_set_error(&a->archive, E2BIG,
		    "Skip length too long");
		return (ARCHIVE_FATAL);
	}

	return (ARCHIVE_OK);
}

static int
has_non_ASCII(const wchar_t *wp)
{
	if (wp == NULL)
		return (1);
	while (*wp != L'\0' && *wp < 128)
		wp++;
	return (*wp != L'\0');
}

/*
 * Used by extended attribute support; encodes the name
 * so that there will be no '=' characters in the result.
 */
static char *
url_encode(const char *in)
{
	const char *s;
	char *d;
	int out_len = 0;
	char *out;

	for (s = in; *s != '\0'; s++) {
		if (*s < 33 || *s > 126 || *s == '%' || *s == '=')
			out_len += 3;
		else
			out_len++;
	}

	out = (char *)malloc(out_len + 1);
	if (out == NULL)
		return (NULL);

	for (s = in, d = out; *s != '\0'; s++) {
		/* encode any non-printable ASCII character or '%' or '=' */
		if (*s < 33 || *s > 126 || *s == '%' || *s == '=') {
			/* URL encoding is '%' followed by two hex digits */
			*d++ = '%';
			*d++ = "0123456789ABCDEF"[0x0f & (*s >> 4)];
			*d++ = "0123456789ABCDEF"[0x0f & *s];
		} else {
			*d++ = *s;
		}
	}
	*d = '\0';
	return (out);
}

/*
 * Encode a sequence of bytes into a C string using base-64 encoding.
 *
 * Returns a null-terminated C string allocated with malloc(); caller
 * is responsible for freeing the result.
 */
static char *
base64_encode(const char *s, size_t len)
{
	static const char digits[64] =
	    { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
	      'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d',
	      'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s',
	      't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
	      '8','9','+','/' };
	int v;
	char *d, *out;

	/* 3 bytes becomes 4 chars, but round up and allow for trailing NUL */
	out = (char *)malloc((len * 4 + 2) / 3 + 1);
	if (out == NULL)
		return (NULL);
	d = out;

	/* Convert each group of 3 bytes into 4 characters. */
	while (len >= 3) {
		v = (((int)s[0] << 16) & 0xff0000)
		    | (((int)s[1] << 8) & 0xff00)
		    | (((int)s[2]) & 0x00ff);
		s += 3;
		len -= 3;
		*d++ = digits[(v >> 18) & 0x3f];
		*d++ = digits[(v >> 12) & 0x3f];
		*d++ = digits[(v >> 6) & 0x3f];
		*d++ = digits[(v) & 0x3f];
	}
	/* Handle final group of 1 byte (2 chars) or 2 bytes (3 chars). */
	switch (len) {
	case 0: break;
	case 1:
		v = (((int)s[0] << 16) & 0xff0000);
		*d++ = digits[(v >> 18) & 0x3f];
		*d++ = digits[(v >> 12) & 0x3f];
		break;
	case 2:
		v = (((int)s[0] << 16) & 0xff0000)
		    | (((int)s[1] << 8) & 0xff00);
		*d++ = digits[(v >> 18) & 0x3f];
		*d++ = digits[(v >> 12) & 0x3f];
		*d++ = digits[(v >> 6) & 0x3f];
		break;
	}
	/* Add trailing NUL character so output is a valid C string. */
	*d++ = '\0';
	return (out);
}

{'repo_name': 'Tarsnap/tarsnap', 'stars': '522', 'repo_language': 'C', 'file_name': 'archive_read_disk_private.h', 'mime_type': 'text/x-c', 'hash': -7584092313506179736, 'source_dataset': 'data'}


---
title: 11 reasons to start using Azure Boards
titleSuffix: Azure Boards & TFS
description: Understand why to use Azure Boards to track your issues, user stories, bugs, tasks, and other work
ms.custom: "boards-get-started, seodec18"
ms.technology: devops-new-user
ms.assetid:
ms.author: kaelli
author: KathrynEE
ms.topic: overview
monikerRange: '>= tfs-2013'
ms.date: 01/11/2019
---

# 11 Reasons for using Azure Boards to plan and track your work

[!INCLUDE [temp](../includes/version-all.md)]

We know you have a choice of tracking systems. So why use Azure Boards to plan and track your work, bugs, and customer issues?

In [What is Azure Boards?](what-is-azure-boards.md), we describe the main features you get with Azure Boards. Here, we provide 11 compelling reasons to take Azure Boards for a free test spin.

## 1. Start simply, scale as you grow

Azure Boards provides you with a set of predefined work item types to support tracking features, user stories, bugs, and tasks. You can quickly get up and running by using your product backlog or Kanban board. Whatever Agile method you use, Azure Boards supports you with the tools you need to implement that method.

As your organization grows, you can [add teams](../../organizations/projects/about-projects.md#add-team) to provide them the autonomy to track their work according to their needs.

> [!TIP]
> Quickly add work items by using your backlog or Kanban board. Or, use [work item templates](../backlogs/work-item-template.md) to simplify defining work items by setting values for select fields.

## 2. Visual, interactive tools

Visual tools help teams quickly see and share progress. For example, with [Kanban boards](../boards/kanban-quickstart.md) you can add work, update the status of work, and monitor work in progress.

> [!div class="mx-imgBorder"]
> ![Example Kanban board](../../boards/boards/media/quickstart/intro-view.png)

With [product backlogs](../backlogs/create-your-backlog.md), you can quickly add work items and prioritize work to keep the most important work at the top of the stack. And, with [delivery plans](../plans/review-team-plans.md), teams can share their plans against a calendar view.

Use [built-in scrum boards and planning tools](../sprints/scrum-overview.md) to help your teams run effective stand-ups, planning meetings, and retrospectives.

## 3. Easy to customize

Kanban boards, taskboards, and delivery plans are easy to configure and customize through the user interface.

For example, with Kanban boards, you can configure columns, swim lanes, card styles, fields shown on cards, and more. You can configure them all through a common configuration dialog.

> [!div class="mx-imgBorder"]
> ![Kanban board common configuration dialog](../../organizations/settings/media/configure-team/common-configuration-dialog.png)

> [!TIP]
> Define [area paths and iteration paths](../../organizations/settings/about-areas-iterations.md) to group work items by product or feature, You also can group work items into sprints, milestones, or other time-related periods.

And, you can easily add [custom fields, work item types, and portfolio backlogs](../../organizations/settings/work/inheritance-process-model.md).

## 4. Built-in social tools and communication

Work item forms provide built-in discussion that you can use to capture questions, notes, and communication as they occur. With this feature, you can maintain a history of what a team decides on any particular work item. You can quickly bring a team member or an entire team into the conversation [by using @mentions](../../notifications/at-mentions.md).

> [!div class="mx-imgBorder"]
> ![Discussion section in work item form](../backlogs/media/add-work-items-discussion.png)

## 5. Capture information, generous cloud storage

Work items are designed to track all the information you need to track. You can perform rich text editing,   drag and drop inline images, and add larger attachments. You can add attachments up to 60 MB and as many as 100 attachments.

In addition, you can link work items within a hierarchy or by simple related links. Each work item form maintains a history of changes, so you can review what changed, by whom, and when.

## 6. Quickly find what you need, get notified of changes

As your project grows, the number of work items used to track it grows. To support your ability to quickly find a specific work item, Azure Boards provides you with easy-to-use tools:

- A follow feature so you can [follow work items](../work-items/follow-work-items.md) to monitor updates and changes
- [Pivot views](../work-items/view-add-work-items.md ) that show you work items assigned to you, that you elected to follow, were recently modified, and more
- A powerful [query engine](../queries/example-queries.md) that filters work item lists based on any field and used to update or triage work items
- Fast, flexible [ad-hoc search](../queries/search-box-queries.md) with quick inline filters
- Alert management settings so you can [personalize the alerts](../../notifications/howto-manage-personal-notifications.md) you receive when work items are assigned to you or are changed, or other filter criteria

## 7. Monitor status and progress with built-in dashboards and analytics

With Azure Boards, you gain access to a number of tools to generate reports to support tracking status and trends.

By using [configurable dashboards](../../report/dashboards/dashboards.md), you can add one or more widgets. You configure widgets to display the information and data you want, such as the following bug burndown widget.

> [!div class="mx-imgBorder"]
> ![Example bug burndown widget](/azure/devops/report/dashboards/media/burndown-widget/burndownup-bug-burndown.png)

In addition to dashboards, you have access to the [Analytics service](../../report/powerbi/what-is-analytics.md), which is optimized for fast read-access and server-based aggregations. By using [Analytics views](../../report/powerbi/what-are-analytics-views.md) and [Power BI](../../report/powerbi/what-are-analytics-views.md), you can create highly sophisticated reports on the project data of interest.

## 8. Office integration

Project managers who want to use familiar tools can import and export work item queries to and from Microsoft Office Excel and Project. To learn more, see:
- [Bulk add or modify work items with Excel](../backlogs/office/bulk-add-modify-work-items-excel.md)
- [Create your backlog and tasks by using Project](../backlogs/office/create-your-backlog-tasks-using-project.md)

## 9. Extensions and extensibility

You can gain even greater functionality by adding Marketplace extensions, many of which are free. An extension is an installable unit that adds capabilities to Visual Studio, Azure DevOps Services, Team Foundation Server, or Visual Studio Code. You can find extensions within these products or in the [Visual Studio Marketplace](https://marketplace.visualstudio.com/azuredevops), Azure DevOps tab.

Here are a few extensions available from the Marketplace.

> [!div class="mx-imgBorder"]
> ![Marketplace extensions for plan and track work](media/why-boards/marketplace-extensions.png)

In addition, by using the [REST API](/rest/api/azure/devops/index), you can create your own extensions or tools to integrate with Azure DevOps Services.

## 10. Mobile app

Azure Boards makes it easy to stay on top of changes as they occur.
By using the [mobile browser](../../project/navigation/mobile-work.md), you can be notified and respond to changes made to work items.

![Mobile browser, work item form](../../project/navigation/media/mobile-work-intro-1.png)

## 11. Start for free

Last but not least, you can start for free and add up to five free users and unlimited [stakeholders](../../organizations/security/get-started-stakeholder.md).

Get started today. To learn how, see [Sign up for free and invite others to collaborate on your project](sign-up-invite-teammates.md).

## Related articles

- [Best tool to add, update, and link work items](../work-items/best-tool-add-update-link-work-items.md)

{'repo_name': 'MicrosoftDocs/azure-devops-docs', 'stars': '330', 'repo_language': 'Shell', 'file_name': 'settings.json', 'mime_type': 'text/plain', 'hash': -775047700918802728, 'source_dataset': 'data'}


//
// 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.
//

== What is (in) ServiceMix?

Apache ServiceMix is an open source ESB (Enterprise Service Bus) that combines the functionality of a Service Oriented Architecture
(SOA) and the modularity. The adoption of a Service Bus allows to decouple the applicatons together and reduce dependencies.
Messages are used to wire together applications (=services) and/or connectors to exchange information using different protocols or
communication modes like FTP, HTTP, and web services.

Apache ServiceMix is designed on top of the OSGI specification. Using OSGI framework brings a new important feature to SOA development:
modularity. That means that we can handle classloading and application lifecycle differently between the components.

ServiceMix is lightweight and easily embeddable, has integrated Spring support and can be run at the edge of the network (inside a
client or server), as a standalone ESB provider or as a service within another ESB. You can use ServiceMix in Java SE or Java EE
application server.

=== Platform presentation

Apache ServiceMix is a distributed ESB built from the ground up and released under the Apache license.

ServiceMix uses ActiveMQ to provide remoting, clustering, reliability and distributed failover.

ServiceMix can also be embedded into a JEE application server such as JBoss WildFly, Oracle Weblogic or IBM Websphere.

=== OSGi for Dummies

http://www.osgi.org/About/Technology[OSGi technology] is the dynamic module system for
http://www.oracle.com/technetwork/java/index.html[Java]. The OSGi Service Platform provides functionality to Java that makes Java
the premier environment for software integration and thus for development. Java provides the portability that is required to support
products on many different platforms. The OSGi technology provides the standardized primitives that allow applications to be
constructed from small, reusable and collaborative components. These components can be composed into an application and deployed.

The OSGi Service Platform provides the functions to change the composition dynamically on the device of a variety of networks,
without requiring restarts. To minimize the coupling, as well as make these couplings managed, the OSGi technology provides a
service-oriented architecture that enables these components to dynamically discover each other for collaboration. The OSGi Alliance
has developed many standard component interfaces for common functions like HTTP servers, configuration, logging, security, user
administration, XML and many more. Plug-compatible implementations of these components can be obtained from different vendors with
different optimizations and costs. However, service interfaces can also be developed on a proprietary basis.

OSGi technology adopters benefit from improved time-to-market and reduced development costs because OSGi technology provides for the
integration of pre-built and pre-tested component subsystems. The technology also reduces maintenance costs and enables unique new
aftermarket opportunities because components can be dynamically delivered to devices in the field.

For more information, check out the http://www.osgi.org/Main/HomePage[OSGi Alliance website].

=== Powered by Apache Karaf

Apache ServiceMix is based on http://karaf.apache.org/[Apache Karaf]. Apache Karaf is a small
http://www.osgi.org/Main/HomePage[OSGi-based] runtime which provides a lightweight container onto which various components and
applications can be deployed.

Here is a short list of features supported by the Karaf:

Hot deployment: Karaf supports hot deployment of OSGi bundles by monitoring jar files inside the $home/deploy directory. Each time a
jar is copied in this folder, it will be installed inside the runtime. You can then update or delete it and changes will be handled
automatically. In addition, the Karaf also supports exploded bundles and custom deployers (Blueprint and Spring ones are included by
default).

Dynamic configuration: Services are usually configured through the ConfigurationAdmin OSGi service. Such configuration can be
defined in Karaf using property files inside the $home/etc directory. These configurations are monitored and changes on the
properties files will be propagated to the services.

Logging System: using a centralized logging back end supported by Log4J, Karaf supports a number of different APIs (JDK 1.4, JCL,
SLF4J, Avalon, Tomcat, OSGi)

Provisioning: Provisioning of libraries or applications can be done through a number of different ways, by which they will be
downloaded locally, installed and started.

Native OS integration: Karaf can be integrated into your own Operating System as a service so that the lifecycle will be bound to
your Operating System.

Extensible Shell console: Karaf features a nice text console where you can manage the services, install new applications or
libraries and manage their state. This shell is easily extensible by deploying new commands dynamically along with new features or
applications.

Remote access: use any SSH client to connect to Karaf and issue commands in the console .

Security framework based on JAAS.

Managing instances: Karaf provides simple commands for managing multiple instances. You can easily create, delete, start and stop
instances of Karaf through the console.

For more information, check out the http://karaf.apache.org/[Apache Karaf project page].

=== Apache Camel

Apache Camel is a powerful open source integration framework based on known
http://camel.apache.org/enterprise-integration-patterns.html[Enterprise Integration Patterns] with powerful
http://camel.apache.org/bean-integration.html[Bean Integration].

Apache Camel lets you create the http://camel.apache.org/enterprise-integration-patterns.html[Enterprise Integration Patterns] to
implement routing and mediation rules in either a Java based http://camel.apache.org/dsl.html[Domain Specific Language (or Fluent
API)], via http://camel.apache.org/spring.html[Spring based Xml Configuration] files or via the
http://camel.apache.org/scala-dsl.html[Scala DSL].

For more information, check out the <<camel-guide.adoc#,Using Apache Camel in ServiceMix User Guide>>.

=== Services proposed

_TODO: write this bit_

==== Message Broker : Apache ActiveMQ

Apache ServiceMix ships with an embedded instance of http://activemq.apache.org[Apache ActiveMQ] out-of-the-box.

It is a fully functional Apache ActiveMQ message broker instance listening for http://activemq.apache.org/openwire.html[TCP]
connections on port 61616 and http://activemq.apache.org/stomp.html[STOMP] connections on port 61613.

The http://activemq.apache.org/xml-configuration.html[default configuration for the Apache ActiveMQ] message broker resides in the
ServiceMix installation directory under the etc sub-directory. The ActiveMQ configuration file is named activemq.xml. It's
configured with reasonable default information like http://activemq.apache.org/persistence.html[Persistence (KahaDB)] and
http://activemq.apache.org/producer-flow-control.html[Producer Flow Control] (essentially to make sure the broker does not run out
of memory).

The configuration file also makes use of a reusable connection pool available to all OSGi bundles exposing a
http://docs.oracle.com/javaee/1.4/api/javax/jms/ConnectionFactory.html[javax.jms.ConnectionFactory] as a service for consumption.
You can re-use this connection pool via tools such as http://activemq.apache.org/osgi-integration.html[spring-dm or blueprint].

The ActiveMQ message broker allows several components such as servicemix-cluster, http://camel.apache.org/jms.html[camel-jms],
http://camel.apache.org/activemq.html[camel-activemq], http://cxf.apache.org/docs/jms-transport.html[cxf-jms transport] to be
utilized without any additional configuration.

==== Transaction : Geronimo Transaction Manager
_TODO: write this bit_

==== Routing and Mediation : Apache Camel
_TODO: write this bit_

==== Web Services : Apache CXF
_TODO: write this bit_

==== Web Container
_TODO: write this bit_

==== SOA platform
_TODO: write this bit_

===== Spring DM container
_TODO: write this bit_

===== Blueprint OSGI container
_TODO: write this bit_

===== EJB Container
_TODO: write this bit_

{'repo_name': 'apache/servicemix', 'stars': '124', 'repo_language': 'Java', 'file_name': 'activemq-service.xml', 'mime_type': 'text/xml', 'hash': 422616071070082914, 'source_dataset': 'data'}


/*
             LUFA Library
     Copyright (C) Dean Camera, 2013.

  dean [at] fourwalledcubicle [dot] com
           www.lufa-lib.org
*/

/*
  Copyright 2013  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, distribute, and sell this
  software and its documentation for any purpose is hereby granted
  without fee, provided that the above copyright notice appear in
  all copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaims all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *  \brief Command constants for the Atmel AT45DB642D Dataflash.
 *  \copydetails Group_AT45DB642D
 */

/** \ingroup Group_MiscDrivers
 *  \defgroup Group_AT45DB642D Atmel AT45DB642D Dataflash Commands
 *  \brief Command constants for the Atmel AT45DB642D Dataflash.
 *
 *  Dataflash command constants for the Atmel AT45DB642D Dataflash IC.
 *
 *  @{
 */

#ifndef __AT45DB642D_CMDS_H__
#define __AT45DB642D_CMDS_H__

	/* Public Interface - May be used in end-application: */
		/* Macros: */
			/** \name Dataflash Status Values */
			//@{
			#define DF_STATUS_READY                         (1 << 7)
			#define DF_STATUS_COMPMISMATCH                  (1 << 6)
			#define DF_STATUS_SECTORPROTECTION_ON           (1 << 1)
			#define DF_STATUS_BINARYPAGESIZE_ON             (1 << 0)
			//@}

			/** \name Dataflash Commands */
			//@{
			#define DF_CMD_GETSTATUS                        0xD7
			#define DF_CMD_POWERDOWN                        0xB9
			#define DF_CMD_WAKEUP                           0xAB

			#define DF_CMD_MAINMEMTOBUFF1                   0x53
			#define DF_CMD_MAINMEMTOBUFF2                   0x55
			#define DF_CMD_MAINMEMTOBUFF1COMP               0x60
			#define DF_CMD_MAINMEMTOBUFF2COMP               0x61
			#define DF_CMD_AUTOREWRITEBUFF1                 0x58
			#define DF_CMD_AUTOREWRITEBUFF2                 0x59

			#define DF_CMD_MAINMEMPAGEREAD                  0xD2
			#define DF_CMD_CONTARRAYREAD_LF                 0x03
			#define DF_CMD_BUFF1READ_LF                     0xD1
			#define DF_CMD_BUFF2READ_LF                     0xD3

			#define DF_CMD_BUFF1WRITE                       0x84
			#define DF_CMD_BUFF2WRITE                       0x87
			#define DF_CMD_BUFF1TOMAINMEMWITHERASE          0x83
			#define DF_CMD_BUFF2TOMAINMEMWITHERASE          0x86
			#define DF_CMD_BUFF1TOMAINMEM                   0x88
			#define DF_CMD_BUFF2TOMAINMEM                   0x89
			#define DF_CMD_MAINMEMPAGETHROUGHBUFF1          0x82
			#define DF_CMD_MAINMEMPAGETHROUGHBUFF2          0x85

			#define DF_CMD_PAGEERASE                        0x81
			#define DF_CMD_BLOCKERASE                       0x50
			#define DF_CMD_SECTORERASE                      0x7C

			#define DF_CMD_CHIPERASE                        ((char[]){0xC7, 0x94, 0x80, 0x9A})
			#define DF_CMD_CHIPERASE_BYTE1                  0xC7
			#define DF_CMD_CHIPERASE_BYTE2                  0x94
			#define DF_CMD_CHIPERASE_BYTE3                  0x80
			#define DF_CMD_CHIPERASE_BYTE4                  0x9A

			#define DF_CMD_SECTORPROTECTIONOFF              ((char[]){0x3D, 0x2A, 0x7F, 0x9A})
			#define DF_CMD_SECTORPROTECTIONOFF_BYTE1        0x3D
			#define DF_CMD_SECTORPROTECTIONOFF_BYTE2        0x2A
			#define DF_CMD_SECTORPROTECTIONOFF_BYTE3        0x7F
			#define DF_CMD_SECTORPROTECTIONOFF_BYTE4        0x9A

			#define DF_CMD_BINARYPAGESIZEMODEON             ((char[]){0x3D, 0x2A, 0x80, 0xA6})
			#define DF_CMD_BINARYPAGESIZEMODEON_BYTE1       0x3D
			#define DF_CMD_BINARYPAGESIZEMODEON_BYTE2       0x2A
			#define DF_CMD_BINARYPAGESIZEMODEON_BYTE3       0x80
			#define DF_CMD_BINARYPAGESIZEMODEON_BYTE4       0xA6

			#define DF_CMD_READMANUFACTURERDEVICEINFO       0x9F
			//@}

			/** Manufacturer code for Atmel Corporation, returned by Atmel Dataflash ICs in response to the \c DF_CMD_READMANUFACTURERDEVICEINFO command. */
			#define DF_MANUFACTURER_ATMEL                   0x1F

#endif

/** @} */

{'repo_name': 'Atarity/Lightpack', 'stars': '211', 'repo_language': 'C++', 'file_name': 'libraryinjector.pro', 'mime_type': 'text/plain', 'hash': 3437892707644998747, 'source_dataset': 'data'}


<?php

require_once __DIR__.'/../ecc/ECKeyPair.php';
require_once __DIR__.'/state/SenderKeyRecord.php';
require_once __DIR__.'/state/SenderKeyStore.php';
require_once __DIR__.'/../protocol/SenderKeyDistributionMessage.php';
class GroupSessionBuilder
{
    protected $senderKeyStore;

    public function GroupSessionBuilder($senderKeyStore)
    {
        $this->senderKeyStore = $senderKeyStore;
    }

    public function processSender($sender, $senderKeyDistributionMessage)
    {
        $senderKeyRecord = $this->senderKeyStore->loadSenderKey($sender);

        $senderKeyRecord->addSenderKeyState($senderKeyDistributionMessage->getId(),
                                            $senderKeyDistributionMessage->getIteration(),
                                            $senderKeyDistributionMessage->getChainKey(),
                                            $senderKeyDistributionMessage->getSignatureKey());
        $this->senderKeyStore->storeSenderKey($sender, $senderKeyRecord);
    }

    public function process($groupId, $keyId, $iteration, $chainKey, $signatureKey)
    {
        $senderKeyRecord = $this->senderKeyStore->loadSenderKey($groupId);

        $senderKeyRecord->setSenderKeyState($keyId, $iteration, $chainKey, $signatureKey);

        $this->senderKeyStore->storeSenderKey($groupId, $senderKeyRecord);

        return new SenderKeyDistributionMessage($keyId, $iteration, $chainKey, $signatureKey->getPublicKey());
    }
}

{'repo_name': 'mgp25/Chat-API', 'stars': '4184', 'repo_language': 'PHP', 'file_name': 'whatsapp.php', 'mime_type': 'text/x-php', 'hash': -7742840734287660816, 'source_dataset': 'data'}


TESTS = t1.aspx t2.aspx t3.aspx t4.aspx t5.aspx t6.aspx t7.aspx
TESTS2 = c1.aspx c2.aspx c3.aspx
#SERVER=quack
SERVER=lalo-office.boston.ximian.com

all: rtest.exe ctest.exe test

rtest.exe: rtest.cs
	mcs rtest.cs

ctest.exe: ctest.cs
	mcs ctest.cs

copy:
	for i in $(TESTS) $(TESTS2); do cp $$i /q/web; done

test: local compare

compare:
	@for i in $(TESTS) $(TESTS2); do \
		if cmp $$i.expected $$i.result; then echo OK; else echo FAILED; exit 1; fi; \
		if test -f $$i.oexpected; then \
		if cmp $$i.oexpected $$i.oresult; then echo OK; else echo FAILED; exit 1; fi; fi \
	done

local:
	@for i in $(TESTS); do \
		echo running test $$i; \
		mono rtest.exe localhost 8080 /$$i > $$i.result; \
		mono ctest.exe localhost 8080 /$$i > $$i.oresult; \
	done
	@for i in $(TESTS2); do \
		echo running test $$i; \
		mono rtest.exe -header Cache-Control: localhost 8080 /$$i > $$i.result; \
	done

tw:
	@for i in $(TESTS); do \
		echo running test $$i; \
		mono rtest.exe $(SERVER) 80 /test/$$i > $$i.expected; \
		mono ctest.exe $(SERVER) 80 /test/$$i > $$i.oexpected; \
	done
	@for i in $(TESTS2); do \
		echo running test $$i; \
		mono rtest.exe -header Cache-Control: $(SERVER) 80 /test/$$i > $$i.expected; \
	done

{'repo_name': 'roozbehid/WasmWinforms', 'stars': '421', 'repo_language': 'C#', 'file_name': 'ChangeLog', 'mime_type': 'text/plain', 'hash': 2424492089281868774, 'source_dataset': 'data'}


package test

import java.io.DataOutput
import java.io.DataInput

/** Interface for writing outputs from a DoFn. */
trait Emitter[A] {
  def emit(value: A): Unit
}

/** A wrapper for a 'map' function tagged for a specific output channel. */
abstract class TaggedMapper[A, K, V]
    (val tags: Set[Int])
    (implicit val mA: Manifest[A], val wtA: WireFormat[A],
              val mK: Manifest[K], val wtK: WireFormat[K], val ordK: Ordering[K],
              val mV: Manifest[V], val wtV: WireFormat[V])
  extends Serializable {
}

/** Type class for sending types across the Hadoop wire. */
trait WireFormat[A]

class MapReduceJob {
  trait DataSource

  import scala.collection.mutable.{ Set => MSet, Map => MMap }
  private val mappers: MMap[DataSource, MSet[TaggedMapper[_, _, _]]] = MMap.empty

  def addTaggedMapper[A, K, V](input: DataSource, m: TaggedMapper[A, K, V]): Unit = {
    if (!mappers.contains(input))
      mappers += (input -> MSet(m))
    else
      mappers(input) += m // : Unit

    m.tags.foreach { tag =>
    }
  }
}

{'repo_name': 'scala/scala', 'stars': '12803', 'repo_language': 'Scala', 'file_name': 'm2-settings.xml', 'mime_type': 'text/xml', 'hash': 8339241163469597262, 'source_dataset': 'data'}


/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#pragma once
#include <aws/athena/Athena_EXPORTS.h>
#include <aws/core/utils/memory/stl/AWSString.h>
#include <utility>

namespace Aws
{
namespace Utils
{
namespace Json
{
  class JsonValue;
  class JsonView;
} // namespace Json
} // namespace Utils
namespace Athena
{
namespace Model
{

  /**
   *
Contains metadata for a column in a table.

See Also:
   AWS API
   * Reference

   */
  class AWS_ATHENA_API Column
  {
  public:
    Column();
    Column(Aws::Utils::Json::JsonView jsonValue);
    Column& operator=(Aws::Utils::Json::JsonView jsonValue);
    Aws::Utils::Json::JsonValue Jsonize() const;

    /**
     *
The name of the column.

     */
    inline const Aws::String& GetName() const{ return m_name; }

    /**
     *
The name of the column.

     */
    inline bool NameHasBeenSet() const { return m_nameHasBeenSet; }

    /**
     *
The name of the column.

     */
    inline void SetName(const Aws::String& value) { m_nameHasBeenSet = true; m_name = value; }

    /**
     *
The name of the column.

     */
    inline void SetName(Aws::String&& value) { m_nameHasBeenSet = true; m_name = std::move(value); }

    /**
     *
The name of the column.

     */
    inline void SetName(const char* value) { m_nameHasBeenSet = true; m_name.assign(value); }

    /**
     *
The name of the column.

     */
    inline Column& WithName(const Aws::String& value) { SetName(value); return *this;}

    /**
     *
The name of the column.

     */
    inline Column& WithName(Aws::String&& value) { SetName(std::move(value)); return *this;}

    /**
     *
The name of the column.

     */
    inline Column& WithName(const char* value) { SetName(value); return *this;}

    /**
     *
The data type of the column.

     */
    inline const Aws::String& GetType() const{ return m_type; }

    /**
     *
The data type of the column.

     */
    inline bool TypeHasBeenSet() const { return m_typeHasBeenSet; }

    /**
     *
The data type of the column.

     */
    inline void SetType(const Aws::String& value) { m_typeHasBeenSet = true; m_type = value; }

    /**
     *
The data type of the column.

     */
    inline void SetType(Aws::String&& value) { m_typeHasBeenSet = true; m_type = std::move(value); }

    /**
     *
The data type of the column.

     */
    inline void SetType(const char* value) { m_typeHasBeenSet = true; m_type.assign(value); }

    /**
     *
The data type of the column.

     */
    inline Column& WithType(const Aws::String& value) { SetType(value); return *this;}

    /**
     *
The data type of the column.

     */
    inline Column& WithType(Aws::String&& value) { SetType(std::move(value)); return *this;}

    /**
     *
The data type of the column.

     */
    inline Column& WithType(const char* value) { SetType(value); return *this;}

    /**
     *
Optional information about the column.

     */
    inline const Aws::String& GetComment() const{ return m_comment; }

    /**
     *
Optional information about the column.

     */
    inline bool CommentHasBeenSet() const { return m_commentHasBeenSet; }

    /**
     *
Optional information about the column.

     */
    inline void SetComment(const Aws::String& value) { m_commentHasBeenSet = true; m_comment = value; }

    /**
     *
Optional information about the column.

     */
    inline void SetComment(Aws::String&& value) { m_commentHasBeenSet = true; m_comment = std::move(value); }

    /**
     *
Optional information about the column.

     */
    inline void SetComment(const char* value) { m_commentHasBeenSet = true; m_comment.assign(value); }

    /**
     *
Optional information about the column.

     */
    inline Column& WithComment(const Aws::String& value) { SetComment(value); return *this;}

    /**
     *
Optional information about the column.

     */
    inline Column& WithComment(Aws::String&& value) { SetComment(std::move(value)); return *this;}

    /**
     *
Optional information about the column.

     */
    inline Column& WithComment(const char* value) { SetComment(value); return *this;}

  private:

    Aws::String m_name;
    bool m_nameHasBeenSet;

    Aws::String m_type;
    bool m_typeHasBeenSet;

    Aws::String m_comment;
    bool m_commentHasBeenSet;
  };

} // namespace Model
} // namespace Athena
} // namespace Aws

{'repo_name': 'aws/aws-sdk-cpp', 'stars': '1060', 'repo_language': 'C++', 'file_name': 'RunTests.cpp', 'mime_type': 'text/x-c', 'hash': -5926638116187026463, 'source_dataset': 'data'}


// *** WARNING: this file was generated by the Pulumi Terraform Bridge (tfgen) Tool. ***
// *** Do not edit by hand unless you're certain you know what you are doing! ***

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Pulumi.Serialization;

namespace Pulumi.Aws.WafV2.Outputs
{

    [OutputType]
    public sealed class WebAclRuleStatementNotStatementStatementAndStatementStatementOrStatementStatementSqliMatchStatementFieldToMatchSingleQueryArgument
    {
        /// <summary>
        /// The name of the query header to inspect. This setting must be provided as lower case characters.
        /// </summary>
        public readonly string Name;

        [OutputConstructor]
        private WebAclRuleStatementNotStatementStatementAndStatementStatementOrStatementStatementSqliMatchStatementFieldToMatchSingleQueryArgument(string name)
        {
            Name = name;
        }
    }
}

{'repo_name': 'pulumi/pulumi-aws', 'stars': '117', 'repo_language': 'Go', 'file_name': 'job.go', 'mime_type': 'text/x-c', 'hash': 8821900905076220743, 'source_dataset': 'data'}


"""
    链表相加的题目一共两种：
        1、数字用链表逆序存储，例如 123 用链表表示是 3 -> 2 -> 1
        2、数字用链表顺序存储，例如 123 用链表表示是 1 -> 2 -> 3

    以链表为基础做加法运算
"""

"""
一、题目
    数字用链表逆序存储，计算任意给定的两个非负整数。
    如：输入 2 -> 4 -> 3, 5 -> 6 -> 4, 得到 7 -> 0 -> 8.
                342     +     465       =      807

二、思路 同其他几种"加法"
    题目的本质是加法运算，注意加法的进位情况，和链表的一些特性即可
    加法运算都是从个位数开始加的，注意进位
    逆序表示的数据，正好可以从头向后依次相加

    下面的循环的结构是任何加法运算（二进制、字符串、链表）的通用结构，值得仔细品味
"""

from Linklist.utils import *

def add(head1, head2):
    cur1 = head1
    cur2 = head2
    carry = 0
    new_head = ListNode(-1)
    new_cur = new_head
    while carry > 0 or cur1 is not None or cur2 is not None:
        if cur1 is not None:
            carry += cur1.val
            cur1 = cur1.next
        if cur2 is not None:
            carry += cur2.val
            cur2 = cur2.next
        # 将求和结果利用“尾插法”，得到逆序链表
        new_cur.next = ListNode(carry % 10)
        new_cur = new_cur.next
        carry = int(carry / 10)
    return new_head.next

if __name__ == '__main__':
    l1 = build_l([9, 9, 9])
    l2 = build_l([1])
    print_l(head=add(l1, l2), p_type="SINGLE")

{'repo_name': 'whtlkeep/BAT-algorithms', 'stars': '133', 'repo_language': 'Python', 'file_name': '完全二叉树-寻找完全二叉树最后一个节点.py', 'mime_type': 'text/x-python', 'hash': -941332765799216741, 'source_dataset': 'data'}


package Test::DB::Dumper;

use strict;

use Config::Neat::Render;
use Config::Neat::Schema;
use Data::Dumper;
use File::Path;
use File::Spec::Functions qw(rel2abs catfile);

our @TABLE_NAMES = qw/files strings items translations properties/;
our $TYPE_NEAT = 'neat';

sub new {
    my ($class, $engine) = @_;

    die "engine not specified" unless $engine;

    my $self = {
        engine => $engine,
        neat_renderer => Config::Neat::Render->new()
    };

    bless($self, $class);
    return $self;
}

sub _render_as_json {
    my ($self, $data, $table_name) = @_;
    return to_json({$table_name => $data}, {pretty => 1, indent_length => 4});
}

sub _render_as_neat {
    my ($self, $data, $table_name) = @_;
    return $self->{neat_renderer}->render({$table_name => $data});
}

sub _save {
    my ($self, $data, $table_name, $type, $path) = @_;

    eval { mkpath($path) };
    die "Couldn't create $path: $@" if $@;

    my $content;
    if ($type eq $TYPE_NEAT) {
        $content = $self->_render_as_neat($data, $table_name);
    } else {
        $content = $self->_render_as_json($data, $table_name);
    }

    my $filename = catfile($path, $table_name);
    open(OUT, ">$filename");
    binmode(OUT, ':unix :utf8');
    print OUT $content;
    close(OUT);
}

sub dump_l10n_tables {
    my ($self, $type, $output_path) = @_;

    print "TEST: dumping the database to $output_path...\n";

    for (@TABLE_NAMES) {
        $self->_save($self->_get_table_dump($_), $_, $type, $output_path);
    }
}

sub _get_table_dump {
    my ($self, $table_name) = @_;

    my $sql = "SELECT * FROM $table_name";

    my $sth = $self->{engine}->{db}->prepare($sql);
    $sth->execute || die $sth->errstr;
    my $ar_all = $sth->fetchall_arrayref();
    $sth->finish;

    return $ar_all;
}

1;

{'repo_name': 'evernote/serge', 'stars': '198', 'repo_language': 'Perl', 'file_name': 'serge-pull-ts.pod', 'mime_type': 'text/plain', 'hash': 8100125683323088412, 'source_dataset': 'data'}


<?php

namespace Alidns\Request\V20150109;

/**
 * @deprecated Please use https://github.com/aliyun/openapi-sdk-php
 *
 * Request of AddGtmRecoveryPlan
 *
 * @method string getFaultAddrPool()
 * @method string getRemark()
 * @method string getUserClientIp()
 * @method string getName()
 * @method string getLang()
 */
class AddGtmRecoveryPlanRequest extends \RpcAcsRequest
{

    /**
     * @var string
     */
    protected $method = 'POST';

    /**
     * Class constructor.
     */
    public function __construct()
    {
        parent::__construct(
            'Alidns',
            '2015-01-09',
            'AddGtmRecoveryPlan',
            'alidns'
        );
    }

    /**
     * @param string $faultAddrPool
     *
     * @return $this
     */
    public function setFaultAddrPool($faultAddrPool)
    {
        $this->requestParameters['FaultAddrPool'] = $faultAddrPool;
        $this->queryParameters['FaultAddrPool'] = $faultAddrPool;

        return $this;
    }

    /**
     * @param string $remark
     *
     * @return $this
     */
    public function setRemark($remark)
    {
        $this->requestParameters['Remark'] = $remark;
        $this->queryParameters['Remark'] = $remark;

        return $this;
    }

    /**
     * @param string $userClientIp
     *
     * @return $this
     */
    public function setUserClientIp($userClientIp)
    {
        $this->requestParameters['UserClientIp'] = $userClientIp;
        $this->queryParameters['UserClientIp'] = $userClientIp;

        return $this;
    }

    /**
     * @param string $name
     *
     * @return $this
     */
    public function setName($name)
    {
        $this->requestParameters['Name'] = $name;
        $this->queryParameters['Name'] = $name;

        return $this;
    }

    /**
     * @param string $lang
     *
     * @return $this
     */
    public function setLang($lang)
    {
        $this->requestParameters['Lang'] = $lang;
        $this->queryParameters['Lang'] = $lang;

        return $this;
    }
}

{'repo_name': 'aliyun/aliyun-openapi-php-sdk', 'stars': '595', 'repo_language': 'PHP', 'file_name': 'TaobaoFilmGetShowCommentsRequest.php', 'mime_type': 'text/x-php', 'hash': -6069416331575546567, 'source_dataset': 'data'}


import maya.cmds as cmds
import maya.api.OpenMaya as OpenMaya
import cmt.shortcuts as shortcuts
import cmt.rig.common as common
from cmt.dge import dge
import cmt.rig.twoboneik as twoboneik
import cmt.rig.spaceswitch as spaceswitch

reload(common)
reload(twoboneik)

class LegRig(object):
    def __init__(self, up_leg_joint, ankle_joint, ball_joint, toe_joint, name="leg"):
        self.two_bone_ik = twoboneik.TwoBoneIk(up_leg_joint, ankle_joint, name)
        self.ik_handle_ball = None
        self.ik_handle_toe = None
        self.ball_joint = ball_joint
        self.toe_joint = toe_joint
        self.hierarchy = None
        self.name = name
        self.group = "{}_grp".format(self.name)

    def create(
        self,
        ik_control,
        pole_vector=None,
        global_scale_attr=None,
        pivots=None,
        scale_stretch=True,
        parent=None,
    ):
        if not cmds.objExists(self.group):
            self.group = cmds.createNode("transform", name=self.group)
            cmds.setAttr("{}.v".format(self.group), 0)
            common.lock_and_hide(self.group, "trsv")

        self.__create_ik(
            ik_control, pole_vector, global_scale_attr, pivots, scale_stretch, parent
        )
        self.__create_fk()

    def __create_ik(
        self,
        ik_control,
        pole_vector=None,
        global_scale_attr=None,
        pivots=None,
        scale_stretch=True,
        parent=None,
    ):
        # Create ik handles
        self.ik_handle_ball = cmds.ikHandle(
            name="{}_ball_ikh".format(self.name),
            solver="ikSCsolver",
            startJoint=self.two_bone_ik.end_joint,
            endEffector=self.ball_joint,
        )[0]
        if self.toe_joint:
            self.ik_handle_toe = cmds.ikHandle(
                name="{}_toe_ikh".format(self.name),
                solver="ikSCsolver",
                startJoint=self.ball_joint,
                endEffector=self.toe_joint,
            )[0]
        for node in [self.ik_handle_ball, self.ik_handle_toe]:
            if node:
                cmds.setAttr("{}.v".format(node), 0)

        self.__create_pivots(ik_control, pivots)
        self.two_bone_ik.create(
            ik_control,
            pole_vector,
            soft_ik_parent=self.hierarchy.heel_ctrl,
            global_scale_attr=global_scale_attr,
            scale_stretch=scale_stretch,
            parent=parent,
        )
        self.config_control = self.two_bone_ik.config_control
        self.upper_fk_control = self.two_bone_ik.start_fk_control
        cmds.parent(self.two_bone_ik.start_loc, self.group)

        is_right_leg = "_r" in self.name.lower()

        cmds.addAttr(ik_control, ln="ballPivot", keyable=True)
        common.connect_attribute(
            "{}.ballPivot".format(ik_control),
            "{}.ry".format(self.hierarchy.ball_pivot),
            negate=is_right_leg,
        )
        # cmds.addAttr(ik_control, ln="footRoll", keyable=True)
        # common.connect_attribute(
        #     "{}.footRoll".format(ik_control),
        #     "{}.rx".format(self.hierarchy.heel_pivot),
        #     clamp=[-90.0, 0.0],
        # )
        # cmds.addAttr(ik_control, ln="raiseHeel", keyable=True)
        # common.connect_attribute(
        #     "{}.raiseHeel".format(ik_control), "{}.rx".format(self.hierarchy.heel_ctrl)
        # )
        cmds.addAttr(ik_control, ln="tilt", keyable=True)
        common.connect_attribute(
            "{}.tilt".format(ik_control),
            "{}.rz".format(self.hierarchy.out_pivot),
            clamp=[-90.0, 0.0] if not is_right_leg else [0.0, 90.0],
            negate=is_right_leg,
        )
        common.connect_attribute(
            "{}.tilt".format(ik_control),
            "{}.rz".format(self.hierarchy.in_pivot),
            clamp=[0.0, 90.0] if not is_right_leg else [-90.0, 0.0],
            negate=is_right_leg,
        )

    def __create_pivots(self, ik_control, pivots):
        """
        """
        hierarchy = {
            "ball_pivot": {
                "heel_pivot_ctrl": {
                    "out_pivot": {
                        "in_pivot": {
                            "toe_pivot_ctrl": {"toe_ctrl": None, "heel_ctrl": None}
                        }
                    }
                }
            }
        }
        hierarchy = common.RigHierarchy(
            hierarchy,
            prefix="{}_".format(self.name),
            suffix="",
            lock_and_hide=["s", "v"],
        )
        hierarchy.create()
        cmds.parent(hierarchy.ball_pivot, ik_control)
        for driver, driven in [
            [self.ball_joint, hierarchy.ball_pivot],
            [self.two_bone_ik.end_joint, hierarchy.heel_pivot_ctrl],
            [self.ball_joint, hierarchy.out_pivot],
            [self.ball_joint, hierarchy.in_pivot],
            [self.toe_joint, hierarchy.toe_pivot_ctrl],
            [self.ball_joint, hierarchy.toe_ctrl],
            [self.ball_joint, hierarchy.heel_ctrl],
        ]:
            if driver and driven:
                common.snap_to_position(driven, driver)
        for node, position in pivots.items():
            node = getattr(hierarchy, node, None)
            if not node:
                continue
            children = cmds.listRelatives(node, children=True, path=True)
            if children:
                cmds.parent(children, world=True)
            cmds.xform(node, ws=True, t=position)
            if children:
                cmds.parent(children, node)

        hierarchy.parent_to_heel_ctrl(self.ik_handle_ball)
        if self.ik_handle_toe:
            hierarchy.parent_to_toe_ctrl(self.ik_handle_toe)
        for node in hierarchy:
            common.lock_and_hide(node, "t")

        cmds.setAttr("{}.rotateOrder".format(hierarchy.heel_ctrl), 2)  # zxy

        self.hierarchy = hierarchy

    def __create_fk(self):
        ik_switch = cmds.listConnections(
            "{}.ikBlend".format(self.two_bone_ik.ik_handle), d=False, plugs=True
        )[0]
        for ikh in [self.ik_handle_ball, self.ik_handle_toe]:
            if ikh:
                cmds.connectAttr(ik_switch, "{}.ikBlend".format(ikh))
        self.ball_fk_ctrl = cmds.createNode(
            "transform", name="{}_fk_ctrl".format(self.ball_joint)
        )
        common.snap_to(self.ball_fk_ctrl, self.ball_joint)
        common.lock_and_hide(self.ball_fk_ctrl, "sv")
        cmds.parent(self.ball_fk_ctrl, self.two_bone_ik.end_fk_control)
        common.freeze_to_parent_offset(self.ball_fk_ctrl)

        if self.ik_handle_toe:
            ori = cmds.orientConstraint(self.ball_fk_ctrl, self.ball_joint)[0]
        else:
            # Without a toe joint, like in the UE4 Mannequin, use a constraint instead of ik
            ori_target = cmds.duplicate(
                self.hierarchy.toe_ctrl,
                name="{}_ori".format(self.hierarchy.toe_pivot_ctrl),
                po=True,
            )[0]
            cmds.parent(ori_target, self.hierarchy.toe_ctrl)
            common.snap_to(ori_target, self.ball_joint)

            ori = cmds.orientConstraint(
                self.ball_fk_ctrl, ori_target, self.ball_joint,
            )[0]
            cmds.connectAttr(ik_switch, "{}.{}W1".format(ori, ori_target))

        cmds.connectAttr(
            "{}.ikFk".format(self.two_bone_ik.config_control),
            "{}.{}W0".format(ori, self.ball_fk_ctrl),
        )

{'repo_name': 'chadmv/cmt', 'stars': '123', 'repo_language': 'Python', 'file_name': 'menu_ChangePanelType.mel', 'mime_type': 'text/plain', 'hash': -1907912971728636032, 'source_dataset': 'data'}


module Rake

  # A Promise object represents a promise to do work (a chore) in the
  # future. The promise is created with a block and a list of
  # arguments for the block. Calling value will return the value of
  # the promised chore.
  #
  # Used by ThreadPool.
  #
  class Promise               # :nodoc: all
    NOT_SET = Object.new.freeze # :nodoc:

    attr_accessor :recorder

    # Create a promise to do the chore specified by the block.
    def initialize(args, &block)
      @mutex = Mutex.new
      @result = NOT_SET
      @error = NOT_SET
      @args = args
      @block = block
    end

    # Return the value of this promise.
    #
    # If the promised chore is not yet complete, then do the work
    # synchronously. We will wait.
    def value
      unless complete?
        stat :sleeping_on, :item_id => object_id
        @mutex.synchronize do
          stat :has_lock_on, :item_id => object_id
          chore
          stat :releasing_lock_on, :item_id => object_id
        end
      end
      error? ? raise(@error) : @result
    end

    # If no one else is working this promise, go ahead and do the chore.
    def work
      stat :attempting_lock_on, :item_id => object_id
      if @mutex.try_lock
        stat :has_lock_on, :item_id => object_id
        chore
        stat :releasing_lock_on, :item_id => object_id
        @mutex.unlock
      else
        stat :bailed_on, :item_id => object_id
      end
    end

    private

    # Perform the chore promised
    def chore
      if complete?
        stat :found_completed, :item_id => object_id
        return
      end
      stat :will_execute, :item_id => object_id
      begin
        @result = @block.call(*@args)
      rescue Exception => e
        @error = e
      end
      stat :did_execute, :item_id => object_id
      discard
    end

    # Do we have a result for the promise
    def result?
      ! @result.equal?(NOT_SET)
    end

    # Did the promise throw an error
    def error?
      ! @error.equal?(NOT_SET)
    end

    # Are we done with the promise
    def complete?
      result? || error?
    end

    # free up these items for the GC
    def discard
      @args = nil
      @block = nil
    end

    # Record execution statistics if there is a recorder
    def stat(*args)
      @recorder.call(*args) if @recorder
    end

  end

end

{'repo_name': 'jruby/warbler', 'stars': '843', 'repo_language': 'Ruby', 'file_name': 'RunnableWarTestIT.java', 'mime_type': 'text/x-java', 'hash': 8876164814078047578, 'source_dataset': 'data'}


// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build !math_big_pure_go,ppc64 !math_big_pure_go,ppc64le

#include "textflag.h"

// This file provides fast assembly versions for the elementary
// arithmetic operations on vectors implemented in arith.go.

TEXT ·mulWW(SB),NOSPLIT,$0
	BR ·mulWW_g(SB)

TEXT ·divWW(SB),NOSPLIT,$0
	BR ·divWW_g(SB)

TEXT ·addVV(SB),NOSPLIT,$0
	BR ·addVV_g(SB)

TEXT ·subVV(SB),NOSPLIT,$0
	BR ·subVV_g(SB)

TEXT ·addVW(SB),NOSPLIT,$0
	BR ·addVW_g(SB)

TEXT ·subVW(SB),NOSPLIT,$0
	BR ·subVW_g(SB)

TEXT ·shlVU(SB),NOSPLIT,$0
	BR ·shlVU_g(SB)

TEXT ·shrVU(SB),NOSPLIT,$0
	BR ·shrVU_g(SB)

TEXT ·mulAddVWW(SB),NOSPLIT,$0
	BR ·mulAddVWW_g(SB)

TEXT ·addMulVVW(SB),NOSPLIT,$0
	BR ·addMulVVW_g(SB)

TEXT ·divWVW(SB),NOSPLIT,$0
	BR ·divWVW_g(SB)

TEXT ·bitLen(SB),NOSPLIT,$0
	BR ·bitLen_g(SB)

{'repo_name': 'deferpanic/gorump', 'stars': '317', 'repo_language': 'Go', 'file_name': 'Makefile', 'mime_type': 'text/x-makefile', 'hash': -1077677803180810922, 'source_dataset': 'data'}


describe('toBeEmptyObject', () => {
  let Foo;
  beforeEach(() => {
    Foo = function() {};
  });
  describe('when invoked', () => {
    describe('when subject IS an Object with no instance members', () => {
      beforeEach(() => {
        Foo.prototype = {
          b: 2
        };
      });
      it('should confirm', () => {
        expect(new Foo()).toBeEmptyObject();
        expect({}).toBeEmptyObject();
      });
    });
    describe('when subject is NOT an Object with no instance members', () => {
      it('should deny', () => {
        expect({
          a: 1
        }).not.toBeEmptyObject();
        expect(null).not.toBeNonEmptyObject();
      });
    });
  });
});

{'repo_name': 'JamieMason/Jasmine-Matchers', 'stars': '542', 'repo_language': 'JavaScript', 'file_name': 'describeWhenNotArray.js', 'mime_type': 'text/plain', 'hash': 4618891787403884037, 'source_dataset': 'data'}