text:
/**
 * @file
 * @brief  VFS-independent part of FAT driver
 * @data   9 Apr 2015
 * @author Denis Deryugin
 */

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <drivers/block_dev.h>
#include <fs/fat.h>
#include <mem/misc/pool.h>
#include <util/math.h>

#define LABEL    "EMBOX_DISK " /* Whitespace-padded 11-char string */
#define SYSTEM12 "FAT12   "
#define SYSTEM16 "FAT16   "
#define SYSTEM32 "FAT32   "

uint8_t fat_sector_buff[FAT_MAX_SECTOR_SIZE]; /* XXX */

uint32_t fat_get_next(struct fat_fs_info *fsi,
		struct dirinfo * dirinfo, struct dirent * dirent);

size_t bdev_blk_sz(struct block_dev *bdev) {
	return bdev->block_size;
}

static const char bootcode[130] =
	{ 0x0e, 0x1f, 0xbe, 0x5b, 0x7c, 0xac, 0x22, 0xc0, 0x74, 0x0b,
	  0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, 0xeb,
	  0xf0, 0x32, 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54,
	  0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74,
	  0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c,
	  0x65, 0x20, 0x64, 0x69, 0x73, 0x6b, 0x2e, 0x20, 0x20, 0x50,
	  0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x65,
	  0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61,
	  0x62, 0x6c, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x70, 0x70, 0x79,
	  0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, 0x65, 0x73,
	  0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20,
	  0x74, 0x6f, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61,
	  0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00 };

extern int fat_read_sector(struct fat_fs_info *fsi, uint8_t *buffer, uint32_t sector);
extern int fat_write_sector(struct fat_fs_info *fsi, uint8_t *buffer, uint32_t sector);

/**
 * @brief Format given block device
 *
 * @param dev Block device to be formatted
 * @param fat_n should be 12/16/32 or 0
 *
 * @return Negative error code or 0 if succeed
 */
int fat_create_partition(void *dev, int fat_n) {
	struct block_dev *bdev = dev;
	uint16_t bytepersec = bdev->block_size;
	size_t num_sect = block_dev(bdev)->size / bytepersec;
	assert(bdev->block_size <= FAT_MAX_SECTOR_SIZE);
	uint32_t secperfat = 1;
	uint16_t rootentries = 0x0200;             /* 512 for FAT16 */
	int reserved;
	int err;
	int i;
	int fat_size;
	int blkpersec;

	struct lbr lbr = (struct lbr) {
		.jump = {0xeb, 0x3c, 0x90},        /* JMP 0x3c; NOP; */
		.oemid = {0x45, 0x45, 0x45, 0x45,
		          0x45, 0x45, 0x45, 0x45}, /* ASCII "EEEEEEEE" */
		.bpb = {
			.bytepersec_l  = (uint8_t)(bytepersec & 0xFF),
			.bytepersec_h  = (uint8_t)((bytepersec & 0xFF00) >> 8),
			.secperclus    = 0x04,
			.reserved_l    = 0x01,     /* reserved sectors */
			.reserved_h    = 0x00,
			.numfats       = 0x02,     /* 2 FAT copy */
			.rootentries_l = (uint8_t)(0x00FF & rootentries ),
			.rootentries_h = (uint8_t)(0x00FF & (rootentries >> 8)),
			.mediatype     = 0xF8,     /* Fixed disk */
			.secpertrk_l   = 0x3F,     /* TODO use actual value? */
			.heads_l       = 0xFF,     /* TODO use actual value? */
			/* TODO handle hidden sectors? */
		},
		.sig_55 = 0x55,
		.sig_aa = 0xAA,
	};

	if (0xFFFF > num_sect)	{
		lbr.bpb.sectors_s_l = (uint8_t)(0x00000FF & num_sect);
		lbr.bpb.sectors_s_h = (uint8_t)(0x00000FF & (num_sect >> 8));
	} else {
		lbr.bpb.sectors_l_0 = (uint8_t)(0x00000FF & num_sect );
		lbr.bpb.sectors_l_1 = (uint8_t)(0x00000FF & (num_sect >> 8));
		lbr.bpb.sectors_l_2 = (uint8_t)(0x00000FF & (num_sect >> 16));
		lbr.bpb.sectors_l_3 = (uint8_t)(0x00000FF & (num_sect >> 24));
	}

	switch (fat_n) {
	case 12:
	case 16:
		lbr.bpb.secperfat_l   = (uint8_t)(0x00FF & secperfat),
		lbr.bpb.secperfat_h   = (uint8_t)(0x00FF & (secperfat >> 8)),
		lbr.ebpb.ebpb = (struct ebpb) {
			.unit      = 0x80, /* Hard disk */
			.signature = 0x29,
			.serial_0  = 0x81, /* We can actually ignore .serial_N */
			.serial_1  = 0xDB,
			.serial_2  = 0xF7,
			.serial_3  = 0xBB,
		};

		memcpy(lbr.ebpb.ebpb.label, LABEL, sizeof(lbr.ebpb.ebpb.label));
		memcpy(lbr.ebpb.ebpb.system,
		       fat_n == 12 ? SYSTEM12:SYSTEM16,
		       sizeof(lbr.ebpb.ebpb.system));

		memcpy(lbr.ebpb.ebpb.code, bootcode, sizeof(bootcode));
		break;
	case 32:
		lbr.ebpb.ebpb32 = (struct ebpb32) {
			.fatsize_0 = (uint8_t) (0xFF & secperfat),
			.fatsize_1 = (uint8_t) (0xFF & (secperfat >> 8)),
			.fatsize_2 = (uint8_t) (0xFF & (secperfat >> 16)),
			.fatsize_3 = (uint8_t) (0xFF & (secperfat >> 24)),
			/* TODO fill flags? */
			.fsver_l = 0x1, /* TODO fill actual fat version */
			.fsver_h = 0x1,
			.root_0  = 0x2, /* Root directory is in the second cluster */
			/* TODO fill fsinfo */
			.unit      = 0x80, /* Hard disk */
			.signature = 0x29,
			.serial_0  = 0x81, /* We can actually ignore .serial_N */
			.serial_1  = 0xDB,
			.serial_2  = 0xF7,
			.serial_3  = 0xBB,
			.label     = LABEL,
			.system    = SYSTEM32,
		};
		memcpy(lbr.ebpb.ebpb32.label, LABEL, sizeof(lbr.ebpb.ebpb32.label));
		memcpy(lbr.ebpb.ebpb32.system, SYSTEM32, sizeof(lbr.ebpb.ebpb32.system));
		memcpy(lbr.ebpb.ebpb32.code, bootcode, sizeof(bootcode));
		break;
	default:
		return -1;
	}

	if (0 > (err = block_dev_write(bdev, (void *) &lbr, sizeof(lbr), 0)))
		return err;

	/* Clear FAT from garbage */
	memset(fat_sector_buff, 0, sizeof(fat_sector_buff));
	reserved = (uint16_t) lbr.bpb.reserved_l |
		(((uint16_t) lbr.bpb.reserved_h) << 8);
	fat_size = lbr.bpb.numfats * secperfat;
	blkpersec = bytepersec / bdev->block_size;

	for (i = reserved; i < reserved + fat_size; i++)
		if (0 > (err = block_dev_write(bdev, (void*) fat_sector_buff, sizeof(fat_sector_buff), i * blkpersec)))
			return err;

	return 0;
}

/**
 *	Get starting sector# of specified partition on drive #unit
 *	NOTE: This code ASSUMES an MBR on the disk.
 *	p_scratchsector should point to a SECTOR_SIZE scratch area
 *	Returns 0xffffffff for any error.
 *	If pactive is non-NULL, this function also returns partition active flag.
 *	If pptype is non-NULL, this function also returns the partition type.
 *	If psize is non-NULL, this function also returns the partition size.
 */
uint32_t fat_get_ptn_start(void *bdev, uint8_t pnum, uint8_t *pactive,
		uint8_t *pptype, uint32_t *psize) {
	uint32_t result;
	struct mbr *mbr = (struct mbr*) fat_sector_buff;

	/* DOS ptable supports maximum 4 partitions */
	if (pnum > 3) {
		return DFS_ERRMISC;
	}

	if (0 > block_dev_read(bdev, (char *) fat_sector_buff, sizeof(struct mbr), 0)) {
		return DFS_ERRMISC;
	}
	/* check if that a lbr */
	if ((mbr->bootcode[0] == 0xeb) &&
		(mbr->bootcode[1] == 0x3c) &&
		(mbr->bootcode[2] == 0x90)) {
		return 0;
	}

	result = (uint32_t) mbr->ptable[pnum].start_0 |
		(((uint32_t) mbr->ptable[pnum].start_1) << 8) |
		(((uint32_t) mbr->ptable[pnum].start_2) << 16) |
		(((uint32_t) mbr->ptable[pnum].start_3) << 24);

	if (pactive) {
		*pactive = mbr->ptable[pnum].active;
	}

	if (pptype) {
		*pptype = mbr->ptable[pnum].type;
	}

	if (psize) {
		*psize = (uint32_t) mbr->ptable[pnum].size_0 |
			(((uint32_t) mbr->ptable[pnum].size_1) << 8) |
			(((uint32_t) mbr->ptable[pnum].size_2) << 16) |
			(((uint32_t) mbr->ptable[pnum].size_3) << 24);
	}

	return result;
}

/**
 * Retrieve volume info from BPB and store it in a volinfo_t structure
 * You must provide the unit and starting sector of the filesystem, and
 * a pointer to a sector buffer for scratch
 * Attempts to read BPB and glean information about the FS from that.
 * Returns 0 OK, nonzero for any error.
 */
uint32_t fat_get_volinfo(void *bdev, struct volinfo * volinfo, uint32_t startsector) {
	struct lbr *lbr = (struct lbr *) fat_sector_buff;

	volinfo->bytepersec = lbr->bpb.bytepersec_l + (lbr->bpb.bytepersec_h << 8);
	volinfo->startsector = startsector;

	if (0 > block_dev_read(	bdev,
				(char *) fat_sector_buff,
				sizeof(struct lbr),
				0)) { /* TODO start sector */
		return DFS_ERRMISC;
	}

	volinfo->secperclus = lbr->bpb.secperclus;
	volinfo->reservedsecs = (uint16_t) lbr->bpb.reserved_l |
		  (((uint16_t) lbr->bpb.reserved_h) << 8);

	volinfo->numsecs =  (uint16_t) lbr->bpb.sectors_s_l |
		  (((uint16_t) lbr->bpb.sectors_s_h) << 8);

	if (!volinfo->numsecs)
		volinfo->numsecs = (uint32_t) lbr->bpb.sectors_l_0 |
		  (((uint32_t) lbr->bpb.sectors_l_1) << 8) |
		  (((uint32_t) lbr->bpb.sectors_l_2) << 16) |
		  (((uint32_t) lbr->bpb.sectors_l_3) << 24);

	/**
	 * If secperfat is 0, we must be in a FAT32 volume
	 */
	volinfo->secperfat =  (uint16_t) lbr->bpb.secperfat_l |
		  (((uint16_t) lbr->bpb.secperfat_h) << 8);

	if (!volinfo->secperfat) {
		volinfo->secperfat = (uint32_t) lbr->ebpb.ebpb32.fatsize_0 |
		  (((uint32_t) lbr->ebpb.ebpb32.fatsize_1) << 8) |
		  (((uint32_t) lbr->ebpb.ebpb32.fatsize_2) << 16) |
		  (((uint32_t) lbr->ebpb.ebpb32.fatsize_3) << 24);

		memcpy(volinfo->label, lbr->ebpb.ebpb32.label, MSDOS_NAME);
		volinfo->label[11] = 0;
	} else {
		memcpy(volinfo->label, lbr->ebpb.ebpb.label, MSDOS_NAME);
		volinfo->label[11] = 0;
	}

	/* note: if rootentries is 0, we must be in a FAT32 volume. */
	volinfo->rootentries =  (uint16_t) lbr->bpb.rootentries_l |
		  (((uint16_t) lbr->bpb.rootentries_h) << 8);

	volinfo->fat1 = startsector + volinfo->reservedsecs;

	/**
	 * The calculation below is designed to round up the root directory size
	 * for FAT12/16 and to simply ignore the root directory for FAT32, since
	 * it's a normal, expandable file in that situation.
	 */

	if (volinfo->rootentries) {
		volinfo->rootdir = volinfo->fat1 + (volinfo->secperfat * 2);
		volinfo->dataarea = volinfo->rootdir
			+ (((volinfo->rootentries * 32) + (volinfo->bytepersec - 1))
			/ volinfo->bytepersec);
	} else {
		volinfo->dataarea = volinfo->fat1 + (volinfo->secperfat * 2);
		volinfo->rootdir = (uint32_t) lbr->ebpb.ebpb32.root_0 |
		  (((uint32_t) lbr->ebpb.ebpb32.root_1) << 8) |
		  (((uint32_t) lbr->ebpb.ebpb32.root_2) << 16) |
		  (((uint32_t) lbr->ebpb.ebpb32.root_3) << 24);
	}

	if (0 == volinfo->secperclus) {
		volinfo->numclusters = 0;
		return DFS_ERRMISC;
	} else {
		volinfo->numclusters = (volinfo->numsecs - volinfo->dataarea) /
			volinfo->secperclus;
	}

	if (volinfo->numclusters < 4085)
		volinfo->filesystem = FAT12;
	else if (volinfo->numclusters < 65525)
		volinfo->filesystem = FAT16;
	else
		volinfo->filesystem = FAT32;

	return DFS_OK;
}

