text:
package hudson.util;

import com.gargoylesoftware.htmlunit.Page;
import hudson.cli.CLICommandInvoker;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.model.FreeStyleProject;
import hudson.model.Items;
import hudson.model.Job;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.Saveable;
import hudson.model.User;
import hudson.security.ACL;

import java.io.ByteArrayInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;

import jenkins.model.Jenkins;
import static org.junit.Assert.*;

import jenkins.security.apitoken.ApiTokenTestHelper;
import net.sf.json.JSONObject;

import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.TestExtension;
import org.jvnet.hudson.test.recipes.LocalData;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;

public class RobustReflectionConverterTest {

    @Rule public JenkinsRule r = new JenkinsRule();

    @Issue("JENKINS-21024")
    @LocalData
    @Test public void randomExceptionsReported() throws Exception {
        FreeStyleProject p = r.jenkins.getItemByFullName("j", FreeStyleProject.class);
        assertNotNull(p);
        assertTrue("There should be no triggers", p.getTriggers().isEmpty());
        OldDataMonitor odm = (OldDataMonitor) r.jenkins.getAdministrativeMonitor("OldData");
        Map<Saveable,OldDataMonitor.VersionRange> data = odm.getData();
        assertEquals(Collections.singleton(p), data.keySet());
        String text = data.values().iterator().next().extra;
        assertTrue(text, text.contains("Could not call hudson.triggers.TimerTrigger.readResolve"));
    }

    // Testing describable object to demonstrate what is expected with RobustReflectionConverter#addCriticalField
    // This should be configured with a specific keyword,
    // and should reject configurations with other keywords.
    // GUI related implementations (@DataBoundConstructor and newInstance) aren't used actually
    // (no jelly files are provides and they don't work actually),
    // but written to clarify a use case.
    public static class AcceptOnlySpecificKeyword extends AbstractDescribableImpl<AcceptOnlySpecificKeyword> {
        public static final String ACCEPT_KEYWORD = "accept";
        private final String keyword;

        @DataBoundConstructor
        public AcceptOnlySpecificKeyword(String keyword) {
            this.keyword = keyword;
        }

        public String getKeyword() {
            return keyword;
        }

        public boolean isAcceptable() {
            return ACCEPT_KEYWORD.equals(keyword);
        }

        private Object readResolve() throws Exception {
            if (!ACL.SYSTEM.equals(Jenkins.getAuthentication())) {
                // called via REST / CLI with authentication
                if (!isAcceptable()) {
                    // Reject invalid configuration via REST / CLI.
                    throw new Exception(String.format("Bad keyword: %s", getKeyword()));
                }
            }
            return this;
        }

        @TestExtension
        public static class DescriptorImpl extends Descriptor<AcceptOnlySpecificKeyword> {
            @Override
            public String getDisplayName() {
                return "AcceptOnlySpecificKeyword";
            }

            @Override
            public AcceptOnlySpecificKeyword newInstance(StaplerRequest req, JSONObject formData)
                    throws FormException {
                AcceptOnlySpecificKeyword instance = super.newInstance(req, formData);
                if (!instance.isAcceptable()) {
                    throw new FormException(String.format("Bad keyword: %s", instance.getKeyword()), "keyword");
                }
                return instance;
            }
        }
    }

    public static class KeywordProperty extends JobProperty<Job<?,?>> {
        private final AcceptOnlySpecificKeyword nonCriticalField;
        private final AcceptOnlySpecificKeyword criticalField;

        public KeywordProperty(AcceptOnlySpecificKeyword nonCriticalField, AcceptOnlySpecificKeyword criticalField) {
            this.nonCriticalField = nonCriticalField;
            this.criticalField = criticalField;
        }

        public AcceptOnlySpecificKeyword getNonCriticalField() {
            return nonCriticalField;
        }

        public AcceptOnlySpecificKeyword getCriticalField() {
            return criticalField;
        }

        @TestExtension
        public static class DescriptorImpl extends JobPropertyDescriptor {
            @Override
            public String getDisplayName() {
                return "KeywordProperty";
            }

            @Override
            public JobProperty<?> newInstance(StaplerRequest req, JSONObject formData)
                    throws FormException {
                // unfortunately, default newInstance bypasses newInstances for members.
                formData = formData.getJSONObject("keywordProperty");
                @SuppressWarnings("unchecked")
                Descriptor<AcceptOnlySpecificKeyword> d = Jenkins.get().getDescriptor(AcceptOnlySpecificKeyword.class);
                return new KeywordProperty(
                        d.newInstance(req, formData.getJSONObject("nonCriticalField")),
                        d.newInstance(req, formData.getJSONObject("criticalField"))
                );
            }
        }
    }

    private static final String CONFIGURATION_TEMPLATE =
            "<?xml version='1.1' encoding='UTF-8'?>"
            + "<project>"
            + "<properties>"
            +     "<hudson.util.RobustReflectionConverterTest_-KeywordProperty>"
            +         "<nonCriticalField>"
            +             "<keyword>%s</keyword>"
            +         "</nonCriticalField>"
            +         "<criticalField>"
            +             "<keyword>%s</keyword>"
            +         "</criticalField>"
            +     "</hudson.util.RobustReflectionConverterTest_-KeywordProperty>"
            + "</properties>"
            + "</project>";

    @Test
    public void testRestInterfaceFailure() throws Exception {
        ApiTokenTestHelper.enableLegacyBehavior();

        Items.XSTREAM2.addCriticalField(KeywordProperty.class, "criticalField");

        User test = User.getById("test", true);

        // without addCriticalField. This is accepted.
        {
            FreeStyleProject p = r.createFreeStyleProject();
            p.addProperty(new KeywordProperty(
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD),
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD)
            ));
            p.save();