/*
 *	Fetch FAT entry for specified cluster number You must provide a scratch
 *	buffer for one sector (SECTOR_SIZE) and a populated struct volinfo
 *	Returns a FAT32 BAD_CLUSTER value for any error, otherwise the contents
 *	of the desired FAT entry.
 *	p_scratchcache should point to a UINT32. This variable caches the physical
 *	sector number last read into the scratch buffer for performance
 *	enhancement reasons.
 */
uint32_t fat_get_fat_(struct fat_fs_info *fsi,
		uint8_t *p_scratch,	uint32_t *p_scratchcache, uint32_t cluster) {
	uint32_t offset, sector, result;
	struct volinfo *volinfo = &fsi->vi;

	switch (volinfo->filesystem) {
		case FAT12:
			offset = cluster + (cluster / 2);
			break;
		case FAT16:
			offset = cluster * 2;
			break;
		case FAT32:
			offset = cluster * 4;
			break;
		default:
			return DFS_BAD_CLUS;
	}

	sector = offset / volinfo->bytepersec + volinfo->fat1;

	if (sector != *p_scratchcache) {
		if (fat_read_sector(fsi, p_scratch, sector)) {
			/*
			 * avoid anyone assuming that this cache value is still valid,
			 * which might cause disk corruption
			 */
			*p_scratchcache = 0;
			return DFS_BAD_CLUS;
		}
		*p_scratchcache = sector;
	}

	/*
	 * At this point, we "merely" need to extract the relevant entry.
	 * This is easy for FAT16 and FAT32, but a royal PITA for FAT12 as
	 * a single entry may span a sector boundary. The normal way around this is
	 * always to read two FAT sectors, but that luxury is (by design intent)
	 * unavailable to DOSFS.
	 */
	offset %= volinfo->bytepersec;
	if (volinfo->filesystem == FAT12) {
		/* Special case for sector boundary - Store last byte of current sector
		 * Then read in the next sector and put the first byte of that sector
		 * into the high byte of result.
		 */
		if (offset == volinfo->bytepersec - 1) {
			result = (uint32_t) p_scratch[offset];
			sector++;
			if (fat_read_sector(fsi, p_scratch, sector)) {
				/*
				 * avoid anyone assuming that this cache value is still valid,
				 *  which might cause disk corruption
				 */
				*p_scratchcache = 0;
				return DFS_BAD_CLUS;
			}
			*p_scratchcache = sector;
			result |= ((uint32_t) p_scratch[0]) << 8;
		} else {
			result = (uint32_t) p_scratch[offset] |
			  ((uint32_t) p_scratch[offset+1]) << 8;
		}
		if (cluster & 1)
			result = result >> 4;
		else
			result = result & 0xfff;
	} else if (volinfo->filesystem == FAT16) {
		result = (uint32_t) p_scratch[offset] |
		  ((uint32_t) p_scratch[offset+1]) << 8;
	} else if (volinfo->filesystem == FAT32) {
		result = ((uint32_t) p_scratch[offset] |
		  ((uint32_t) p_scratch[offset+1]) << 8 |
		  ((uint32_t) p_scratch[offset+2]) << 16 |
		  ((uint32_t) p_scratch[offset+3]) << 24) & 0x0fffffff;
	} else
		result = DFS_BAD_CLUS;

	return result;
}

/*
 * Set FAT entry for specified cluster number
 * You must provide a scratch buffer for one sector (SECTOR_SIZE)
 * and a populated volinfo_t Returns DFS_ERRMISC for any error, otherwise
 * DFS_OK p_scratchcache should point to a UINT32. This variable caches the
 * physical sector number last read into the scratch buffer for performance
 * enhancement reasons.
 *
 * NOTE: This code is HIGHLY WRITE-INEFFICIENT, particularly for flash media.
 * Considerable performance gains can be realized by caching the sector.
 * However this is difficult to achieve on FAT12 without requiring 2 sector
 * buffers of scratch space, and it is a design requirement of this code to
 * operate on a single 512-byte scratch. If you are operating DOSFS over flash,
 * you are strongly advised to implement a writeback cache in your physical
 * I/O driver. This will speed up your code significantly and will
 * also conserve power and flash write life.
 */

uint32_t fat_set_fat_(struct fat_fs_info *fsi, uint8_t *p_scratch,
		uint32_t *p_scratchcache, uint32_t cluster, uint32_t new_contents) {
	uint32_t offset, sector, result;
	struct volinfo *volinfo = &fsi->vi;

	switch (volinfo->filesystem) {
		case FAT12:
			offset = cluster + (cluster / 2);
			new_contents &=0xfff;
			break;
		case FAT16:
			offset = cluster * 2;
			new_contents &=0xffff;
			break;
		case FAT32:
			offset = cluster * 4;
			new_contents &=0x0fffffff;	/* FAT32 is really "FAT28" */
			break;
		default:
			return DFS_ERRMISC;
	}
	/*
	 * at this point, offset is the BYTE offset of the desired sector from
	 * the start of the FAT.
	 * Calculate the physical sector containing this FAT entry.
	 */
	sector = offset / volinfo->bytepersec + volinfo->fat1;

	/* If this is not the same sector we last read, then read it into RAM */
	if (sector != *p_scratchcache) {
		if (fat_read_sector(fsi, p_scratch, sector)) {
			/*
			 * avoid anyone assuming that this cache value is still valid,
			 * which might cause disk corruption
			 */
			*p_scratchcache = 0;
			return DFS_ERRMISC;
		}
		*p_scratchcache = sector;
	}

	/*
	 * At this point, we "merely" need to extract the relevant entry.
	 * This is easy for FAT16 and FAT32, but a royal PITA for FAT12 as a
	 * single entry may span a sector boundary. The normal way around this
	 * is always to read two FAT sectors, but that luxury is (by design intent)
	 * unavailable to DOSFS.
	 */
	offset %= volinfo->bytepersec;

	switch (volinfo->filesystem) {
	case FAT12:
		if (cluster & 1)
			new_contents = new_contents << 4;

		if (offset == volinfo->bytepersec - 1) {
			/* Odd cluster: High 12 bits being set */
			if (cluster & 1) {
				p_scratch[offset] = (p_scratch[offset] & 0x0f) |
						(new_contents & 0xf0);
			}
			/* Even cluster: Low 12 bits being set */
			else {
				p_scratch[offset] = new_contents & 0xff;
			}
			result = fat_write_sector(fsi, p_scratch, *p_scratchcache);
			/* mirror the FAT into copy 2 */
			if (DFS_OK == result) {
				result = fat_write_sector(fsi, p_scratch,
						(*p_scratchcache) + volinfo->secperfat);
			}

			/*
			 * If we wrote that sector OK, then read in the subsequent sector
			 * and poke the first byte with the remainder of this FAT entry.
			 */
			if (DFS_OK == result) {
				(*p_scratchcache)++;
				result = fat_read_sector(fsi, p_scratch, *p_scratchcache);
				if (DFS_OK == result) {
					/* Odd cluster: High 12 bits being set*/
					if (cluster & 1) {
						p_scratch[0] = new_contents & 0xff00;
					}
					/* Even cluster: Low 12 bits being set */
					else {
						p_scratch[0] = (p_scratch[0] & 0xf0) |
								(new_contents & 0x0f);
					}
					result = fat_write_sector(fsi, p_scratch,
							*p_scratchcache);
					/* mirror the FAT into copy 2 */
					if (DFS_OK == result) {
						result = fat_write_sector(fsi, p_scratch,
								(*p_scratchcache)+volinfo->secperfat);
					}
				} else {
					/*
					 * avoid anyone assuming that this cache value is still
					 * valid, which might cause disk corruption
					 */
					*p_scratchcache = 0;
				}
			}
		}

		/*
		 * Not a sector boundary. But we still have to worry about if it's an
		 * odd or even cluster number.
		 */
		else {
			/* Odd cluster: High 12 bits being set */
			if (cluster & 1) {
				p_scratch[offset] = (p_scratch[offset] & 0x0f) |
						(new_contents & 0xf0);
				p_scratch[offset + 1] = (new_contents & 0xff00) >> 8;
			}
			/* Even cluster: Low 12 bits being set */
			else {
				p_scratch[offset] = new_contents & 0xff;
				p_scratch[offset+1] = (p_scratch[offset+1] & 0xf0) |
						((new_contents & 0x0f00) >> 8);
			}
			result = fat_write_sector(fsi, p_scratch, *p_scratchcache);
			/* mirror the FAT into copy 2 */
			if (DFS_OK == result) {
				result = fat_write_sector(fsi, p_scratch,
						(*p_scratchcache) + volinfo->secperfat);
			}
		}
		break;
	case FAT32:
		p_scratch[offset + 3] = (p_scratch[offset  + 3] & 0xf0) |
				((new_contents & 0x0f000000) >> 24);
		p_scratch[offset + 2] = (new_contents & 0xff0000) >> 16;
		/* Fall through */
	case FAT16:
		p_scratch[offset + 1] = (new_contents & 0xff00) >> 8;
		p_scratch[offset] = (new_contents & 0xff);
		result = fat_write_sector(fsi, p_scratch, *p_scratchcache);
		/* mirror the FAT into copy 2 */
		if (DFS_OK == result)
			result = fat_write_sector(
					fsi,
					p_scratch,
					(*p_scratchcache) + volinfo->secperfat
				);
		break;
	default:
		result = DFS_ERRMISC;
	}
	return result;
}

/*
 * 	Find the first unused FAT entry
 * 	You must provide a scratch buffer for one sector (SECTOR_SIZE) and a
 * 	populated volinfo_t Returns a FAT32 BAD_CLUSTER value for any error,
 * 	otherwise the contents of the desired FAT entry.
 * 	Returns FAT32 bad_sector (0x0ffffff7) if there is no free cluster available
 */
uint32_t fat_get_free_fat_(struct fat_fs_info *fsi, uint8_t *p_scratch) {
	uint32_t i, result = 0xffffffff, p_scratchcache = 0;
	/*
	 * Search starts at cluster 2, which is the first usable cluster
	 * NOTE: This search can't terminate at a bad cluster, because there might
	 * legitimately be bad clusters on the disk.
	 */
	for (i = 2; i < fsi->vi.numclusters; i++) {
		result = fat_get_fat_(fsi, p_scratch, &p_scratchcache, i);
		if (!result)
			return i;
	}
	return DFS_BAD_CLUS;
}

static inline int dir_is_root(uint8_t *name) {
	return !strlen((char *) name) ||
		((strlen((char *) name) == 1) && (name[0] == DIR_SEPARATOR));
}

/*
 * Open a directory for enumeration by fat_get_nextDirEnt
 * You must supply a populated volinfo_t (see fat_get_volinfo)
 * The empty string or a string containing only the directory separator are
 * considered to be the root directory.
 * Returns 0 OK, nonzero for any error.
 */