            // Configure a bad keyword via REST.
            r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
            WebClient wc = r.createWebClient();
            wc.withBasicApiToken(test);
            WebRequest req = new WebRequest(new URL(wc.getContextPath() + String.format("%s/config.xml", p.getUrl())), HttpMethod.POST);
            req.setEncodingType(null);
            req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD));
            wc.getPage(req);

            // AcceptOnlySpecificKeyword with bad value is not instantiated for rejected with readResolve,
            assertNull(p.getProperty(KeywordProperty.class).getNonCriticalField());
            assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());

            // but save to the disk.
            r.jenkins.reload();

            p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
            assertEquals("badvalue", p.getProperty(KeywordProperty.class).getNonCriticalField().getKeyword());
            assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());
        }

        // with addCriticalField. This is not accepted.
        {
            FreeStyleProject p = r.createFreeStyleProject();
            p.addProperty(new KeywordProperty(
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD),
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD)
            ));
            p.save();

            // Configure a bad keyword via REST.
            r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
            WebClient wc = r.createWebClient()
                    .withThrowExceptionOnFailingStatusCode(false);
            wc.withBasicApiToken(test);
            WebRequest req = new WebRequest(new URL(wc.getContextPath() + String.format("%s/config.xml", p.getUrl())), HttpMethod.POST);
            req.setEncodingType(null);
            req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue"));

            Page page = wc.getPage(req);
            assertEquals("Submitting unacceptable configuration via REST should fail.",
                    HttpURLConnection.HTTP_INTERNAL_ERROR,
                    page.getWebResponse().getStatusCode());

            // Configuration should not be updated for a failure of the critical field,
            assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());

            r.jenkins.reload();

            // rejected configuration is not saved
            p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
            assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());
        }
    }

    @Test
    public void testCliFailure() throws Exception {
        Items.XSTREAM2.addCriticalField(KeywordProperty.class, "criticalField");

        // without addCriticalField. This is accepted.
        {
            FreeStyleProject p = r.createFreeStyleProject();
            p.addProperty(new KeywordProperty(
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD),
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD)
            ));
            p.save();

            // Configure a bad keyword via CLI.
            r.jenkins.setSecurityRealm(r.createDummySecurityRealm());

            CLICommandInvoker.Result ret = new CLICommandInvoker(r, "update-job")
                    .asUser("test")
                    .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, "badvalue", AcceptOnlySpecificKeyword.ACCEPT_KEYWORD).getBytes()))
                    .withArgs(
                            p.getFullName()
                    )
                    .invoke();

            assertEquals(0, ret.returnCode());

            // AcceptOnlySpecificKeyword with bad value is not instantiated for rejected with readResolve,
            assertNull(p.getProperty(KeywordProperty.class).getNonCriticalField());
            assertEquals(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());

            // but save to the disk.
            r.jenkins.reload();

            p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
            assertEquals("badvalue", p.getProperty(KeywordProperty.class).getNonCriticalField().getKeyword());
        }

        // with addCriticalField. This is not accepted.
        {
            FreeStyleProject p = r.createFreeStyleProject();
            p.addProperty(new KeywordProperty(
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD),
                    new AcceptOnlySpecificKeyword(AcceptOnlySpecificKeyword.ACCEPT_KEYWORD)
            ));
            p.save();

            // Configure a bad keyword via CLI.
            r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
            CLICommandInvoker.Result ret = new CLICommandInvoker(r, "update-job")
                    .asUser("test")
                    .withStdin(new ByteArrayInputStream(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue").getBytes()))
                    .withArgs(
                            p.getFullName()
                    )
                    .invoke();
            assertNotEquals(0, ret.returnCode());

            // Configuration should not be updated for a failure of the critical field,
            assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());

            r.jenkins.reload();

            // rejected configuration is not saved
            p = r.jenkins.getItemByFullName(p.getFullName(), FreeStyleProject.class);
            assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());
        }
    }
}


text:
@implementation EJCanvasContext2D

const EJCompositeOperationFunc EJCompositeOperationFuncs[] = {
	[kEJCompositeOperationSourceOver] = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 1},
	[kEJCompositeOperationLighter] = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA, 0},
	[kEJCompositeOperationDarker] = {GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA, 1},
	[kEJCompositeOperationDestinationOut] = {GL_ZERO, GL_ONE_MINUS_SRC_ALPHA, 1},
	[kEJCompositeOperationDestinationOver] = {GL_ONE_MINUS_DST_ALPHA, GL_ONE, 1},
	[kEJCompositeOperationSourceAtop] = {GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1},
	[kEJCompositeOperationXOR] = {GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1}
};

@synthesize state;
@synthesize backingStoreRatio;
@synthesize useRetinaResolution;
@synthesize imageSmoothingEnabled;

- (id)initWithScriptView:(EJJavaScriptView *)scriptViewp width:(short)widthp height:(short)heightp {
	if( self = [super init] ) {
		scriptView = scriptViewp;
		sharedGLContext = scriptView.openGLContext;
		glContext = sharedGLContext.glContext2D;
		vertexBuffer = (EJVertex *)(sharedGLContext.vertexBuffer.mutableBytes);
		vertexBufferSize = sharedGLContext.vertexBuffer.length / sizeof(EJVertex);

		memset(stateStack, 0, sizeof(stateStack));
		stateIndex = 0;
		state = &stateStack[stateIndex];
		state->globalAlpha = 1;
		state->globalCompositeOperation = kEJCompositeOperationSourceOver;
		state->transform = CGAffineTransformIdentity;
		state->lineWidth = 1;
		state->lineCap = kEJLineCapButt;
		state->lineJoin = kEJLineJoinMiter;
		state->miterLimit = 10;
		state->textBaseline = kEJTextBaselineAlphabetic;
		state->textAlign = kEJTextAlignStart;
		state->font = [[EJFontDescriptor descriptorWithName:@"Helvetica" size:10] retain];
		state->clipPath = nil;

		bufferWidth = width = widthp;
		bufferHeight = height = heightp;

		path = [[EJPath alloc] init];
		backingStoreRatio = 1;

		fontCache = [[NSCache alloc] init];
		fontCache.countLimit = 8;

		textureFilter = GL_LINEAR;
		msaaEnabled = NO;
		msaaSamples = 2;
	}
	return self;
}

- (void)dealloc {
	// Make sure this rendering context is the current one, so all
	// OpenGL objects can be deleted properly.
	EAGLContext *oldContext = [EAGLContext currentContext];
	[EAGLContext setCurrentContext:glContext];

	[fontCache release];

	// Release all fonts, clip paths and patterns from the stack
	for( int i = 0; i < stateIndex + 1; i++ ) {
		[stateStack[i].font release];
		[stateStack[i].clipPath release];
		[stateStack[i].fillObject release];
	}

	if( viewFrameBuffer ) { glDeleteFramebuffers( 1, &viewFrameBuffer); }
	if( viewRenderBuffer ) { glDeleteRenderbuffers(1, &viewRenderBuffer); }
	if( msaaFrameBuffer ) {	glDeleteFramebuffers( 1, &msaaFrameBuffer); }
	if( msaaRenderBuffer ) { glDeleteRenderbuffers(1, &msaaRenderBuffer); }
	if( stencilBuffer ) { glDeleteRenderbuffers(1, &stencilBuffer); }

	[path release];
	[EAGLContext setCurrentContext:oldContext];

	[super dealloc];
}

- (void)create {
	if( msaaEnabled ) {
		glGenFramebuffers(1, &msaaFrameBuffer);
		glGenRenderbuffers(1, &msaaRenderBuffer);
	}

	glGenFramebuffers(1, &viewFrameBuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, viewFrameBuffer);

	glGenRenderbuffers(1, &viewRenderBuffer);
	glBindRenderbuffer(GL_RENDERBUFFER, viewRenderBuffer);

	glDisable(GL_CULL_FACE);
	glDisable(GL_DITHER);

	glEnable(GL_BLEND);
	glDepthFunc(GL_ALWAYS);

	[self resizeToWidth:width height:height];
}

- (void)resizeToWidth:(short)newWidth height:(short)newHeight {
	// This function is a stub - Overwritten in both subclasses
	width = newWidth;
	height = newHeight;

	backingStoreRatio = (useRetinaResolution && [UIScreen mainScreen].scale == 2) ? 2 : 1;
	bufferWidth = width * backingStoreRatio;
	bufferHeight = height * backingStoreRatio;

	[self resetFramebuffer];
}

- (void)resetFramebuffer {
	// Delete stencil buffer if present; it will be re-created when needed
	if( stencilBuffer ) {
		glDeleteRenderbuffers(1, &stencilBuffer);
		stencilBuffer = 0;
	}

	// Resize the MSAA buffer
	if( msaaEnabled && msaaFrameBuffer && msaaRenderBuffer ) {
		glBindFramebuffer(GL_FRAMEBUFFER, msaaFrameBuffer);
		glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderBuffer);

		glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, msaaSamples, GL_RGBA8_OES, bufferWidth, bufferHeight);
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaRenderBuffer);
	}

	[self prepare];

	// Clear to transparent
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT);

	needsPresenting = YES;
}