uint32_t fat_open_dir(struct fat_fs_info *fsi,
		uint8_t *dirname, struct dirinfo *dirinfo) {
	struct volinfo *volinfo;

	assert(fsi);

	volinfo = &fsi->vi;
	dirinfo->flags = 0;
	dirinfo->currentsector = 0;
	dirinfo->currententry = 0;

	if (dir_is_root(dirname)) {
		dirinfo->currentcluster = volinfo->rootdir / volinfo->secperclus;
		if (volinfo->filesystem == FAT32)
			dirinfo->currentsector = volinfo->dataarea +
				((volinfo->rootdir - 2) * volinfo->secperclus);
		else
			dirinfo->currentsector = (volinfo->rootdir % volinfo->secperclus);
		return fat_read_sector(fsi, dirinfo->p_scratch, dirinfo->currentsector + dirinfo->currentcluster * volinfo->secperclus);
	} else {
		uint8_t tmpfn[12];
		uint8_t *ptr = dirname;
		uint32_t result;
		struct dirent de;

		if (volinfo->filesystem == FAT32) {
			dirinfo->currentcluster = volinfo->rootdir / volinfo->secperclus;
			if (fat_read_sector(fsi, dirinfo->p_scratch, volinfo->dataarea +
					((volinfo->rootdir - 2) * volinfo->secperclus))) {
				return DFS_ERRMISC;
			}
		} else {
			dirinfo->currentcluster = 0;
			if (fat_read_sector(fsi, dirinfo->p_scratch, volinfo->rootdir)) {
				return DFS_ERRMISC;
			}
		}

		while (*ptr == DIR_SEPARATOR && *ptr) {
			ptr++;
		}

		/*
		 *  Scan the path from left to right, finding the start cluster
		 *  of each entry.  Observe that this code is inelegant, but obviates
		 *  the need for recursion.
		 */
		while (*ptr) {
			path_canonical_to_dir((char *) tmpfn, (char *) ptr);

			de.name[0] = '\0';

			do {
				result = fat_get_next(fsi, dirinfo, &de);
			} while (!result && memcmp(de.name, tmpfn, MSDOS_NAME));

			if (!memcmp(de.name, tmpfn, MSDOS_NAME) && (de.attr & ATTR_DIRECTORY)) {
				if (volinfo->filesystem == FAT32) {
					dirinfo->currentcluster = (uint32_t) de.startclus_l_l |
					  ((uint32_t) de.startclus_l_h) << 8 |
					  ((uint32_t) de.startclus_h_l) << 16 |
					  ((uint32_t) de.startclus_h_h) << 24;
				}
				else {
					dirinfo->currentcluster = (uint32_t) de.startclus_l_l |
					  ((uint32_t) de.startclus_l_h) << 8;
				}
				dirinfo->currentsector = 0;
				dirinfo->currententry = 0;

				if (fat_read_sector(fsi, dirinfo->p_scratch, volinfo->dataarea +
					((dirinfo->currentcluster - 2) * volinfo->secperclus))) {
					return DFS_ERRMISC;
				}
			} else if (!memcmp(de.name, tmpfn, MSDOS_NAME) && !(de.attr & ATTR_DIRECTORY))
				return DFS_WRONGRES;

			while (*ptr != DIR_SEPARATOR && *ptr)
				ptr++;

			while (*ptr == DIR_SEPARATOR)
				ptr++;
		}

		if (!dirinfo->currentcluster)
			return DFS_NOTFOUND;
	}

	return DFS_OK;
}

/*
 * Get next entry in opened directory structure.
 * Copies fields into the dirent structure, updates dirinfo. Note that it is
 * the _caller's_ responsibility to	handle the '.' and '..' entries.
 * A deleted file will be returned as a NULL entry (first char of filename=0)
 * by this code. Filenames beginning with 0x05 will be translated to 0xE5
 * automatically. Long file name entries will be returned as NULL.
 * returns DFS_EOF if there are no more entries, DFS_OK if this entry is valid,
 * or DFS_ERRMISC for a media error
 */
uint32_t fat_get_next(struct fat_fs_info *fsi,
		struct dirinfo *dir, struct dirent *dirent) {
	struct volinfo *volinfo;
	void *dirent_src;
	uint32_t tempint;
	int next_ent;
	int ent_per_sec;
	int end_of_chain;
	int read_sector;

	volinfo = &fsi->vi;
	ent_per_sec = volinfo->bytepersec / sizeof(struct dirent);

	/* Do we need to read the next sector of the directory? */
	if (dir->currententry >= ent_per_sec) {
		dir->currententry = 0;
		dir->currentsector++;

		/* Root directory; special case handling
		 * Note that currentcluster will only ever be zero if both:
		 * (a) this is the root directory, and
		 * (b) we are on a FAT12/16 volume, where the root dir can't be
		 * expanded
		 */
		if (dir->currentcluster == 0) {
			/* Trying to read past end of root directory? */
			next_ent  = dir->currentsector * volinfo->bytepersec;
			next_ent /= sizeof(struct dirent);
			if (next_ent >= volinfo->rootentries)
				return DFS_EOF;

			/* Otherwise try to read the next sector */
			if (fat_read_sector(fsi, dir->p_scratch, dir->currentsector))
				return DFS_ERRMISC;
		} else {
			if (dir->currentsector >= volinfo->secperclus) {
				dir->currentsector = 0;
				switch (volinfo->filesystem) {
				case FAT12:
					end_of_chain = dir->currentcluster >= 0xff7;
					break;
				case FAT16:
					end_of_chain = dir->currentcluster >= 0xfff7;
					break;
				case FAT32:
					end_of_chain = dir->currentcluster >= 0xffffff7;
					break;
				default:
					return DFS_ERRMISC;
				}

				if (end_of_chain) {
					/* We are at the end of the directory chain.
					 * If this is a normal find operation, we should indicate
					 * that there is nothing more to see.
					 */
					if (!(dir->flags & DFS_DI_BLANKENT))
						return DFS_EOF;
					/*
					 * On the other hand, if this is a "find free entry"
					 * search, we need to tell the caller to allocate a
					 * new cluster
					 */
					else
						return DFS_ALLOCNEW;
				}

				dir->currentcluster = fat_get_fat_(fsi, dir->p_scratch, &tempint, dir->currentcluster);
			}

			read_sector  = (dir->currentcluster - 2) * volinfo->secperclus;
			read_sector += volinfo->dataarea + dir->currentsector;

			if (fat_read_sector(fsi, dir->p_scratch, read_sector))
				return DFS_ERRMISC;
		}
	}

	dirent_src = &((struct dirent*) dir->p_scratch)[dir->currententry];
	memcpy(dirent, dirent_src, sizeof(struct dirent));

	if (dirent->name[0] == '\0') {
		if (dir->flags & DFS_DI_BLANKENT) {
			dir->currententry++; // DOSFS 1.03 BUG, currententry was not incremented in this case
			return DFS_OK;
		} else
			return DFS_EOF;
	}

	if (dirent->name[0] == 0xe5 || (dirent->attr & ATTR_LONG_NAME) == ATTR_LONG_NAME)
		dirent->name[0] = '\0';
	else if (dirent->name[0] == 0x05)
		/* handle kanji filenames beginning with 0xE5 */
		dirent->name[0] = 0xe5;

	dir->currententry++;

	return DFS_OK;
}

/*
 * INTERNAL
 * Find a free directory entry in the directory specified by path
 * This function MAY cause a disk write if it is necessary to extend the
 * directory size.
 * Note - di.p_scratch must be preinitialized to point to a sector scratch buffer
 * de is a scratch structure
 * Returns DFS_ERRMISC if a new entry could not be located or created
 * de is updated with the same return information you would expect
 * from fat_get_next
 */
uint32_t fat_get_free_dir_ent(struct fat_fs_info *fsi, uint8_t *path,
		struct dirinfo *di, struct dirent *de) {
	uint32_t tempclus,i;
	struct volinfo *volinfo;

	volinfo = &fsi->vi;

	//if (fat_open_dir(fsi, path, di)) {
	//	return DFS_NOTFOUND;
	//}

	di->flags |= DFS_DI_BLANKENT;

	/*
	 * Note we are reusing tempclus as a temporary result holder.
	 */
	tempclus = 0;
	do {
		tempclus = fat_get_next(fsi, di, de);

		if (tempclus == DFS_OK && (!de->name[0])) {
			return DFS_OK;
		} else if (tempclus == DFS_EOF) {
			return DFS_ERRMISC;
		} else if (tempclus == DFS_ALLOCNEW) {
			tempclus = fat_get_free_fat_(fsi, di->p_scratch);
			if (tempclus == DFS_BAD_CLUS) {
				return DFS_ERRMISC;
			}

			memset(di->p_scratch, 0, volinfo->bytepersec);
			for (i = 0; i < volinfo->secperclus; i++) {
				if (fat_write_sector(fsi, di->p_scratch,
						volinfo->dataarea + ((tempclus - 2) *
								volinfo->secperclus) + i)) {
					return DFS_ERRMISC;
				}
			}
			i = 0;
			fat_set_fat_(fsi,
					di->p_scratch, &i, di->currentcluster, tempclus);

			di->currentcluster = tempclus;
			di->currentsector = 0;
			di->currententry = 0; /* tempclus is not zero but contains fat entry, so next loop will call */
			switch(volinfo->filesystem) {
				case FAT12:		tempclus = 0xfff;	break;
				case FAT16:		tempclus = 0xffff;	break;
				case FAT32:		tempclus = 0x0fffffff;	break;
				default:		return DFS_ERRMISC;
			}
			fat_set_fat_(fsi, di->p_scratch, &i, di->currentcluster, tempclus);
		}
	} while (!tempclus);

	/* We shouldn't get here */
	return DFS_ERRMISC;
}

void fat_set_direntry (uint32_t dir_cluster, uint32_t cluster) {
	struct dirent *de = (struct dirent *) fat_sector_buff;

	de[0] = (struct dirent) {
		.name = MSDOS_DOT,
		.attr = ATTR_DIRECTORY,
		.startclus_l_l = cluster & 0xff,
		.startclus_l_h = (cluster & 0xff00) >> 8,
		.startclus_h_l = (cluster & 0xff0000) >> 16,
		.startclus_h_h = (cluster & 0xff000000) >> 24,
	};

	de[1] = (struct dirent) {
		.name = MSDOS_DOTDOT,
		.attr = ATTR_DIRECTORY,
		.startclus_l_l = dir_cluster & 0xff,
		.startclus_l_h = (dir_cluster & 0xff00) >> 8,
		.startclus_h_l = (dir_cluster & 0xff0000) >> 16,
		.startclus_h_h = (dir_cluster & 0xff000000) >> 24,
	};

	fat_set_filetime(&de[0]);
	fat_set_filetime(&de[1]);
}

int fat_root_dir_record(void *bdev) {
	uint32_t cluster;
	struct fat_fs_info fsi;
	uint32_t pstart, psize;
	uint8_t pactive, ptype;
	struct dirent de;
	int dev_blk_size = bdev_blk_sz(bdev);
	int root_dir_sz;

	assert(dev_blk_size > 0);

	fsi.bdev = bdev;

	/* Obtain pointer to first partition on first (only) unit */
	pstart = fat_get_ptn_start(bdev, 0, &pactive, &ptype, &psize);
	if (pstart == 0xffffffff) {
		return -1;
	}

	if (fat_get_volinfo(bdev, &fsi.vi, pstart)) {
		return -1;
	}

	cluster = fsi.vi.rootdir / fsi.vi.secperclus;

	de = (struct dirent) {
		.name = "ROOT DIR   ",
		.attr = ATTR_DIRECTORY,
		.startclus_l_l = cluster & 0xff,
		.startclus_l_h = (cluster & 0xff00) >> 8,
		.startclus_h_l = (cluster & 0xff0000) >> 16,
		.startclus_h_h = (cluster & 0xff000000) >> 24,
	};

	fat_set_filetime(&de);

	/*
	 * write the directory entry
	 * note that we no longer have the sector containing the directory
	 * entry, tragically, so we have to re-read it
	 */

	/* we clear other FAT TABLE */
	memset(fat_sector_buff, 0, sizeof(fat_sector_buff));
	memcpy(&(((struct dirent*) fat_sector_buff)[0]), &de, sizeof(struct dirent));

	if (0 > block_dev_write(	bdev,
					(char *) fat_sector_buff,
					fsi.vi.bytepersec,
					fsi.vi.rootdir * fsi.vi.bytepersec / dev_blk_size)) {
		return DFS_ERRMISC;
	}

	root_dir_sz = (fsi.vi.rootentries * sizeof(struct dirent) +
	               fsi.vi.bytepersec - 1) / fsi.vi.bytepersec - 1;

	if (root_dir_sz)
		memset(fat_sector_buff, 0, sizeof(struct dirent)); /* The rest is zeroes already */
	/* Clear the rest of root directory */
	while (root_dir_sz) {
		block_dev_write(bdev,
				(char *) fat_sector_buff,
				fsi.vi.bytepersec,
				(root_dir_sz + fsi.vi.rootdir) * fsi.vi.bytepersec / dev_blk_size);
		root_dir_sz--;
	}

	/* Mark newly allocated cluster as end of chain */
	switch (fsi.vi.filesystem) {
		case FAT12:		cluster = 0xfff;	break;
		case FAT16:		cluster = 0xffff;	break;
		case FAT32:		cluster = 0x0fffffff;	break;
		default:		return DFS_ERRMISC;
	}
	psize = 0;
	fat_set_fat_(&fsi, fat_sector_buff, &psize, cluster, cluster);

	return DFS_OK;
}