- (void)createStencilBufferOnce {
	if( stencilBuffer ) { return; }

	glGenRenderbuffers(1, &stencilBuffer);
	glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
	if( msaaEnabled ) {
		glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, msaaSamples, GL_DEPTH24_STENCIL8_OES, bufferWidth, bufferHeight);
	}
	else {
		glRenderbufferStorageOES(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, bufferWidth, bufferHeight);
	}
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, stencilBuffer);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilBuffer);

	glBindRenderbuffer(GL_RENDERBUFFER, msaaEnabled ? msaaRenderBuffer : viewRenderBuffer );

	glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
}

- (void)bindVertexBuffer {
	glEnableVertexAttribArray(kEJGLProgram2DAttributePos);
	glVertexAttribPointer(kEJGLProgram2DAttributePos, 2, GL_FLOAT, GL_FALSE,
		sizeof(EJVertex), (char *)vertexBuffer + offsetof(EJVertex, pos));

	glEnableVertexAttribArray(kEJGLProgram2DAttributeUV);
	glVertexAttribPointer(kEJGLProgram2DAttributeUV, 2, GL_FLOAT, GL_FALSE,
		sizeof(EJVertex), (char *)vertexBuffer + offsetof(EJVertex, uv));

	glEnableVertexAttribArray(kEJGLProgram2DAttributeColor);
	glVertexAttribPointer(kEJGLProgram2DAttributeColor, 4, GL_UNSIGNED_BYTE, GL_TRUE,
		sizeof(EJVertex), (char *)vertexBuffer + offsetof(EJVertex, color));
}

- (void)prepare {
	// Bind the frameBuffer and vertexBuffer array
	glBindFramebuffer(GL_FRAMEBUFFER, msaaEnabled ? msaaFrameBuffer : viewFrameBuffer );
	glBindRenderbuffer(GL_RENDERBUFFER, msaaEnabled ? msaaRenderBuffer : viewRenderBuffer );

	glViewport(0, 0, bufferWidth, bufferHeight);

	EJCompositeOperation op = state->globalCompositeOperation;
	glBlendFunc( EJCompositeOperationFuncs[op].source, EJCompositeOperationFuncs[op].destination );
	currentTexture = nil;
	currentProgram = nil;

	[self bindVertexBuffer];

	if( stencilBuffer ) {
		glEnable(GL_DEPTH_TEST);
	}
	else {
		glDisable(GL_DEPTH_TEST);
	}

	if( state->clipPath ) {
		glDepthFunc(GL_EQUAL);
	}
	else {
		glDepthFunc(GL_ALWAYS);
	}

	needsPresenting = YES;
}

- (void)setWidth:(short)newWidth {
	if( newWidth == width ) { return; }
	[self resizeToWidth:newWidth height:height];
}

- (void)setHeight:(short)newHeight {
	if( newHeight == height ) { return; }
	[self resizeToWidth:width height:newHeight];
}

- (void)setTexture:(EJTexture *)newTexture {
	if( currentTexture == newTexture ) { return; }

	[self flushBuffers];

	currentTexture = newTexture;
	[currentTexture bindWithFilter:textureFilter];
}

- (void)setProgram:(EJGLProgram2D *)newProgram {
	if( currentProgram == newProgram ) { return; }

	[self flushBuffers];
	currentProgram = newProgram;

	glUseProgram(currentProgram.program);
	glUniform2f(currentProgram.screen, width, height * (upsideDown ? -1 : 1));
}

- (void)pushTriX1:(float)x1 y1:(float)y1 x2:(float)x2 y2:(float)y2
	x3:(float)x3 y3:(float)y3
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( vertexBufferIndex >= vertexBufferSize - 3 ) {
		[self flushBuffers];
	}

	EJVector2 d1 = { x1, y1 };
	EJVector2 d2 = { x2, y2 };
	EJVector2 d3 = { x3, y3 };

	if( !CGAffineTransformIsIdentity(transform) ) {
		d1 = EJVector2ApplyTransform( d1, transform );
		d2 = EJVector2ApplyTransform( d2, transform );
		d3 = EJVector2ApplyTransform( d3, transform );
	}

	EJVertex *vb = &vertexBuffer[vertexBufferIndex];
	vb[0] = (EJVertex) { d1, {0, 0}, color };
	vb[1] = (EJVertex) { d2, {0, 0}, color };
	vb[2] = (EJVertex) { d3, {0, 0}, color };

	vertexBufferIndex += 3;
}

- (void)pushQuadV1:(EJVector2)v1 v2:(EJVector2)v2 v3:(EJVector2)v3 v4:(EJVector2)v4
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( vertexBufferIndex >= vertexBufferSize - 6 ) {
		[self flushBuffers];
	}

	if( !CGAffineTransformIsIdentity(transform) ) {
		v1 = EJVector2ApplyTransform( v1, transform );
		v2 = EJVector2ApplyTransform( v2, transform );
		v3 = EJVector2ApplyTransform( v3, transform );
		v4 = EJVector2ApplyTransform( v4, transform );
	}

	EJVertex *vb = &vertexBuffer[vertexBufferIndex];
	vb[0] = (EJVertex) { v1, {0, 0}, color };
	vb[1] = (EJVertex) { v2, {0, 0}, color };
	vb[2] = (EJVertex) { v3, {0, 0}, color };
	vb[3] = (EJVertex) { v2, {0, 0}, color };
	vb[4] = (EJVertex) { v3, {0, 0}, color };
	vb[5] = (EJVertex) { v4, {0, 0}, color };

	vertexBufferIndex += 6;
}

- (void)pushRectX:(float)x y:(float)y w:(float)w h:(float)h
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( vertexBufferIndex >= vertexBufferSize - 6 ) {
		[self flushBuffers];
	}

	EJVector2 d11 = {x, y};
	EJVector2 d21 = {x+w, y};
	EJVector2 d12 = {x, y+h};
	EJVector2 d22 = {x+w, y+h};

	if( !CGAffineTransformIsIdentity(transform) ) {
		d11 = EJVector2ApplyTransform( d11, transform );
		d21 = EJVector2ApplyTransform( d21, transform );
		d12 = EJVector2ApplyTransform( d12, transform );
		d22 = EJVector2ApplyTransform( d22, transform );
	}

	EJVertex *vb = &vertexBuffer[vertexBufferIndex];
	vb[0] = (EJVertex) { d11, {0, 0}, color };	// top left
	vb[1] = (EJVertex) { d21, {0, 0}, color };	// top right
	vb[2] = (EJVertex) { d12, {0, 0}, color };	// bottom left

	vb[3] = (EJVertex) { d21, {0, 0}, color };	// top right
	vb[4] = (EJVertex) { d12, {0, 0}, color };	// bottom left
	vb[5] = (EJVertex) { d22, {0, 0}, color };	// bottom right

	vertexBufferIndex += 6;
}

- (void)pushFilledRectX:(float)x y:(float)y w:(float)w h:(float)h
	fillable:(NSObject<EJFillable> *)fillable
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( [fillable isKindOfClass:[EJCanvasPattern class]] ) {
		EJCanvasPattern *pattern = (EJCanvasPattern *)fillable;
		[self pushPatternedRectX:x y:y w:w h:h pattern:pattern color:color withTransform:transform];
	}
	else if( [fillable isKindOfClass:[EJCanvasGradient class]] ) {
		EJCanvasGradient *gradient = (EJCanvasGradient *)fillable;
		[self pushGradientRectX:x y:y w:w h:h gradient:gradient color:color withTransform:transform];
	}
}