/*
 * Read an open file
 * You must supply a prepopulated file_info_t as provided by fat_open_file,
 * and a pointer to a volinfo->bytepersec scratch buffer.
 * 	Note that returning DFS_EOF is not an error condition. This function
 * 	updates the	successcount field with the number of bytes actually read.
 */
uint32_t fat_read_file(struct fat_file_info *fi, uint8_t *p_scratch,
		uint8_t *buffer, uint32_t *successcount, uint32_t len) {
	uint32_t remain;
	uint32_t result;
	uint32_t sector;
	uint32_t bytesread;
	uint32_t clastersize;
	struct fat_fs_info *fsi;
	fsi = fi->fsi;

	result = DFS_OK;
	remain = len;
	*successcount = 0;
	clastersize = fi->volinfo->secperclus * fi->volinfo->bytepersec;

	while (remain && result == DFS_OK) {
		/* This is a bit complicated. The sector we want to read is addressed
		 * at a cluster granularity by the fi->cluster member. The file
		 * pointer tells us how many extra sectors to add to that number.
		 */
		sector = fi->volinfo->dataarea +
		  ((fi->cluster - 2) * fi->volinfo->secperclus) +
		  div(div(fi->pointer, clastersize).rem, fi->volinfo->bytepersec).quot;

		/* Case 1 - File pointer is not on a sector boundary */
		if (div(fi->pointer, fi->volinfo->bytepersec).rem) {
			uint16_t tempreadsize;

			/* We always have to go through scratch in this case */
			result = fat_read_sector(fsi, p_scratch, sector);

			/*
			 * This is the number of bytes that we actually care about in the
			 * sector just read.
			 */
			tempreadsize = fi->volinfo->bytepersec -
					(div(fi->pointer, fi->volinfo->bytepersec).rem);

			/* Case 1A - We want the entire remainder of the sector. After this
			 * point, all passes through the read loop will be aligned on a
			 * sector boundary, which allows us to go through the optimal path
			 *  2A below.
			 */
		   	if (remain >= tempreadsize) {
				memcpy(buffer, p_scratch + (fi->volinfo->bytepersec - tempreadsize),
						tempreadsize);
				bytesread = tempreadsize;
				buffer += tempreadsize;
				fi->pointer += tempreadsize;
				remain -= tempreadsize;
			}
			/* Case 1B - This read concludes the file read operation */
			else {
				memcpy(buffer, p_scratch +
						(fi->volinfo->bytepersec - tempreadsize), remain);

				buffer += remain;
				fi->pointer += remain;
				bytesread = remain;
				remain = 0;
			}
		}
		/* Case 2 - File pointer is on sector boundary */
		else {
			/*
			 * Case 2A - We have at least one more full sector to read and
			 * don't have to go through the scratch buffer. You could insert
			 * optimizations here to read multiple sectors at a time, if you
			 * were thus inclined (note that the maximum multi-read you could
			 * perform is a single cluster, so it would be advantageous to have
			 * code similar to case 1A above that would round the pointer to a
			 * cluster boundary the first pass through, so all subsequent
			 * [large] read requests would be able to go a cluster at a time).
			 */
			 if (remain >= fi->volinfo->bytepersec) {
				result = fat_read_sector(fsi, buffer, sector);
				remain -= fi->volinfo->bytepersec;
				buffer += fi->volinfo->bytepersec;
				fi->pointer += fi->volinfo->bytepersec;
				bytesread = fi->volinfo->bytepersec;
			}
			/* Case 2B - We are only reading a partial sector */
			else {
				result = fat_read_sector(fsi, p_scratch, sector);
				memcpy(buffer, p_scratch, remain);
				buffer += remain;
				fi->pointer += remain;
				bytesread = remain;
				remain = 0;
			}
		}

		*successcount += bytesread;
		/* check to see if we stepped over a cluster boundary */
		if (div(fi->pointer - bytesread, clastersize).quot !=
			div(fi->pointer, clastersize).quot) {
			/*
			 * An act of minor evil - we use bytesread as a scratch integer,
			 * knowing that its value is not used after updating *successcount
			 * above
			 */
			bytesread = 0;
			if (((fi->volinfo->filesystem == FAT12) &&
					(fi->cluster >= 0xff8)) ||
					((fi->volinfo->filesystem == FAT16) &&
							(fi->cluster >= 0xfff8)) ||
							((fi->volinfo->filesystem == FAT32) &&
									(fi->cluster >= 0x0ffffff8))) {
				result = DFS_EOF;
			}
			else {
				fi->cluster = fat_get_fat_(fsi, p_scratch, &bytesread, fi->cluster);
			}
		}
	}

	return result;
}

/*
 * Write an open file
 * You must supply a prepopulated file_info_t as provided by
 * fat_open_file, and a pointer to a SECTOR_SIZE scratch buffer.
 * This function updates the successcount field with the number
 * of bytes actually written.
 */
uint32_t fat_write_file(struct fat_file_info *fi, uint8_t *p_scratch,
		uint8_t *buffer, uint32_t *successcount, uint32_t len, size_t *size) {
	uint32_t remain;
	uint32_t result = DFS_OK;
	uint32_t sector;
	uint32_t byteswritten;
	uint32_t lastcluster, nextcluster;
	uint32_t clastersize;
	struct fat_fs_info *fsi;
	fsi = fi->fsi;

	if (!(fi->mode & O_WRONLY) && !(fi->mode & O_APPEND) && !(fi->mode & O_RDWR)) {
		return DFS_ERRMISC;
	}

	remain = len;
	*successcount = 0;
	clastersize = fi->volinfo->secperclus * fi->volinfo->bytepersec;

	while (remain && result == DFS_OK) {
		/*
		 * This is a bit complicated. The sector we want to read is addressed
		 * at a cluster granularity by  the fi->cluster member.
		 * The file pointer tells us how many extra sectors to add to that
		 * number.
		 */
		sector = fi->volinfo->dataarea +
		  ((fi->cluster - 2) * fi->volinfo->secperclus) +
		  div(div(fi->pointer, clastersize).rem, fi->volinfo->bytepersec).quot;

		/* Case 1 - File pointer is not on a sector boundary */
		if (div(fi->pointer, fi->volinfo->bytepersec).rem) {
			uint16_t tempsize;

			/* We always have to go through scratch in this case */
			result = fat_read_sector(fsi, p_scratch, sector);

			/*
			 * This is the number of bytes that we don't want to molest in the
			 * scratch sector just read.
			 */
			tempsize = div(fi->pointer, fi->volinfo->bytepersec).rem;

			/*
			 * Case 1A - We are writing the entire remainder of the sector.
			 * After this point, all passes through the read loop will be
			 * aligned on a sector boundary, which allows us to go through the
			 * optimal path
			 * 2A below.
			 */
		   	if (remain >= fi->volinfo->bytepersec - tempsize) {
				memcpy(p_scratch + tempsize, buffer, fi->volinfo->bytepersec - tempsize);
				if (!result) {
					result = fat_write_sector(fsi, p_scratch, sector);
				}

				byteswritten = fi->volinfo->bytepersec - tempsize;
				buffer += fi->volinfo->bytepersec - tempsize;
				fi->pointer += fi->volinfo->bytepersec - tempsize;
				if (*size < fi->pointer) {
					*size = fi->pointer;
				}
				remain -= fi->volinfo->bytepersec - tempsize;
			}
			/* Case 1B - This concludes the file write operation */
			else {
				memcpy(p_scratch + tempsize, buffer, remain);
				if (!result) {
					result = fat_write_sector(fsi, p_scratch, sector);
				}

				buffer += remain;
				fi->pointer += remain;
				if (*size < fi->pointer) {
					*size = fi->pointer;
				}
				byteswritten = remain;
				remain = 0;
			}
		} /* case 1 */
		/* Case 2 - File pointer is on sector boundary */
		else {
			/* Case 2A - We have at least one more full sector to write and
			 * don't have to go through the scratch buffer. You could insert
			 * optimizations here to write multiple sectors at a time, if you
			 * were thus inclined. Refer to similar notes in fat_read_file.
			 */
			if (remain >= fi->volinfo->bytepersec) {
				result = fat_write_sector(fsi, buffer, sector);
				remain -= fi->volinfo->bytepersec;
				buffer += fi->volinfo->bytepersec;
				fi->pointer += fi->volinfo->bytepersec;
				if (*size < fi->pointer) {
					*size = fi->pointer;
				}
				byteswritten = fi->volinfo->bytepersec;
			}
			/*
			 * Case 2B - We are only writing a partial sector and potentially
			 * need to go through the scratch buffer.
			 */
			else {
				/* If the current file pointer is not yet at or beyond the file
				 * length, we are writing somewhere in the middle of the file
				 * and need to load the original sector to do
				 * a read-modify-write.
				 */
				if (fi->pointer < *size) {
					result = fat_read_sector(fsi, p_scratch, sector);
					if (!result) {
						memcpy(p_scratch, buffer, remain);
						result = fat_write_sector(fsi, p_scratch, sector);
					}
				}
				else {
					memset(p_scratch, 0, fi->volinfo->bytepersec);
					memcpy(p_scratch, buffer, remain);
					result = fat_write_sector(fsi, p_scratch, sector);
				}

				buffer += remain;
				fi->pointer += remain;
				if (*size < fi->pointer) {
					*size = fi->pointer;
				}
				byteswritten = remain;
				remain = 0;
			}
		}

		*successcount += byteswritten;

		/* check to see if we stepped over a cluster boundary */
		if (div(fi->pointer - byteswritten, clastersize).quot !=
				div(fi->pointer, clastersize).quot) {

		  	/* We've transgressed into another cluster. If we were already
		  	 * at EOF, we need to allocate a new cluster.
		  	 * An act of minor evil - we use byteswritten as a scratch integer,
		  	 * knowing that its value is not used after updating *successcount
		  	 * above
		  	 */
		  	byteswritten = 0;

			lastcluster = fi->cluster;
			fi->cluster = fat_get_fat_(fsi, p_scratch,
					&byteswritten, fi->cluster);

			/* Allocate a new cluster? */
			if (((fi->volinfo->filesystem == FAT12) &&
					(fi->cluster >= 0xff8)) ||
					((fi->volinfo->filesystem == FAT16) &&
					(fi->cluster >= 0xfff8)) ||
					((fi->volinfo->filesystem == FAT32) &&
					(fi->cluster >= 0x0ffffff8))) {
			  	uint32_t tempclus;
				tempclus = fat_get_free_fat_(fsi, p_scratch);
				byteswritten = 0; /* invalidate cache */
				if (tempclus == DFS_BAD_CLUS)
					return DFS_ERRMISC;
				/* Link new cluster onto file */
				fat_set_fat_(fsi, p_scratch,
						&byteswritten, lastcluster, tempclus);
				fi->cluster = tempclus;

				/* Mark newly allocated cluster as end of chain */
				switch(fi->volinfo->filesystem) {
					case FAT12:		tempclus = 0xfff;	break;
					case FAT16:		tempclus = 0xffff;	break;
					case FAT32:		tempclus = 0x0fffffff;	break;
					default:		return DFS_ERRMISC;
				}
				fat_set_fat_(fsi, p_scratch,
						&byteswritten, fi->cluster, tempclus);

				result = DFS_OK;
			}
		}
	}
	/* If cleared, then mark free clusters*/
	// TODO implement fat truncate
	if (0 && *size > fi->pointer) {
		if (div(*size, clastersize).quot !=
			div(fi->pointer, clastersize).quot) {

			byteswritten = 0;/* invalidate cache */
			nextcluster = fat_get_fat_(fsi, p_scratch,
					&byteswritten, fi->cluster);

			switch(fi->volinfo->filesystem) {
				case FAT12:		lastcluster = 0xfff;	break;
				case FAT16:		lastcluster = 0xfff;	break;
				case FAT32:		lastcluster = 0x0fffffff;	break;
				default:		return DFS_ERRMISC;
			}
			fat_set_fat_(fsi, p_scratch, &byteswritten,
					fi->cluster, lastcluster);

			/* Now follow the cluster chain to free the file space */
			while (!((fi->volinfo->filesystem == FAT12 &&
					nextcluster >= 0x0ff7) ||
					(fi->volinfo->filesystem == FAT16 &&
					nextcluster >= 0xfff7) ||
					(fi->volinfo->filesystem == FAT32 &&
					nextcluster >= 0x0ffffff7))) {
				lastcluster = nextcluster;
				nextcluster = fat_get_fat_(fsi, p_scratch,
						&byteswritten, nextcluster);

				fat_set_fat_(fsi, p_scratch,
						&byteswritten, lastcluster, 0);
			}

		}
	}

	//*size = fi->pointer; // TODO implement fat truncate

	/* Update directory entry */
	if (fat_read_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}

	((struct dirent*) p_scratch)[fi->diroffset].filesize_0 =
			 *size & 0xff;

	((struct dirent*) p_scratch)[fi->diroffset].filesize_1 =
			(*size & 0xff00) >> 8;

	((struct dirent*) p_scratch)[fi->diroffset].filesize_2 =
			(*size & 0xff0000) >> 16;

	((struct dirent*) p_scratch)[fi->diroffset].filesize_3 =
			(*size & 0xff000000) >> 24;

	if (fat_write_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}

	return result;
}