- (void)pushGradientRectX:(float)x y:(float)y w:(float)w h:(float)h
	gradient:(EJCanvasGradient *)gradient
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( gradient.type == kEJCanvasGradientTypeLinear ) {
		// Local positions inside the quad
		EJVector2 p1 = {(gradient.p1.x-x)/w, (gradient.p1.y-y)/h};
		EJVector2 p2 = {(gradient.p2.x-x)/w, (gradient.p2.y-y)/h};

		// Calculate the slope of (p1,p2) and the line orthogonal to it
		float aspect = w/h;
		EJVector2 slope = EJVector2Sub(p2, p1);
		EJVector2 ortho = {slope.y/aspect, -slope.x*aspect};

		// Calculate the intersection points of the slope (starting at p1)
		// and the orthogonal starting at each corner of the quad - these
		// points are the final texture coordinates.
		float d = 1/(slope.y * ortho.x - slope.x * ortho.y);

		EJVector2
			ot = {ortho.x * d, ortho.y * d},
			st = {slope.x * d, slope.y * d};

		EJVector2
			a11 = {ot.x * -p1.y, st.x * -p1.y},
			a12 = {ot.y * p1.x, st.y * p1.x},
			a21 = {ot.x * (1 - p1.y), st.x * (1 - p1.y)},
			a22 = {ot.y * (p1.x - 1), st.y * (p1.x - 1)};

		EJVector2
			t11 = {a11.x + a12.x, a11.y + a12.y},
			t21 = {a11.x + a22.x, a11.y + a22.y},
			t12 = {a21.x + a12.x, a21.y + a12.y},
			t22 = {a21.x + a22.x, a21.y + a22.y};

		[self setProgram:sharedGLContext.glProgram2DTexture];
		[self setTexture:gradient.texture];
		if( vertexBufferIndex >= vertexBufferSize - 6 ) {
			[self flushBuffers];
		}

		// Vertex coordinates
		EJVector2 d11 = {x, y};
		EJVector2 d21 = {x+w, y};
		EJVector2 d12 = {x, y+h};
		EJVector2 d22 = {x+w, y+h};

		if( !CGAffineTransformIsIdentity(transform) ) {
			d11 = EJVector2ApplyTransform( d11, transform );
			d21 = EJVector2ApplyTransform( d21, transform );
			d12 = EJVector2ApplyTransform( d12, transform );
			d22 = EJVector2ApplyTransform( d22, transform );
		}

		EJVertex *vb = &vertexBuffer[vertexBufferIndex];
		vb[0] = (EJVertex) { d11, t11, color };	// top left
		vb[1] = (EJVertex) { d21, t21, color };	// top right
		vb[2] = (EJVertex) { d12, t12, color };	// bottom left

		vb[3] = (EJVertex) { d21, t21, color };	// top right
		vb[4] = (EJVertex) { d12, t12, color };	// bottom left
		vb[5] = (EJVertex) { d22, t22, color };	// bottom right

		vertexBufferIndex += 6;
	}

	else if( gradient.type == kEJCanvasGradientTypeRadial ) {
		[self flushBuffers];

		EJGLProgram2DRadialGradient *gradientProgram = sharedGLContext.glProgram2DRadialGradient;
		[self setProgram:gradientProgram];

		glUniform3f(gradientProgram.inner, gradient.p1.x, gradient.p1.y, gradient.r1);
		EJVector2 dp = EJVector2Sub(gradient.p2, gradient.p1);
		float dr = gradient.r2 - gradient.r1;
		glUniform3f(gradientProgram.diff, dp.x, dp.y, dr);

		[self setTexture:gradient.texture];
		[self pushTexturedRectX:x y:y w:w h:h tx:x ty:y tw:w th:h color:color withTransform:transform];
	}
}

- (void)pushPatternedRectX:(float)x y:(float)y w:(float)w h:(float)h
	pattern:(EJCanvasPattern *)pattern
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	EJTexture *texture = pattern.texture;
	float scale = texture.contentScale;
	float
		tw = texture.width / scale,
		th = texture.height / scale,
		pw = w,
		ph = h;

	if( !(pattern.repeat & kEJCanvasPatternRepeatX) ) {
		pw = MIN(tw - x, w);
	}
	if( !(pattern.repeat & kEJCanvasPatternRepeatY) ) {
		ph = MIN(th - y, h);
	}

	if( pw > 0 && ph > 0 ) { // We may have to skip entirely
		[self setProgram:sharedGLContext.glProgram2DPattern];
		[self setTexture:texture];

		[self pushTexturedRectX:x y:y w:pw h:ph tx:x/tw ty:y/th tw:pw/tw th:ph/th
			color:color withTransform:transform];
	}

	if( pw < w || ph < h ) {
		// Draw clearing rect for the stencil buffer if we didn't fill everything with
		// the pattern image - happens when not repeating in both directions
		[self setProgram:sharedGLContext.glProgram2DFlat];
		EJColorRGBA transparentBlack = {.hex = 0x00000000};
		[self pushRectX:x y:y w:w h:h color:transparentBlack withTransform:transform];
	}
}

- (void)pushTexturedRectX:(float)x y:(float)y w:(float)w h:(float)h
	tx:(float)tx ty:(float)ty tw:(float)tw th:(float)th
	color:(EJColorRGBA)color
	withTransform:(CGAffineTransform)transform
{
	if( vertexBufferIndex >= vertexBufferSize - 6 ) {
		[self flushBuffers];
	}

	EJVector2 d11 = {x, y};
	EJVector2 d21 = {x+w, y};
	EJVector2 d12 = {x, y+h};
	EJVector2 d22 = {x+w, y+h};

	if( !CGAffineTransformIsIdentity(transform) ) {
		d11 = EJVector2ApplyTransform( d11, transform );
		d21 = EJVector2ApplyTransform( d21, transform );
		d12 = EJVector2ApplyTransform( d12, transform );
		d22 = EJVector2ApplyTransform( d22, transform );
	}

	EJVertex *vb = &vertexBuffer[vertexBufferIndex];
	vb[0] = (EJVertex) { d11, {tx, ty}, color };	// top left
	vb[1] = (EJVertex) { d21, {tx+tw, ty}, color };	// top right
	vb[2] = (EJVertex) { d12, {tx, ty+th}, color };	// bottom left

	vb[3] = (EJVertex) { d21, {tx+tw, ty}, color };	// top right
	vb[4] = (EJVertex) { d12, {tx, ty+th}, color };	// bottom left
	vb[5] = (EJVertex) { d22, {tx+tw, ty+th}, color };	// bottom right

	vertexBufferIndex += 6;
}

- (void)flushBuffers {
	if( vertexBufferIndex == 0 ) { return; }

	glDrawArrays(GL_TRIANGLES, 0, vertexBufferIndex);
	needsPresenting = YES;
	vertexBufferIndex = 0;
}

- (BOOL)imageSmoothingEnabled {
	return (textureFilter == GL_LINEAR);
}

- (void)setImageSmoothingEnabled:(BOOL)enabled {
	[self setTexture:NULL]; // force rebind for next texture
	textureFilter = (enabled ? GL_LINEAR : GL_NEAREST);
}

- (void)setGlobalCompositeOperation:(EJCompositeOperation)op {
	// Same composite operation or switching between SourceOver <> Lighter? We don't
	// have to flush and set the blend mode then, but we still need to update the state,
	// as the alphaFactor may be different.
	if(
		op == state->globalCompositeOperation ||
		(op == kEJCompositeOperationLighter && state->globalCompositeOperation == kEJCompositeOperationSourceOver) ||
		(op == kEJCompositeOperationSourceOver && state->globalCompositeOperation == kEJCompositeOperationLighter)
	) {
		state->globalCompositeOperation = op;
		return;
	}

	[self flushBuffers];
	glBlendFunc( EJCompositeOperationFuncs[op].source, EJCompositeOperationFuncs[op].destination );
	state->globalCompositeOperation = op;
}

- (EJCompositeOperation)globalCompositeOperation {
	return state->globalCompositeOperation;
}

- (void)setFont:(EJFontDescriptor *)font {
	[state->font release];
	state->font = [font retain];
}

- (EJFontDescriptor *)font {
	return state->font;
}

- (void)setFillObject:(NSObject<EJFillable> *)fillObject {
	[state->fillObject release];
	state->fillObject = [fillObject retain];
}

- (NSObject<EJFillable> *)fillObject {
	return state->fillObject;
}

- (void)save {
	if( stateIndex == EJ_CANVAS_STATE_STACK_SIZE-1 ) {
		NSLog(@"Warning: EJ_CANVAS_STATE_STACK_SIZE (%d) reached", EJ_CANVAS_STATE_STACK_SIZE);
		return;
	}

	stateStack[stateIndex+1] = stateStack[stateIndex];
	stateIndex++;
	state = &stateStack[stateIndex];
	[state->font retain];
	[state->fillObject retain];
	[state->clipPath retain];
}

- (void)restore {
	if( stateIndex == 0 ) {	return; }

	EJCompositeOperation oldCompositeOp = state->globalCompositeOperation;
	EJPath *oldClipPath = state->clipPath;

	// Clean up current state
	[state->font release];
	[state->fillObject release];

	if( state->clipPath && state->clipPath != stateStack[stateIndex-1].clipPath ) {
		[self resetClip];
	}
	[state->clipPath release];

	// Load state from stack
	stateIndex--;
	state = &stateStack[stateIndex];

	path.transform = state->transform;

	// Set Composite op, if different
	if( state->globalCompositeOperation != oldCompositeOp ) {
		self.globalCompositeOperation = state->globalCompositeOperation;
	}

	// Render clip path, if present and different
	if( state->clipPath && state->clipPath != oldClipPath ) {
		[self setProgram:sharedGLContext.glProgram2DFlat];
		[state->clipPath drawPolygonsToContext:self target:kEJPathPolygonTargetDepth];
	}
}

- (void)rotate:(float)angle {
	state->transform = CGAffineTransformRotate( state->transform, angle );
	path.transform = state->transform;
}

- (void)translateX:(float)x y:(float)y {
	state->transform = CGAffineTransformTranslate( state->transform, x, y );
	path.transform = state->transform;
}

- (void)scaleX:(float)x y:(float)y {
	state->transform = CGAffineTransformScale( state->transform, x, y );
	path.transform = state->transform;
}

- (void)transformM11:(float)m11 m12:(float)m12 m21:(float)m21 m22:(float)m22 dx:(float)dx dy:(float)dy {
	CGAffineTransform t = CGAffineTransformMake( m11, m12, m21, m22, dx, dy );
	state->transform = CGAffineTransformConcat( t, state->transform );
	path.transform = state->transform;
}

- (void)setTransformM11:(float)m11 m12:(float)m12 m21:(float)m21 m22:(float)m22 dx:(float)dx dy:(float)dy {
	state->transform = CGAffineTransformMake( m11, m12, m21, m22, dx, dy );
	path.transform = state->transform;
}

- (void)drawImage:(EJTexture *)texture sx:(float)sx sy:(float)sy sw:(float)sw sh:(float)sh dx:(float)dx dy:(float)dy dw:(float)dw dh:(float)dh {

	float tw = texture.width;
	float th = texture.height;

	[self setProgram:sharedGLContext.glProgram2DTexture];
	[self setTexture:texture];
	[self pushTexturedRectX:dx y:dy w:dw h:dh tx:sx/tw ty:sy/th tw:sw/tw th:sh/th
		color:EJCanvasBlendWhiteColor(state) withTransform:state->transform];
}

- (void)fillRectX:(float)x y:(float)y w:(float)w h:(float)h {
	if( state->fillObject ) {
		[self pushFilledRectX:x y:y w:w h:h fillable:state->fillObject
			color:EJCanvasBlendWhiteColor(state) withTransform:state->transform];
	}
	else {
		[self setProgram:sharedGLContext.glProgram2DFlat];

		EJColorRGBA cc = EJCanvasBlendFillColor(state);
		[self pushRectX:x y:y w:w h:h
			color:cc withTransform:state->transform];
	}
}

- (void)strokeRectX:(float)x y:(float)y w:(float)w h:(float)h {
	// strokeRect should not affect the current path, so we create
	// a new, tempPath instead.
	EJPath *tempPath = [[EJPath alloc] init];
	tempPath.transform = state->transform;

	[tempPath moveToX:x y:y];
	[tempPath lineToX:x+w y:y];
	[tempPath lineToX:x+w y:y+h];
	[tempPath lineToX:x y:y+h];
	[tempPath close];

	[self setProgram:sharedGLContext.glProgram2DFlat];
	[tempPath drawLinesToContext:self];
	[tempPath release];
}

- (void)clearRectX:(float)x y:(float)y w:(float)w h:(float)h {
	[self setProgram:sharedGLContext.glProgram2DFlat];

	EJCompositeOperation oldOp = state->globalCompositeOperation;
	self.globalCompositeOperation = kEJCompositeOperationDestinationOut;

	static EJColorRGBA white = {.hex = 0xffffffff};
	[self pushRectX:x y:y w:w h:h color:white withTransform:state->transform];

	self.globalCompositeOperation = oldOp;
}

- (EJImageData*)getImageDataScaled:(float)scale flipped:(bool)flipped sx:(short)sx sy:(short)sy sw:(short)sw sh:(short)sh {

	[self flushBuffers];

	NSMutableData *pixels;

	// Fast case - no scaling, no flipping
	if( scale == 1 && !flipped ) {
		pixels = [NSMutableData dataWithLength:sw * sh * 4 * sizeof(GLubyte)];
		glReadPixels(sx, sy, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, pixels.mutableBytes);
	}

	// More processing needed - take care of the flipped screen layout and the scaling
	else {
		int internalWidth = sw * scale;
		int internalHeight = sh * scale;
		int internalX = sx * scale;
		int internalY = (height-sy-sh) * scale;

		EJColorRGBA *internalPixels = malloc( internalWidth * internalHeight * sizeof(EJColorRGBA));
		glReadPixels( internalX, internalY, internalWidth, internalHeight, GL_RGBA, GL_UNSIGNED_BYTE, internalPixels );

		int size = sw * sh * sizeof(EJColorRGBA);
		EJColorRGBA *scaledPixels = malloc( size );
		int index = 0;
		for( int y = 0; y < sh; y++ ) {
			int rowIndex = (int)((flipped ? sh-y-1 : y) * scale) * internalWidth;
			for( int x = 0; x < sw; x++ ) {
				int internalIndex = rowIndex + (int)(x * scale);
				scaledPixels[ index ] = internalPixels[ internalIndex ];
				index++;
			}
		}
		free(internalPixels);

		pixels = [NSMutableData dataWithBytesNoCopy:scaledPixels length:size];
	}

	return [[[EJImageData alloc] initWithWidth:sw height:sh pixels:pixels] autorelease];
}