/*
 * Open a file for reading or writing. You supply populated volinfo_t,
 * a path to the file, mode (DFS_READ or DFS_WRITE) and an empty fileinfo
 * structure. You also need to provide a pointer to a sector-sized scratch
 * buffer.
 * Returns various DFS_* error states. If the result is DFS_OK, fileinfo
 * can be used to access the file from this point on.
 */
uint32_t fat_open_file(struct fat_file_info *fi, uint8_t *path, int mode,
		uint8_t *p_scratch, size_t *size) {
	char tmppath[PATH_MAX];
	uint8_t filename[12];
	struct dirinfo di;
	struct dirent de;

	struct volinfo *volinfo;
	struct fat_fs_info *fsi;

	fsi = fi->fsi;
	volinfo = &fsi->vi;

	fi->mode = mode;

	strncpy((char *) tmppath, (char *) path, PATH_MAX);
	tmppath[PATH_MAX - 1] = 0;
	if (strcmp((char *) path,(char *) tmppath)) {
		return DFS_PATHLEN;
	}

	fat_get_filename(tmppath, (char *) filename);

	/*
	 *  At this point, if our path was MYDIR/MYDIR2/FILE.EXT,
	 *  filename = "FILE    EXT" and  tmppath = "MYDIR/MYDIR2".
	 */

	di.p_scratch = p_scratch;
	if (fat_open_dir(fsi, (uint8_t *) tmppath, &di)) {
		return DFS_NOTFOUND;
	}

	while (!fat_get_next(fsi, &di, &de)) {
		path_canonical_to_dir(tmppath, (char *) de.name);
		if (!memcmp(tmppath, filename, MSDOS_NAME)) {
			if (de.attr & ATTR_DIRECTORY){
				return DFS_WRONGRES;
			}

			fi->volinfo = volinfo;
			fi->pointer = 0;
			/*
			 * The reason we store this extra info about the file is so that we
			 * can speedily update the file size, modification date, etc. on a
			 * file that is opened for writing.
			 */
			if (di.currentcluster == 0) {
				fi->dirsector = volinfo->rootdir + di.currentsector;
			} else {
				fi->dirsector = volinfo->dataarea +
						((di.currentcluster - 2) *
						volinfo->secperclus) + di.currentsector;
			}
			fi->diroffset = di.currententry - 1;
			if (volinfo->filesystem == FAT32) {
				fi->cluster = (uint32_t) de.startclus_l_l |
				  ((uint32_t) de.startclus_l_h) << 8 |
				  ((uint32_t) de.startclus_h_l) << 16 |
				  ((uint32_t) de.startclus_h_h) << 24;
			} else {
				fi->cluster = (uint32_t) de.startclus_l_l |
				  ((uint32_t) de.startclus_l_h) << 8;
			}
			fi->firstcluster = fi->cluster;
			fi->filelen = (uint32_t) de.filesize_0 |
			              ((uint32_t) de.filesize_1) << 8 |
			              ((uint32_t) de.filesize_2) << 16 |
			              ((uint32_t) de.filesize_3) << 24;
			if (size)
				*size = fi->filelen;
			return DFS_OK;
		}
	}
	return DFS_NOTFOUND;
}

/*
 * Delete a file
 * p_scratch must point to a sector-sized buffer
 */
int fat_unlike_file(struct fat_file_info *fi, uint8_t *path,
		uint8_t *p_scratch) {
	uint32_t cache;
	uint32_t tempclus;
	struct volinfo *volinfo;
	struct fat_fs_info *fsi;

	fsi = fi->fsi;
	volinfo = &fsi->vi;
	cache = 0;

	/* if (DFS_OK != fat_open_file(fi, path, O_RDONLY, p_scratch, NULL)) {
		return DFS_NOTFOUND;
	} */

	if (fat_read_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}
	((struct dirent*) p_scratch)[fi->diroffset].name[0] = 0xe5;
	if (fat_write_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}

	/* Now follow the cluster chain to free the file space */
	while (!((volinfo->filesystem == FAT12 && fi->firstcluster >= 0x0ff7) ||
			(volinfo->filesystem == FAT16 && fi->firstcluster >= 0xfff7) ||
			(volinfo->filesystem == FAT32 && fi->firstcluster >= 0x0ffffff7))) {
		tempclus = fi->firstcluster;
		//assert(fsi->bdev == nas->fs->bdev);
		fi->firstcluster = fat_get_fat_(fsi, p_scratch,
				&cache, fi->firstcluster);
		//assert(nas->fs->bdev == fsi->bdev);
		fat_set_fat_(fsi, p_scratch, &cache, tempclus, 0);
	}
	return DFS_OK;
}

/*
 * Delete a file
 * p_scratch must point to a sector-sized buffer
 */
int fat_unlike_directory(struct fat_file_info *fi, uint8_t *path,
		uint8_t *p_scratch) {
	uint32_t cache;
	uint32_t tempclus;
	struct volinfo *volinfo;
	struct fat_fs_info *fsi;

	fsi = fi->fsi;
	volinfo = &fsi->vi;

	cache = 0;

	/* fat_open_file gives us all the information we need to delete it */
	/* if (DFS_OK != fat_open_file(fi, path, O_RDONLY, p_scratch, NULL)) {
		return DFS_NOTFOUND;
	} */

	/* First, read the directory sector and delete that entry */
	if (fat_read_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}
	((struct dirent*) p_scratch)[fi->diroffset].name[0] = 0xe5;
	if (fat_write_sector(fsi, p_scratch, fi->dirsector)) {
		return DFS_ERRMISC;
	}

	/* Now follow the cluster chain to free the file space */
	while (!((volinfo->filesystem == FAT12 && fi->firstcluster >= 0x0ff7) ||
			(volinfo->filesystem == FAT16 && fi->firstcluster >= 0xfff7) ||
			(volinfo->filesystem == FAT32 && fi->firstcluster >= 0x0ffffff7))) {
		tempclus = fi->firstcluster;
		//assert(nas->fs->bdev == fsi->bdev);
		fi->firstcluster = fat_get_fat_(fsi, p_scratch,
				&cache, fi->firstcluster);
		//assert(nas->fs->bdev == fsi->bdev);
		fat_set_fat_(fsi, p_scratch, &cache, tempclus, 0);
	}
	return DFS_OK;
}

/*
 * Create a file or directory. You supply a file_create_param_t
 * structure.
 * Returns various DFS_* error states. If the result is DFS_OK, file
 * was created and can be used.
 */
int fat_create_file(struct fat_file_info *fi, struct dirinfo *di, char *name, int mode) {
	uint8_t filename[12];
	struct dirent de;
	struct volinfo *volinfo;
	uint32_t cluster, temp;
	struct fat_fs_info *fsi;

	assert(fi);
	assert(di);
	assert(name);

	fsi = fi->fsi;
	volinfo = &fsi->vi;
	fi->volinfo = volinfo;

	fat_get_filename(name, (char *) filename);

	while (!fat_get_next(fsi, di, &de));

	/* Locate or create a directory entry for this file */
	if (DFS_OK != fat_get_free_dir_ent(fsi, (uint8_t *) name, di, &de)) {
		return DFS_ERRMISC;
	}

	cluster = fat_get_free_fat_(fsi, fat_sector_buff);
	de = (struct dirent) {
		.attr = S_ISDIR(mode) ? ATTR_DIRECTORY : 0,
		.startclus_l_l = cluster & 0xff,
		.startclus_l_h = (cluster & 0xff00) >> 8,
		.startclus_h_l = (cluster & 0xff0000) >> 16,
		.startclus_h_h = (cluster & 0xff000000) >> 24,
	};
	memcpy(de.name, filename, MSDOS_NAME);
	fat_set_filetime(&de);

	fi->volinfo = volinfo;
	fi->pointer = 0;
	/*
	 * The reason we store this extra info about the file is so that we can
	 * speedily update the file size, modification date, etc. on a file
	 * that is opened for writing.
	 */

	//fi->dirsector = volinfo->dataarea + (di->fi.cluster - 2) * volinfo->secperclus;
	/* 'di' have to be filled already */
	fi->dirsector = di->currentsector + di->currentcluster * volinfo->secperclus;
	fi->diroffset = di->currententry - 1;
	fi->cluster = cluster;
	fi->firstcluster = cluster;

	/*
	 * write the directory entry
	 * note that we no longer have the sector containing the directory
	 * entry, tragically, so we have to re-read it
	 */

	if (fat_read_sector(fsi, fat_sector_buff, fi->dirsector)) {
		return DFS_ERRMISC;
	}
	memcpy(&(((struct dirent*) fat_sector_buff)[fi->diroffset]),
			&de, sizeof(struct dirent));
	if (fat_write_sector(fsi, fat_sector_buff, fi->dirsector)) {
		return DFS_ERRMISC;
	}
	/* Mark newly allocated cluster as end of chain */
	switch(volinfo->filesystem) {
		case FAT12:		cluster = 0xfff;	break;
		case FAT16:		cluster = 0xffff;	break;
		case FAT32:		cluster = 0x0fffffff;	break;
		default:		return DFS_ERRMISC;
	}

	temp = 0;
	fat_set_fat_(fsi,
			fat_sector_buff, &temp, fi->cluster, cluster);

	if (S_ISDIR(mode)) {
		/* create . and ..  files of this catalog */
		fat_set_direntry(di->currentcluster, fi->cluster);
		cluster = fi->volinfo->dataarea +
				  ((fi->cluster - 2) * fi->volinfo->secperclus);
		if (fat_write_sector(fsi, fat_sector_buff, cluster)) {
			return DFS_ERRMISC;
		}
	}

	return DFS_OK;
}

#include <framework/mod/options.h>

POOL_DEF(fat_fs_pool,
         struct fat_fs_info,
	 OPTION_GET(NUMBER, fat_descriptor_quantity));

POOL_DEF(fat_file_pool,
         struct fat_file_info,
         OPTION_GET(NUMBER, inode_quantity));

POOL_DEF(fat_dirinfo_pool,
         struct dirinfo,
         OPTION_GET(NUMBER, inode_quantity));

POOL_DEF(fat_dirent_pool,
         struct dirent,
         OPTION_GET(NUMBER, inode_quantity));

struct fat_fs_info *fat_fs_alloc(void) {
	return pool_alloc(&fat_fs_pool);
}

void fat_fs_free(struct fat_fs_info *fsi) {
	pool_free(&fat_fs_pool, fsi);
}

struct fat_file_info *fat_file_alloc(void) {
	return pool_alloc(&fat_file_pool);
}

void fat_file_free(struct fat_file_info *fi) {
	pool_free(&fat_file_pool, fi);
}

struct dirinfo *fat_dirinfo_alloc(void) {
	return pool_alloc(&fat_dirinfo_pool);
}

void fat_dirinfo_free(struct dirinfo *di) {
	pool_free(&fat_dirinfo_pool, di);
}


text:
using J2N.Text;
using Lucene.Net.Benchmarks.ByTask.Feeds;
using Lucene.Net.Search;
using System;

namespace Lucene.Net.Benchmarks.ByTask.Tasks
{

    /// <summary>
    /// Does sort search on specified field.
    /// </summary>
    public class SearchWithSortTask : ReadTask
    {
        private bool doScore = true;
        private bool doMaxScore = true;
        private Sort sort;

        public SearchWithSortTask(PerfRunData runData)
            : base(runData)
        {
        }

        /// <summary>
        /// SortFields: field:type,field:type[,noscore][,nomaxscore]
        /// <para/>
        /// If noscore is present, then we turn off score tracking
        /// in <see cref="TopFieldCollector"/>.
        /// If nomaxscore is present, then we turn off maxScore tracking
        /// in <see cref="TopFieldCollector"/>.
        /// <para/>
        /// name:string,page:int,subject:string
        /// </summary>
        public override void SetParams(string sortField)
        {
            base.SetParams(sortField);
            string[] fields = sortField.Split(',').TrimEnd();
            SortField[] sortFields = new SortField[fields.Length];
            int upto = 0;
            for (int i = 0; i < fields.Length; i++)
            {
                string field = fields[i];
                SortField sortField0;
                if (field.Equals("doc", StringComparison.Ordinal))
                {
                    sortField0 = SortField.FIELD_DOC;
                }
                else if (field.Equals("score", StringComparison.Ordinal))
                {
                    sortField0 = SortField.FIELD_SCORE;
                }
                else if (field.Equals("noscore", StringComparison.Ordinal))
                {
                    doScore = false;
                    continue;
                }
                else if (field.Equals("nomaxscore", StringComparison.Ordinal))
                {
                    doMaxScore = false;
                    continue;
                }
                else
                {
                    int index = field.LastIndexOf(':');
                    string fieldName;
                    string typeString;
                    if (index != -1)
                    {
                        fieldName = field.Substring(0, index - 0);
                        typeString = field.Substring(1 + index, field.Length - (1 + index));
                    }
                    else
                    {
                        throw RuntimeException.Create("You must specify the sort type ie page:int,subject:string");
                    }
                    sortField0 = new SortField(fieldName, (SortFieldType)Enum.Parse(typeof(SortFieldType), typeString, true));
                }
                sortFields[upto++] = sortField0;
            }

            if (upto < sortFields.Length)
            {
                SortField[] newSortFields = new SortField[upto];
                System.Array.Copy(sortFields, 0, newSortFields, 0, upto);
                sortFields = newSortFields;
            }
            this.sort = new Sort(sortFields);
        }

        public override bool SupportsParams => true;

        public override IQueryMaker GetQueryMaker()
        {
            return RunData.GetQueryMaker(this);
        }

        public override bool WithRetrieve => false;

        public override bool WithSearch => true;

        public override bool WithTraverse => false;

        public override bool WithWarm => false;

        public override bool WithScore => doScore;

        public override bool WithMaxScore => doMaxScore;