- (EJImageData*)getImageDataSx:(short)sx sy:(short)sy sw:(short)sw sh:(short)sh {
	return [self getImageDataScaled:backingStoreRatio flipped:upsideDown sx:sx sy:sy sw:sw sh:sh];
}

- (EJImageData*)getImageDataHDSx:(short)sx sy:(short)sy sw:(short)sw sh:(short)sh {
	return [self getImageDataScaled:1 flipped:upsideDown sx:sx sy:sy sw:sw sh:sh];
}

- (void)putImageData:(EJImageData*)imageData scaled:(float)scale dx:(float)dx dy:(float)dy {
	EJTexture *texture = imageData.texture;
	[self setProgram:sharedGLContext.glProgram2DTexture];
	[self setTexture:texture];

	short tw = texture.width / scale;
	short th = texture.height / scale;

	static EJColorRGBA white = {.hex = 0xffffffff};

	[self pushTexturedRectX:dx y:dy w:tw h:th tx:0 ty:0 tw:1 th:1 color:white withTransform:CGAffineTransformIdentity];
	[self flushBuffers];
}

- (void)putImageData:(EJImageData*)imageData dx:(float)dx dy:(float)dy {
	[self putImageData:imageData scaled:1 dx:dx dy:dy];
}

- (void)putImageDataHD:(EJImageData*)imageData dx:(float)dx dy:(float)dy {
	[self putImageData:imageData scaled:backingStoreRatio dx:dx dy:dy];
}

- (void)beginPath {
	[path reset];
}

- (void)closePath {
	[path close];
}

- (void)fill {
	[self setProgram:sharedGLContext.glProgram2DFlat];
	[path drawPolygonsToContext:self target:kEJPathPolygonTargetColor];
}

- (void)stroke {
	[self setProgram:sharedGLContext.glProgram2DFlat];
	[path drawLinesToContext:self];
}

- (void)moveToX:(float)x y:(float)y {
	[path moveToX:x y:y];
}

- (void)lineToX:(float)x y:(float)y {
	[path lineToX:x y:y];
}

- (void)bezierCurveToCpx1:(float)cpx1 cpy1:(float)cpy1 cpx2:(float)cpx2 cpy2:(float)cpy2 x:(float)x y:(float)y {
	float scale = CGAffineTransformGetScale( state->transform );
	[path bezierCurveToCpx1:cpx1 cpy1:cpy1 cpx2:cpx2 cpy2:cpy2 x:x y:y scale:scale];
}

- (void)quadraticCurveToCpx:(float)cpx cpy:(float)cpy x:(float)x y:(float)y {
	float scale = CGAffineTransformGetScale( state->transform );
	[path quadraticCurveToCpx:cpx cpy:cpy x:x y:y scale:scale];
}

- (void)rectX:(float)x y:(float)y w:(float)w h:(float)h {
	[path moveToX:x y:y];
	[path lineToX:x+w y:y];
	[path lineToX:x+w y:y+h];
	[path lineToX:x y:y+h];
	[path close];
}

- (void)arcToX1:(float)x1 y1:(float)y1 x2:(float)x2 y2:(float)y2 radius:(float)radius {
	[path arcToX1:x1 y1:y1 x2:x2 y2:y2 radius:radius];
}

- (void)arcX:(float)x y:(float)y radius:(float)radius
	startAngle:(float)startAngle endAngle:(float)endAngle
	antiClockwise:(BOOL)antiClockwise
{
	[path arcX:x y:y radius:radius startAngle:startAngle endAngle:endAngle antiClockwise:antiClockwise];
}

- (EJFont *)getFontWithDescriptor:(EJFontDescriptor *)desc filled:(BOOL)filled {
	NSString *cacheKey = (filled)
		? [desc identFilled]
		: [desc identOutlinedWithWidth:state->lineWidth];

	EJFont *font = [fontCache objectForKey:cacheKey];
	if( !font ) {
		font = [[EJFont alloc] initWithDescriptor:desc fill:filled lineWidth:state->lineWidth contentScale:backingStoreRatio];
		[fontCache setObject:font forKey:cacheKey];
		[font autorelease];
	}
	return font;
}

- (void)fillText:(NSString *)text x:(float)x y:(float)y {
	EJFont *font = [self getFontWithDescriptor:state->font filled:YES];

	[self setProgram:sharedGLContext.glProgram2DAlphaTexture];
	[font drawString:text toContext:self x:x y:y];
}

- (void)strokeText:(NSString *)text x:(float)x y:(float)y {
	EJFont *font = [self getFontWithDescriptor:state->font filled:NO];

	[self setProgram:sharedGLContext.glProgram2DAlphaTexture];
	[font drawString:text toContext:self x:x y:y];
}

- (EJTextMetrics)measureText:(NSString *)text {
	EJFont *font = [self getFontWithDescriptor:state->font filled:YES];
	return [font measureString:text forContext:self];
}

- (void)clip {
	[self flushBuffers];
	[state->clipPath release];
	state->clipPath = nil;

	state->clipPath = path.copy;
	[self setProgram:sharedGLContext.glProgram2DFlat];
	[state->clipPath drawPolygonsToContext:self target:kEJPathPolygonTargetDepth];
}

- (void)resetClip {
	if( state->clipPath ) {
		[self flushBuffers];
		[state->clipPath release];
		state->clipPath = nil;

		glDepthMask(GL_TRUE);
		glClear(GL_DEPTH_BUFFER_BIT);
		glDepthMask(GL_FALSE);
		glDepthFunc(GL_ALWAYS);
	}
}

@end

redpajama_set_name: RedPajamaGithub


text:
//
//  FFLocalStorage.h
//  FF-IOS-Framework
//
//  Copyright (c) 2013 FatFractal, Inc. All rights reserved.
//
//

#import <Foundation/Foundation.h>
#import "FFQueuedOperation.h"

@class FatFractal;

@protocol FFLocalStorage <NSObject>

/**
 Load operations from the local database.
 @return Array of FFQueuedOperation objects read from the local database.
 */
- (NSMutableArray *)loadQueuedOperationsFromLocalStorage:(FatFractal *)ff error:(NSError **)outErr;

/**
 Store an operation to the local database.
 @param op  The operation to store.
 */
- (void)storeQueuedOperationToLocalStorage:(FatFractal *)ff op:(FFQueuedOperation *)op error:(NSError **)outErr;

/**
 Remove an operation from the local database.
 @param op  The operation to remove.
 */
- (void)removeQueuedOperationFromLocalStorage:(FatFractal *)ff op:(FFQueuedOperation *)op error:(NSError **)outErr;

- (NSData *) loadDataFromCacheUsingKey:(NSString *)cacheKey tag:(NSString *)tag userGuid:(NSString *)userGuid error:(NSError **)outErr;
- (void) storeDataToCache:(NSData *)data key:(NSString *)cacheKey tag:(NSString *)tag userGuid:(NSString *)userGuid error:(NSError **)outErr;
- (void) removeDataFromCacheUsingKey:(NSString *)cacheKey userGuid:(NSString *)userGuid error:(NSError **)outErr;

/**
 * Deletes all offline queued operations and all cached data for every FatFractal instance which uses this LocalStorage
 */
- (void) wipeAllData;

/**
 * Deletes all offline queued operations for every FatFractal instance which uses this LocalStorage
 */
- (NSError *) wipeQueuedOperations;

/**
 * Deletes all cached data for every FatFractal instance which uses this LocalStorage
 */
- (NSError *) wipeCache;

- (BOOL) debug;
- (void) setDebug:(BOOL)flag;

@end


text:
#include "contig.h"

/*convert the character to  a base*/
valid_base char_2_base(const char a)
{
	valid_base base = N;
	switch(a){
		case 'a': base = A; break;
		case 'A': base = A; break;
		case 'c': base = C; break;
		case 'C': base = C; break;
		case 'g': base = G; break;
		case 'G': base = G; break;
		case 't': base = T; break;
		case 'T': base = T; break;
		case '*': base = GAP; break;
		case 'N': base = N; break;
		case 'n': base = N; break;
		default: fatalf("unknown base:%c", a);
	}
	return base;
}

/*convert a base to a character*/
char base_2_char(const valid_base a)
{
	char b;
	switch(a){
		case A: b = 'A'; break;
		case C: b = 'C'; break;
		case G: b = 'G'; break;
		case T: b = 'T'; break;
		case N: b = 'N'; break;
		default: b = '*'; break;
	}
	return b;
}

/*make a new contig of this size*/
contig* construct_contig(const int num_bases,
						 const int num_reads,
						 const int num_segments)
{
	contig* contig = ckallocz(sizeof(struct contig_st));

	contig->num_bases = num_bases;
	contig->num_reads = num_reads;
	contig->num_segments = num_segments;

	contig->reads = ckallocz(num_reads*sizeof(sff_read**));
	contig->info  = ckallocz(num_bases*sizeof(information));
	return contig;
}

/*create a new allele*/
allele* new_allele(const char base, const char qual, sff_read* const read)
{
	allele* allele = ckalloc(sizeof(struct allele_st));
	allele->base = char_2_base(base);
	allele->quality = qual;
	allele->read = read;
	allele->next = NULL;

	return allele;
}

static void free_contig(contig* contig)
{
	ckfree(contig->header);
	ckfree(contig->reads);

	unsigned int i;
	information info;

	for(i = 0; i < contig->num_bases; i++){
		info = contig->info[i];
		slfreelist(&info.alleles);
	}
	ckfree(contig->info);
}

/*free the resources associated with all the contigs*/
void free_contigs(contig** pcontigs)
{
	contig* iter;
	contig* contigs = *pcontigs;
	for(iter = contigs; iter; iter = iter->next){
		free_contig(iter);
	}
	slfreelist(pcontigs);
	ckfree(*pcontigs);
	*pcontigs = NULL;
}

/*for debugging purposes : print the contig in detail*/
void print_contig(const contig* const contig)
{
	unsigned int i;
	sff_read* read;
	information info;
	allele* iter;

	printf("%s\n", contig->header);
	printf("Number of bases:%d\n", contig->num_bases);
	printf("Number of reads:%d\n", contig->num_reads);
	printf("Number of segments:%d\n", contig->num_segments);

	for(i = 0; i < contig->num_reads; i++){
		read = contig->reads[i];
		printf("%s\t%s\n", read->header->name, read->individual);
	}

	for(i = 0; i < contig->num_bases; i++){
		info = contig->info[i];
		printf("%c(%d)\t", base_2_char(info.consensus), info.quality);
		for(iter = info.alleles; iter; iter = iter->next){
			printf("%c(%d)\t", base_2_char(iter->base), iter->quality);
		}
		printf("\n");
	}
}


text:
import ExpandableSection from "../src/ExpandableSection.js";
export default class ElixExpandableSection extends ExpandableSection {}
customElements.define("elix-expandable-section", ElixExpandableSection);


text:
import {Injectable} from '@angular/core';
import {Fornecedor} from './Fornecedor';
import {Http, Response, Headers, RequestOptions} from "@angular/http";
import 'rxjs/add/operator/toPromise';
import {Mensagem} from "../Mensagem";

@Injectable()
export class FornecedorService {
    constructor(private http: Http) {
    }
    getFornecedor(){
        return this.http.get("/fornecedor")
            .toPromise()
            .then(response => {return response.json() as Fornecedor})
            .catch();
    }

    salvarFornecedor(fornecedor:Fornecedor) {
        return this.http.post( "/fornecedor/salvar", fornecedor)
            .toPromise()
            .then(response => response.json() as Mensagem);
    }

    private handleError(error: any): Promise<any> {
        console.error('An error occurred', error); // for demo purposes only
        return Promise.reject(error.message || error);
    }
}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        <title>SFML - Simple and Fast Multimedia Library</title>
        <meta http-equiv="Content-Type" content="text/html;"/>
        <meta charset="utf-8"/>

        <link rel="stylesheet" type="text/css" href="doxygen.css" title="default" media="screen,print" />

                SFML 2.4.1

Main Page

Related Pages

Modules

Namespaces

Classes

Files

Class List

Class Index

Class Hierarchy

Class Members

sf

Event

SensorEvent

Public Attributes |
List of all members

sf::Event::SensorEvent Struct Reference

Sensor event parameters (SensorChanged)
 More...

#include <Event.hpp>

Public Attributes

Sensor::Type 	type

 	Type of the sensor.  More...

float 	x

 	Current value of the sensor on X axis.  More...

float 	y

 	Current value of the sensor on Y axis.  More...

float 	z

 	Current value of the sensor on Z axis.  More...

Detailed Description

Sensor event parameters (SensorChanged)

Definition at line 175 of file Event.hpp.

Member Data Documentation

          Sensor::Type sf::Event::SensorEvent::type

Type of the sensor.

Definition at line 177 of file Event.hpp.

          float sf::Event::SensorEvent::x

Current value of the sensor on X axis.

Definition at line 178 of file Event.hpp.

          float sf::Event::SensorEvent::y

Current value of the sensor on Y axis.

Definition at line 179 of file Event.hpp.

          float sf::Event::SensorEvent::z

Current value of the sensor on Z axis.

Definition at line 180 of file Event.hpp.

The documentation for this struct was generated from the following file:

Event.hpp

                SFML is licensed under the terms and conditions of the zlib/png license.

                Copyright © Laurent Gomila  ::
                Documentation generated by doxygen  ::


text:
package com.itheima.mobilesafe.utils.objects;

/**
 * Created by Catherine on 2016/8/19.
 * Soft-World Inc.
 * catherine919@soft-world.com.tw
 */

import android.graphics.Bitmap;

import java.util.LinkedList;
import java.util.List;

/**
 * 手机联系人
 */
public class Contact {
    public String id;
    public String name;
    public List<String> phone = new LinkedList<>();
    public String email;
    public String company;
    public String address;
    public Bitmap photo;
    public Bitmap circlarPhoto;

    @Override
    public String toString() {
        return "Contact{" +
                "address='" + address + '\'' +
                ", id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", phone=" + phone +
                ", email='" + email + '\'' +
                ", company='" + company + '\'' +
                ", photo=" + photo +
                ", circlarPhoto=" + circlarPhoto +
                '}';
    }
}