        public override Sort Sort
        {
            get
            {
                if (sort is null)
                {
                    throw IllegalStateException.Create("No sort field was set");
                }
                return sort;
            }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
        I have no idea how to start solving this mission

        You can replace the substrings with the
        "replace()" method.

"abcd ababba".replace("ab", "0") == "0cd 00ba"

        I need some help to proceed with the mission

        And you can join strings with the "join" method.

":".join(["A", "1", "cd"]) == "A:1:cd"

        I am gone half way through. Need help!

        Join all the given strings, then replace "right" with "left" and return (do not print) the result.

def left_join(phrases: tuple) -> str:
    join_phrase = ','.join(phrases)
    result = join_phrase.replace('right','left')
    return result


text:
package org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.ddl;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterViewStatement;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.MySQLStatement;

import java.util.Optional;

/**
 * MySQL alter view statement.
 */
@Getter
@Setter
@ToString
public final class MySQLAlterViewStatement extends AlterViewStatement implements MySQLStatement {

    private SelectStatement select;

    /**
     * Get select statement.
     *
     * @return select statement
     */
    public Optional<SelectStatement> getSelect() {
        return Optional.ofNullable(select);
    }
}


text:
all analysts

                            name
                            username
                            available modules
                            analyst type
                            options

                        {{ analyst.getName() }}

                                {{ analyst.email }}

                            {{ analyst.username }}

                            {{ app }}

                            {{ analyst.getType() }}

                            change password


text:
#ifndef TENSORFLOW_LITE_DELEGATES_GPU_METAL_KERNELS_TRANSPOSE_CONV_H_
#define TENSORFLOW_LITE_DELEGATES_GPU_METAL_KERNELS_TRANSPOSE_CONV_H_

#include <vector>

#include "tensorflow/lite/delegates/gpu/common/model.h"
#include "tensorflow/lite/delegates/gpu/common/operations.h"
#include "tensorflow/lite/delegates/gpu/metal/compute_task_descriptor.h"
#include "tensorflow/lite/delegates/gpu/metal/environment.h"
#include "tensorflow/lite/delegates/gpu/metal/runtime_options.h"

namespace tflite {
namespace gpu {
namespace metal {

std::vector<ComputeTaskDescriptorPtr> ConvolutionTransposed(
    int id, ValueId input_id, ValueId output_id,
    const ConvolutionTransposedAttributes& params,
    const DeviceInfo& device_info, const RuntimeOptions& options);

std::vector<ComputeTaskDescriptorPtr> ConvolutionTransposed4x4(
    int id, ValueId input_id, ValueId output_id,
    const ConvolutionTransposedAttributes& params,
    const DeviceInfo& device_info, const RuntimeOptions& options);

bool CheckConvolutionTransposed4x4Support(
    const ConvolutionTransposedAttributes& attr);

}  // namespace metal
}  // namespace gpu
}  // namespace tflite

#endif  // TENSORFLOW_LITE_DELEGATES_GPU_METAL_KERNELS_TRANSPOSE_CONV_H_


text:
module.exports = function(grunt){

	grunt.loadNpmTasks("grunt-contrib-uglify");
	grunt.loadNpmTasks("grunt-contrib-concat");

	var banner = grunt.file.read("src/banner.js");

	grunt.initConfig({
		concat : {
			options : {
				stripBanners : true,
				banner : banner
			},
			dist : {
				src : [
					"src/fullslider.js"
				],
				dest : "assets/js/fullslider/fullslider.js"
			}
		},
		uglify : {
			options : {
				stripBanners : true,
				banner : banner
			},
			dist : {
				src : [
					"src/fullslider.js"
				],
				dest : "assets/js/fullslider/fullslider.min.js"
			}
		}
	});

	grunt.registerTask("default", ["concat:dist", "uglify:dist"]);

};


text:
using PoppertechCalculator.Models;
using PoppertechCalculator.Processors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using System.Web.Http.ModelBinding;

namespace PoppertechCalculator.Controllers
{
    [RoutePrefix("investment")]
    public class InvestmentSimulationController : ApiController
    {
        ISimulationProcessor _processor;
        public InvestmentSimulationController(ISimulationProcessor processor)
        {
            _processor = processor;
        }

        [HttpPost]
        [Route("")]
        [ResponseType(typeof(Response<IEnumerable<SimulationResults>>))]
        public IHttpActionResult Post([FromBody] IEnumerable<ForecastVariable> request)
        {
            var simulationsResults = _processor.SimulateInvestments(request);
            var response = new Response<IEnumerable<SimulationResults>> { Model = simulationsResults };
            return Ok(response);

        }

    }
}


text:
//
//  GBOutputGenerator.h
//  appledoc
//
//  Created by Tomaz Kragelj on 28.11.10.
//  Copyright 2010 Gentle Bytes. All rights reserved.
//

#import "GBTemplateFilesHandler.h"

@class GBStore;
@class GBApplicationSettingsProvider;

/** The base class for all output generators.

 Output generator is an object that handles a specific spet while generating output. These are helper classes for `GBGenerator` class; each concrete subclass handles specifics for certain step. Generator just ties all of these together into properly ordered chain as required by command line parameters.

 @warning *Implementation detail:* As this is a subclass of `GBTemplateFilesHandler`, it automatically inherits all template files processing functionality from it. However it overrides `templateUserPath` and `outputUserPath` to use values from `GBApplicationSettingsProvider`. This greatly simplifies output generators handling - instead of requiring clients to setup proper paths, subclasses only need to override `outputSubpath` and return subdirectory which is used for both: actual template files and output files location; in both cases, the subpath is appended to the locations from the settings.
 */
@interface GBOutputGenerator : GBTemplateFilesHandler

///---------------------------------------------------------------------------------------
/// @name Initialization & disposal
///---------------------------------------------------------------------------------------

/** Returns autoreleased generator that work with the given `GBApplicationSettingsProvider` implementor.

 @param settingsProvider Application-wide settings provider to use for checking parameters.
 @return Returns initialized instance or `nil` if initialization fails.
 @exception NSException Thrown if the given application is `nil`.
 */
+ (id)generatorWithSettingsProvider:(id)settingsProvider;

/** Initializes the generator to work with the given `GBApplicationSettingsProvider` implementor.

 This is the designated initializer.

 @param settingsProvider Application-wide settings provider to use for checking parameters.
 @return Returns initialized instance or `nil` if initialization fails.
 @exception NSException Thrown if the given application is `nil`.
 */
- (id)initWithSettingsProvider:(id)settingsProvider;

///---------------------------------------------------------------------------------------
/// @name Generation handling
///---------------------------------------------------------------------------------------

/** Initializes the directory at the given path.

 If the directory alreay exists, it is removed. Then a new one is created with all intermediate directories as needed. The result of the method is an empty directory at the given path. Sending this message has the same effect as sending `initializeDirectoryAtPath:preserve:error:` and passing `nil` for preserve argument.

 @param path The path to initialize.
 @param error If initialization fails, error is returned here.
 @return Returns `YES` if initialization succeeds, `NO` otherwise.
 @see initializeDirectoryAtPath:preserve:error:
 */
- (BOOL)initializeDirectoryAtPath:(NSString *)path error:(NSError **)error;

/** Initializes the directory at the given path optionally preserving any number of files or subdirectories.

 If the directory doesn't exist, it is created. Otherwise all files and subdirectories are removed, except for the given array of files or subdirectories to preserve. If the array is `nil` or empty, all files are removed. Preserve array should contain paths relative to the given path. The paths are not handled recursively - only first level items are preserved!

 The result of the method is an empty directory at the given path containing only files or subdirectories from the given array.

 @param path The path to initialize.
 @param preserve An array of paths to preserve.
 @param error If initialization fails, error is returned here.
 @return Returns `YES` if initialization succeeds, `NO` otherwise.
 @see initializeDirectoryAtPath:error:
 */
- (BOOL)initializeDirectoryAtPath:(NSString *)path preserve:(NSArray *)preserve error:(NSError **)error;

/** Copies or moves directory or file from the given source path to the destination path.

 This method takes into account `[GBApplicationSettingsProvider keepIntermediateFiles]` and either copies or moves files regarding it's value. The method is designed to be used from within subclasses.

 @param source Source path to copy or move from.
 @param destination Destination path to copy or move to.
 @param error If copying fails, error description is returned here.
 @return Returns `YES` if all files were succesfully copied, `NO` otherwise.
 */
- (BOOL)copyOrMoveItemFromPath:(NSString *)source toPath:(NSString *)destination error:(NSError **)error;

/** Generates the output at the proper subdirectory of the output path as defined in assigned `settings`.

 This is the most important method of the `GBOutputGenerator` class. It generates all required output. It is intended to be overriden in subclasses. Default implementation assigns the given store and returns YES. Subclasses must call super class implementation before anything else!

 @param store The `GBStore` object that holds the store with all parsed and processed data.
 @param error If generation fails, error description is returned here.
 @see writeString:toFile:error:
 @see store
 */
- (BOOL)generateOutputWithStore:(id)store error:(NSError **)error;

/** Writes the given string to the given path, creating all necessary directories if they don't exist.

 This method is intended to be used from subclass, in most cases from `generateOutputWithStore:error:`.

 @param string The string to write.
 @param path The path and filename to write to.
 @param error If writing fails, error description is returned here.
 @return Returns `YES` is writing succeds, `NO` otherwise.
 @see generateOutputWithStore:error:
 */
- (BOOL)writeString:(NSString *)string toFile:(NSString *)path error:(NSError **)error;

///---------------------------------------------------------------------------------------
/// @name Subclass parameters and helpers
///---------------------------------------------------------------------------------------

/** Returns user-friendly input path string.

 This is simply a shortcut for output path of previous generator. Internally it works by sending the `outputUserPath` message to `previousGenerator and returning the result. If previous generator is `nil` (i.e. this is the first generator), `nil` is returned. Send `stringByStandardizingPath` message to the returned value before using it!

 @see templateUserPath
 @see outputUserPath
 */
@property (readonly) NSString *inputUserPath;

/** Returns the `GBOutputGenerator` that was used just before this one or `nil` if this is the first generator in this session.

 This is useful for subclasses that rely on files generated by previous generator. For example, we can get the location of generated files so we can further manipulate them. If a concrete subclass requires previous generator, and none is provided, it should throw an exception from `generateOutputWithStore:error:`!
 */
@property (strong) GBOutputGenerator *previousGenerator;

/** The store as assigned to `generateOutput`.

 @see generateOutputWithStore:error:
 */
@property (readonly, strong) GBStore *store;

///---------------------------------------------------------------------------------------
/// @name Generation parameters
///---------------------------------------------------------------------------------------

/** Returns the path relative to main output path, where all generated data is stored.

 At the same this, this also defines the path relative to main templates path, where all template files for this output generator are stored. Default implementation simply returns empty string, each subclass is supposed to override and return prover value.
  */
@property (readonly) NSString *outputSubpath;

/** The `GBApplicationSettingsProvider` object that provides application-wide settings for this session.
 */
@property (strong) GBApplicationSettingsProvider *settings;

@end


text:
SYNONYM

#### According to
Index Fungorum

#### Published in
null

#### Original name
Hygrocybe calyptriformis (Berk.) Fayod, 1889

### Remarks
null


text:
UPGRADE
=======

# From 0.15.0 to 0.16.x

## Codebase upgrade:

 * Change your configuration for bundles all resources are configured under ``sylius_<bundle> -> resources -> <resource>`` node
 * Rename validation groups parameter names if you used them anywhere

## PayumBundle

 * Changed configuration key `sylius_payum.classes.payment_config` to `sylius_payum.classes.gateway_config`

## Resource

 * RepositoryInterface now has two additional methods `add` and `remove`

# From 0.14.0 to 0.15.x

## Multi Channel support

https://github.com/Sylius/Sylius/pull/2752

## UserBundle

https://github.com/Sylius/Sylius/pull/2717

#### Database upgrade:
 * Call ``` sylius:rbac:initialize ``` to create new roles in your system
 * Execute migration script to migrate your data into the new model schema<br/>

**The migration script migrates only default data, if you have some customizations on any of affected entities you should take care of them yourself!**

#### Codebase upgrade:

 * We no longer use FOSUserBundle
 * User provider has been changed https://github.com/Sylius/Sylius/pull/2717/files#diff-da1af97fca8a5fcb6fb7053584105ba7R6
 * Everything related to e-commerce (orders, addresses, groups and coupons) are now associated with Customer
 * Everything related to system account remains on User entity
 * Email no longer exist on Order
 * All order are associated with Customer (even guest orders - during guest checkout Customer is created based on email)
 * User must have associated Customer
 * Email no longer exist on User. It is on Customer now
 * In the checkout we depend on Customer not User
 * In templates in many places we use Customer instead of User entity now

## API client

https://github.com/Sylius/Sylius/pull/2887

#### Codebase upgrade:

When you create server client in Sylius, it's public id was a combination of Client internal id and it's random id. E.g.
```
client_id: 1_mpO5ZJ35hx
```
now it is simply random id, so it will be changed to:
```
client_id: mpO5ZJ35hx
```

**Remember to update your API clients using Sylius!**

Related discussion https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/issues/328.

## Translating country names using Symfony's Intl component

[Removed `CountryTranslation`, using `Intl` Symfony component instead to provide translated country names based on ISO country code.](https://github.com/Sylius/Sylius/pull/3035)

#### Database upgrade

 * Execute migration script to migrate your data into the new model schema

# From 0.9.0 to 0.10.x

Version 0.10.x includes the new Sylius e-commerce components.
All classes without Symfony dependency have been moved to separate ``Sylius\Component`` namespace.

VariableProductBundle has been merged into ProductBundle.
Its functionality extracted into two separate bundles - SyliusAttributeBundle & SyliusVariationBundle.

Property model has been renamed to Attribute.

Before performing this procedure, please create a safe backup of your database.
This upgrade changes significantly the way product attributes and options are stored in the database.
We do provide a way to migrate your data, but no rollback will be possible in case of a problem.

In addition to the components split, we have switched to state-machine in order to deal with states, instead of
hard-coded states. You can now configure all the states you want and the transitions between them. Please refer to
`state-machine.yml` that you can find in the bundles using it. *Most events have been replaced by state-machine events,
much more powerful. Please update your listeners to make them callbacks of state-machine transitions. Again, please
refer to the state-machine configuration files to do so.*

The signature of `PaymentInterface::setDetails` method was changed. Now it allows either array or instance of \Traversable.

### Addressing

Model classes and ZoneMatcher services have been moved to ``Sylius\Component\Addressing`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\AddressingBundle\\Model/Sylius\\Component\\Addressing\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\AddressingBundle\\ZoneMatcher/Sylius\\Component\\Addressing\\ZoneMatcher/g' {} \;
```

### Cart

Model classes and several services have been moved to ``Sylius\Component\Cart`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CartBundle\\Model/Sylius\\Component\\Cart\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CartBundle\\Provider\\CartProviderInterface/Sylius\\Component\\Cart\\Provider\\CartProviderInterface/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CartBundle\\Storage\\CartStorageInterface/Sylius\\Component\\Cart\\Storage\\CartStorageInterface/g' {} \;
```

Twig extension class name & service were changed:

* `SyliusCartExtension` into `CartExtension`,
* `sylius.cart_twig` into `sylius.twig.extension.cart`

### Core

All Symfony independent code has been moved to ``Sylius\Component\Core`` namespace.
Variant model has been renamed to ProductVariant and VariantImage to ProductVariantImage.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\Model\\Variant/Sylius\\Component\\Core\\Model\\ProductVariant/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\Model/Sylius\\Component\\Core\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\Calculator/Sylius\\Component\\Core\\Calculator/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\OrderProcessing/Sylius\\Component\\Core\\OrderProcessing/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\Promotion/Sylius\\Component\\Core\\Promotion/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\CoreBundle\\Uploader/Sylius\\Component\\Core\\Uploader/g' {} \;
```

Twig extension class name & service were changed:

* `SyliusMoneyExtension` into `SyliusMoneyExtension`,
* `SyliusRestrictedZoneExtension` into `RestrictedZoneExtension`,
* `sylius.twig.restricted_zone_extension` into `sylius.twig.extension.restricted_zone`

### Inventory

Model classes and all Symfony-agnostic services have been moved to ``Sylius\Component\Inventory`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\InventoryBundle\\Model/Sylius\\Component\\Inventory\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\InventoryBundle\\Checker/Sylius\\Component\\Inventory\\Checker/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\InventoryBundle\\Factory/Sylius\\Component\\Inventory\\Factory/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\InventoryBundle\\Operator/Sylius\\Component\\Inventory\\Operator/g' {} \;
```

Twig extension class name & service were changed:

* `SyliusInventoryExtension` into `InventoryExtension`,
* `sylius.inventory_twig` into `sylius.twig.extension.inventory`

### Money

Model classes and interfaces have been moved to ``Sylius\Component\Money`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\MoneyBundle\\Model/Sylius\\Component\\Money\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\MoneyBundle\\Converter/Sylius\\Component\\Money\\Converter/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\MoneyBundle\\Context\\CurrencyContextInterface/Sylius\\Component\\Money\\Context\\CurrencyContextInterface/g' {} \;
```

Twig extension class name & service were changed:

* `SyliusMoneyExtension` into `MoneyExtension`,
* `sylius.twig.money` into `sylius.twig.extension.money`

### Order

Model classes and repository interfaces have been moved to ``Sylius\Component\Order`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\OrderBundle\\Model/Sylius\\Component\\Order\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\OrderBundle\\Generator/Sylius\\Component\\Order\\Generator/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\OrderBundle\\Repository/Sylius\\Component\\Order\\Repository/g' {} \;
```

### Payment

PaymentsBundle has been renamed to PaymentBundle.
Model classes interfaces have been moved to ``Sylius\Component\Order`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PaymentsBundle\\Model/Sylius\\Component\\Payment\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/PaymentsBundle/PaymentBundle/g' {} \;
```

Configuration root node has been adjusted as well.

Before:

```yaml
sylius_payments:
    driver: doctrine/orm
```

After:

```yaml
sylius_payment:
    driver: doctrine/orm
```

### Product

Previously, ProductBundle provided basic product model with properties support.
VariableProductBundle, with its options and variants support, has been merged into the basic bundle.
From now on, Sylius product catalog ships with variations support by default.

The concept of properties has been renamed to attributes.

* Property model becomes Attribute.
* ProductProperty becomes AttributeValue.

Attributes can be attached to any object and can be configured under ``sylius_attribute`` node.
The product bundle configures its attributes automatically.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\VariableProductBundle\\Model/Sylius\\Component\\Product\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.option/sylius.repository.product_option/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.option_value/sylius.repository.product_option_value/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.product_property/sylius.repository.product_attribute_value/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.property/sylius.repository.product_attribute/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.prototype/sylius.repository.product_prototype/g' {} \;
$ find ./src -type f -exec sed -i 's/sylius.repository.variant/sylius.repository.product_variant/g' {} \;
```

Beware, the Doctrine relationship name has changed as well between `Variant` (now, `ProductVariant`) and `Product`. If you use it in custom repository methods, you need to adapt accordingly:

Before:

```yaml
variant.product
```

After:

```yaml
product_variant.object
```

### Promotion

PromotionsBundle has been renamed to PromotionBundle.
Model classes interfaces have been moved to ``Sylius\Component\Promotion`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/PromotionsBundle/PromotionBundle/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PromotionBundle\\Model/Sylius\\Component\\Promotion\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PromotionBundle\\Action/Sylius\\Component\\Promotion\\Action/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PromotionBundle\\Checker/Sylius\\Component\\Promotion\\Checker/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PromotionBundle\\Generator/Sylius\\Component\\Promotion\\Generator/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\PromotionBundle\\Processor/Sylius\\Component\\Promotion\\Processor/g' {} \;
```

Configuration root node has been adjusted as well.

Before:

```yaml
sylius_promotions:
    driver: doctrine/orm
```

After:

```yaml
sylius_promotion:
    driver: doctrine/orm
```

### Resource

ResourceBundle model interfaces have been moved to ``Sylius\Component\Resource`` namespace.
``RepositoryInterface`` has been moved to ``Repository`` namespace under the component.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ResourceBundle\\Model/Sylius\\Component\\Resource\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Component\\Resource\\Model\\RepositoryInterface/Sylius\\Component\\Resource\\Repository\\RepositoryInterface/g' {} \;
```

Twig extension class name & service were changed:

* `SyliusResourceExtension` into `SyliusResourceExtension`,
* `sylius.twig.resource` into `sylius.twig.extension.resource`

### Settings

Twig extension class name & service were changed:

* `SyliusSettingsExtension` into `SettingsExtension`,
* `sylius.settings.twig` into `sylius.twig.extension.settings`

### Shipping

Model classes and Symfony agnostic services & interfaces have been moved to ``Sylius\Component\Shipping`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ShippingBundle\\Model/Sylius\\Component\\Shipping\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ShippingBundle\\Calculator/Sylius\\Component\\Shipping\\Calculator/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ShippingBundle\\Checker/Sylius\\Component\\Shipping\\Checker/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ShippingBundle\\Resolver/Sylius\\Component\\Shipping\\Resolver/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\ShippingBundle\\Processor/Sylius\\Component\\Shipping\\Processor/g' {} \;
```

### Taxation

Model classes and Symfony agnostic services have been moved to ``Sylius\Component\Taxation`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\TaxationBundle\\Model/Sylius\\Component\\Taxation\\Model/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\TaxationBundle\\Calculator/Sylius\\Component\\Taxation\\Calculator/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\TaxationBundle\\Resolver/Sylius\\Component\\Taxation\\Resolver/g' {} \;
```

### Taxonomy

TaxonomiesBundle has been renamed to TaxonomyBundle.
Model classes interfaces have been moved to ``Sylius\Component\Taxonomy`` namespace.

```bash
$ find ./src -type f -exec sed -i 's/TaxonomiesBundle/TaxonomyBundle/g' {} \;
$ find ./src -type f -exec sed -i 's/Sylius\\Bundle\\TaxonomyBundle\\Model/Sylius\\Component\\Taxonomy\\Model/g' {} \;
```

Configuration root node has been adjusted as well.

Before:

```yaml
sylius_taxonomies:
    driver: doctrine/orm
```

After:

```yaml
sylius_taxonomy:
    driver: doctrine/orm
```

### Web

Twig extension service name was changed:

* `sylius.twig.text_extension` into `sylius.twig.extension.text`


text:
<?php

namespace Archibald;

use Archibald\Request;

class Api
{
	private $slashToken = SLASHCOMMAND_TOKEN;
	private $commandName = '/archie';

	public function __construct($request)
	{
		if ($request['token'] && $request['command']) {
			$token      = $request['token'];
			$command    = $request['command'];

			if ($this->isValidToken($token) && $this->isValidCommand($command)) {

				$data = array(
					'team_id'   => $request['team_id'],
					'channel'   => $request['channel_id'],
					'user_id'   => $request['user_id'],
					'user'      => $request['user_name'],
					'body'      => $request['text']
				);

				$request = new Request($data);
			}
			else {
				echo 'Invalid Token or Command';
			}
		}
		else {
			echo 'No valid API call.';
		}
	}

	private function isValidToken($token)
	{
		return $token == $this->slashToken;
	}

	private function isValidCommand($command)
	{
		return $command == $this->commandName;
	}
}


text:
<?php
/**
 * Created by JetBrains PhpStorm.
 * User: Yura Rodchyn (rodchyn) rodchyn@gmail.com
 * Date: 7/15/13
 * Time: 8:47 PM
 * To change this template use File | Settings | File Templates.
 */

namespace Rodchyn\ElephantLang;

class Init {
    public static function init()
    {

    }
}

namespace Rodchyn\ElephantLang\Parser;

function yy($type) {
    $args = func_get_args();
    array_shift($args);

    $type = __NAMESPACE__.'\yy\\'.$type;

    $inst = new $type;
    $inst = call_user_func_array(array($inst, 'constructor'), $args);

    return $inst;
}


text:
import play.api.libs.json._

package object models {
  implicit val formatTeam = Json.format[Team]
}


text:
<?php

namespace AppBundle\Model;

use Symfony\Component\Translation\TranslatorInterface;

interface HasTranslatorInterface
{
    /**
     * @param TranslatorInterface $translator
     */
    public function setTranslator(TranslatorInterface $translator);

    /**
     * @return TranslatorInterface
     */
    public function getTranslator(): ?TranslatorInterface;
}


text:
paper-date-picker-item [![Bower version](https://badge.fury.io/bo/paper-date-picker-item.svg)](http://badge.fury.io/bo/paper-date-picker-item) [![Travis state](https://travis-ci.org/Collaborne/paper-date-picker-item.svg?branch=master)](https://travis-ci.org/Collaborne/paper-date-picker-item) [![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/Collaborne/paper-date-picker-item)
=========

`paper-date-picker-item` provides a Material Design item that shows a date and opens a date picker dialog on tap. The web component is built with [Polymer 1.x](https://www.polymer-project.org).

This component builds on the components [paper-date-picker](https://github.com/bendavis78/paper-date-picker) and [paper-time-picker](https://github.com/bendavis78/paper-time-picker)  by [Ben Davis](https://github.com/bendavis78).

To use the elements:

`bower install paper-date-picker-item`

<!--
```
<custom-element-demo>
  <template>
    <script src="../webcomponentsjs/webcomponents-lite.js"></script>
    <link rel="import" href="../iron-icons/iron-icons.html">
    <link rel="import" href="paper-datetime-picker-item.html">
    <custom-style>
      <style is="custom-style">
        body {
          min-height: 600px;
        }
      </style>
    <custom-style>
    <next-code-block></next-code-block>
  </template>
</custom-element-demo>
```
-->
```html
<paper-datetime-picker-item
    icon="icons:today"
    placeholder="Add date and time"
    date-format="Do, MMMM, YYYY">
</paper-datetime-picker-item>
```

## i18n Support

`paper-date-picker-item` uses [Moment.js](http://momentjs.com), and so supports all locales that Moment.js supports. But,
the component does not reference any specific locale, so when you want to use it with a locale other than `en` you must
load the locales explicitly.

~~~~
<link rel="import" href="bower_components/paper-date-picker-item/paper-date-picker-item.html">
<script src="bower_components/moment/min/locales.js"></script>
~~~~

The `paper-date-picker-item` components all provide a `locale` property to set the locale used by the component.

## License

    This software is licensed under the Apache 2 license, quoted below.

    Copyright 2011-2017 Collaborne B.V. <http://github.com/Collaborne/>

    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.


text:
<?php

namespace ActivismeBe\Console\Utils;

class ArrayUtil
{
    public static function get(array $array, $key)
    {
        return (array_key_exists($key, $array)) ? $array[$key] : null;
    }

    public static function filter(array $array)
    {
        if (isset($array['.'])) {
            unset($array['.']);
        }

        if (isset($array['..'])) {
            unset($array['..']);
        }

        unset($array[0]);
        unset($array[1]);

        return $array;
    }
}


text:
<mainfest>
	<package>de.pubflow.services.eprints</package>
	<description>
	</description>
	<signatures>
		<signature name="de.pubflow.services.eprints.checkRSSFeeds">
			<description></description>
		</signature>
	</signatures>
</mainfest>


text:
<?php // Script 8.4 - index.php
/* This is the home page for this site.
It uses templates to create the layout. */

// Include the header:
include('templates/header.html');
// Leave the PHP section to display lots of HTML:
?>

Welcome to a J.D. Salinger Fan Club!

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

Another Header

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

<?php // Return to PHP.
include('templates/footer.html'); // Include the footer.
?>


text:
next_url:   contributing.html
next_title: Contributing
prev_title: Pagination
prev_url:   pagination.html

## metacrawler.authentication.Authentication(self, url, xpath=None, **data) ##

### Initialization arguments ###
- `url`: `str`
Authentication page URL.

- `xpath` *(optional)*: `str`
XPath for extact form. By default extract first `form` tag.

- `**data`: `keywords arguments`
Form data. For example, `username=username, password=password`. See form `input`s `name` attributes.

### Public attributes ###
- `url`: `str`
Authentication page URL.

- `xpath` *(optional)*: `str`
XPath for extact form. By default extract first `form` tag.

- `data`: `dict`
Passed form data.

### Public methods ###
- `get_form(self, page)`
Return form element.
  - `page`: `lxml.Element`
  `lxml` reperesentation of authentication page.

- `get_login_url(self, form)`
Return login url from form.
  - `form`: `lxml.Element`
  `lxml` reperesentation of form.

- `get_form_data(self, form)`
Return data for submit.
  - `form`: `lxml.Element`
  `lxml` reperesentation of form.

- `authentication(self, session=None)`
Return session after submit form (with cookies).
  - `session`: `requests.Session`
  Using for authentication and save cookies.


text:
package net.liujiacai.jcscheme.keyword;

import net.liujiacai.jcscheme.JCEnvironment;
import net.liujiacai.jcscheme.JCExpression;
import net.liujiacai.jcscheme.exception.IllegalExpressionException;
import net.liujiacai.jcscheme.type.JCFunction;
import net.liujiacai.jcscheme.type.JCObject;
import net.liujiacai.jcscheme.util.JCConstants;

import java.util.ArrayList;
import java.util.List;

public class Lambda {
    public static boolean isLambda(JCExpression exp) {
        List<JCExpression> children = exp.getChildren();
        if (children.size() > 0) {
            if (children.get(0).getValue().equals(JCConstants.LAMBDA)) {
                if (children.size() >= 4) {
                    return true;
                } else {
                    try {
                        throw new IllegalExpressionException("illegal LAMBDA exp. (lambda (param) (action1)" +
                                " (action2) ... )");
                    } catch (IllegalExpressionException e) {
                        e.printStackTrace();
                        System.exit(1);
                    }
                }

            }
        }
        return false;
    }

    public static JCExpression getParamExp(JCExpression exp) {
        List<JCExpression> children = exp.getChildren();
        return children.get(1);
    }

    public static List<JCExpression> getBodyExps(JCExpression exp) {
        List<JCExpression> children = exp.getChildren();
        return children.subList(2, children.size() - 1);
    }

    public static List<String> getParamList(JCExpression paramExp) {
        List<JCExpression> children = paramExp.getChildren();
        List<JCExpression> paramExps = children.subList(0, children.size() - 1);

        List<String> params = new ArrayList<>();
        for (JCExpression param : paramExps) {
            params.add(param.getValue());
        }
        return params;

    }

    public static JCObject apply(JCExpression exp, JCEnvironment env) {

        JCFunction func = new JCFunction(getParamList(getParamExp(exp)), getBodyExps(exp), new JCEnvironment(
                env));
        return func;
    }
}


text:
package View;

import javax.swing.SwingUtilities;

import com.alee.laf.WebLookAndFeel;

/**
 *
 * @author SEVAK MARDIOSIAN
 * @version 0.3 Time Management system
 */
public class App {

	public static void main(String[] args) {

		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run()
			{
				WebLookAndFeel.install();
				new MainView();

			}

		}
		);
	}

}


text:
import React, { PureComponent } from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';

const styles = StyleSheet.create({
  tab: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 10,
  },
  tabs: {
    height: 45,
    flexDirection: 'row',
    paddingTop: 5,
    borderWidth: 1,
    borderTopWidth: 0,
    borderLeftWidth: 0,
    borderRightWidth: 0,
    borderBottomColor: 'rgba(0,0,0,0.05)',
  },
});

class TabNav extends PureComponent {

  tabIcons = []

  setAnimationValue = ({ value, }) => {
    this.tabIcons.forEach((icon, i) => {
      const progress = Math.min(1, Math.abs(value - i))
      icon.setNativeProps({
        style: {
          color: this.iconColor(progress),
        },
      });
    });
  }

  iconColor = (progress) => {
    const red = 59 + (204 - 59) * progress;
    const green = 89 + (204 - 89) * progress;
    const blue = 152 + (204 - 152) * progress;
    return `rgb(${red}, ${green}, ${blue})`;
  }

  render() {
    const { tabs } = this.props;
    return (
      <View style={[styles.tabs, this.props.style, ]}>
        {this.props.tabs.map((tab, i) => {
          return (
            <TouchableOpacity key={tab} onPress={() => this.props.goToPage(i)} style={styles.tab}>
              <Text>aa</Text>
            </TouchableOpacity>
          )
        })}
      </View>
    )
  }
}

export default TabNav;