text:
/**
 * Constructor method.
 */
function SoundManager() {}

/**
* Plays a sound.
*
* @param AssetManager assetManager
* @return sound instance
*/
SoundManager.prototype.play = function(src, interrupt, delay, offset, loop, volume, pan, startTime, duration) {
	if (this.soundIsOn() === false) { //sort of IE9 fix...
		return;
	}
	return createjs.Sound.play(src, interrupt, delay, offset, loop, volume, pan, startTime, duration);
};

/**
* ...
*
* @param AssetManager assetManager
* @return sound instance
*/
SoundManager.prototype.playInstance = function(soundInstance) {
	if (this.soundIsOn() === false) { //sort of IE9 fix...
		return;
	}
	return soundInstance.play();
};

/**
 * Appends the SoundManager onto the element.
 *
 * @return boolean
 */
SoundManager.prototype.toggleSound = function() {
	createjs.Sound.setMute(!createjs.Sound.getMute());
	return this.soundIsOn();
};

/**
* ...
*
* @return boolean
*/
SoundManager.prototype.soundIsOn = function() {
	return !createjs.Sound.getMute();
};

fragment.soundManager = new SoundManager();


text:
var Constants = require('./constants');
var req = require('request');
var debug = require('debug')('node-gcm');

function SenderBase(key, options) {
    if (!(this instanceof SenderBase)) {
        return new SenderBase(key, options);
    }

    this.key = key;
    this.options = options;

    // added to support child dependency injection
    this.req = this.req ? this.req : require('request');
}

SenderBase.prototype.sendBaseNoRetry = function(message, recipient, callback) {
    if(!callback) {
        callback = function() {};
    }

    var body = {},
        requestBody,
        post_options,
        post_req,
        timeout;

    if (recipient && recipient.registrationIds) {
        // Registration IDs take precedence
        body[Constants.JSON_REGISTRATION_IDS] = recipient.registrationIds;
    } else if (recipient && recipient.notificationKey && recipient.notificationKey.length) {
        body[Constants.PARAM_TO] = recipient.notificationKey;
    } else {
        return callback('No recipients provided', null);
    }

    if (message.delayWhileIdle !== undefined) {
        body[Constants.PARAM_DELAY_WHILE_IDLE] = message.delayWhileIdle;
    }
    if (message.collapseKey !== undefined) {
        body[Constants.PARAM_COLLAPSE_KEY] = message.collapseKey;
    }
    if (message.timeToLive !== undefined) {
        body[Constants.PARAM_TIME_TO_LIVE] = message.timeToLive;
    }
    if (message.dryRun !== undefined) {
        body[Constants.PARAM_DRY_RUN] = message.dryRun;
    }
    if (message.data && Object.keys(message.data)) {
        if (recipient.notificationKey) {
            message.data[Constants.JSON_NOTIFICATION_KEY] = recipient.notificationKey;
        }
        body[Constants.PARAM_PAYLOAD_KEY] = message.data;
    }

    requestBody = JSON.stringify(body);

    post_options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-length': Buffer.byteLength(requestBody, 'utf8'),
            'Authorization': 'key=' + this.key
        },
        uri: Constants.GCM_SEND_URI,
        body: requestBody
    };

    if (this.options && this.options.proxy) {
        post_options.proxy = this.options.proxy;
    }

    if (this.options && this.options.maxSockets) {
        post_options.maxSockets = this.options.maxSockets;
    }

    timeout = Constants.SOCKET_TIMEOUT;

    if (this.options && this.options.timeout) {
        timeout =  this.options.timeout;
    }

    post_options.timeout = timeout;

    post_req = this.req(post_options, function (err, res, resBody) {

        if (err) {
            return callback(err, null);
        }
        if (!res) {
            return callback('response is null', null);
        }
        if (res.statusCode >= 500) {
            debug('GCM service is unavailable (500)');
            return callback(res.statusCode, resBody);
        } else if (res.statusCode === 401) {
            debug('Unauthorized (401). Check that your API token is correct.');
            return callback(res.statusCode, 'Unauthorized. Check that your API token is correct.');
        } else if (res.statusCode !== 200) {
            debug('Invalid request (' + res.statusCode + '): ' + resBody);
            return callback(res.statusCode, resBody);
        }

        try {
            callback(null, JSON.parse(resBody));
        } catch (e) {
            debug("Error handling GCM response " + e);
            callback("error", e);
        }
    });
};

SenderBase.prototype.sendBase = function(message, recipient, retries, callback) {
    if(typeof retries == "undefined" || typeof retries == "function") {
        callback = retries;
        retries = 5;
    }
    if(!callback) {
        callback = function() {};
    }

    var attempt = 0,
        backoff = Constants.BACKOFF_INITIAL_DELAY,
        self = this;

    if (recipient && (recipient.notificationKey ||
        (recipient.registrationIds && recipient.registrationIds.length))) {

        this.sendBaseNoRetry(message, recipient, function lambda(err, result) {

            if (attempt < retries) {
                var sleepTime, unsentRegIds = [], i;

                // If registration IDs are provided, retry if an error occurred for the whole request
                // or retry if the request was unsuccessful for a subset of the registration IDs.
                if (recipient.registrationIds && recipient.registrationIds.length) {

                    // if we err'd resend them all
                    if (err) {
                        unsentRegIds = recipient.registrationIds;
                    }
                    // success but check for bad ids
                    else {
                        for (i = 0; i < recipient.registrationIds.length; i++) {
                            if (result.results[i].error === 'Unavailable') {
                                unsentRegIds.push(recipient.registrationIds[i]);
                            }
                        }
                    }

                    if (unsentRegIds.length) {
                        if (result) {
                            debug("Results received but not all successful", result);
                        }

                        recipient.registrationIds = unsentRegIds;

                        setTimeout(function () {
                            self.sendBaseNoRetry(message, recipient, lambda);
                        }, calculateSleepTime(attempt, backoff));
                        attempt += 1;
                    } else {
                        // No more registration ids to send
                        callback(err, result);
                    }

                }
                // If a notification_key is provided (and no registration IDs), retry if an error occurred.
                else if (recipient.notificationKey) {

                    var retry = false;

                    if (result && result.success && result.failure && result.failed_registration_ids) {
                        // Google's suggestion is unclear, as there seems no way to "resend" a partially successful
                        // message with a notification_key without sending duplicates to the successful reg IDs.
                        // The current solution here is to revert back to a registration ID collection and retry.

                        recipient = { registrationIds: result.failed_registration_ids };
                        retry = true;

                    } else if (err) {
                        retry = true;
                    }

                    if (retry) {
                        setTimeout(function () {
                            self.sendBaseNoRetry(message, recipient, lambda);
                        }, calculateSleepTime(attempt, backoff));
                        attempt += 1;
                    } else {
                        callback(err, result);
                    }
                }
                // Recipient is invalid at this point
                else {
                    callback(err, result);
                }

            } else {
                // attempts has exceeded retries
                callback(err, result);
            }
        });
    } else {
        debug('No recipient data provided!');
        callback('No recipient data provided!', null);
    }
};

function calculateSleepTime(attempt, backoff) {
    var sleepTime = Math.pow (2, attempt) * backoff;
    if (sleepTime > Constants.MAX_BACKOFF_DELAY) {
        sleepTime = Constants.MAX_BACKOFF_DELAY;
    }
    return sleepTime;
}

module.exports = SenderBase;