Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* ************************************************************************
  #
  #  DivConq
  #
  #  http://divconq.com/
  #
  #  Copyright:
  #    Copyright 2014 eTimeline, LLC. All rights reserved.
  #
 #  License:
 #    See the license.txt file in the project's top-level directory for details.
 #
 #  Authors:
 #    * Andy White
 #
 ************************************************************************ */
 package divconq.lang.chars;
 
 
 import java.util.List;
 
 
 public class Utf8Decoder implements ICharDecoder {
     private int leftBits = 0;
     private int leftSoFar = 0;
     private int leftSize = 0;
     private int charatcer = 0;
     private boolean needMore = false;
 
     // TODO consider maybe array of char instead of string builder? then return new String(array)?
     // prescan for size
     protected List<StringBuilder32result = new ArrayList<StringBuilder32>();
     private int lastSpecial = -1;
     
 	public int getCharacter() {
 		return this.;
 	}
 	
 	public int getLastSpecialCharacter() {
 		return this.;
 	}
 
 	public boolean needsMore() {
 		return (this. && (this. != 0));
 	}
 
 	public int getCharacterAndReset() {
         int tchar = ;
         this.reset();
         return tchar;
 	}
 
 	public void reset() {
 		this. = 0;
 		this. = 0;
 		this. = 0;
 		this. = 0;
 		this. = false;
 		this. = -1;
 	}
 
 	public CharSequence processBytes(byte[] values) {
 		if (values == null)
 			return null;
 		
         return this.processBytes(valuesvalues.length);
 	}
 
 	public CharSequence processBytes(byte[] valuesint len) {
 		if (values == null)
 			return null;
 		
         StringBuilder32 sb = new StringBuilder32();
 
         try {
 	        for (int pos = 0; pos < lenpos++) 
 	            if (!this.readByteNeedMore(values[pos], true))
 	                sb.append(this.getCharacterAndReset());
         }
         catch (Exception x) {
         	// TODO
         }
         
         return sb;
 	}
 
 	public List<StringBuilder32processBytesSplit(ByteBuffer bufferSpecial partSep) {
         StringBuilder32 sb = null;
         
         // continue to build up strings from last call
        if (this..size() > 0)
        	sb = this..get(this..size() - 1);
        else {
        	sb = new StringBuilder32();
        	this..add(sb);
        }
        
        this. = -1;
        
        try {
        	while (buffer.hasRemaining()) {
	            if (this.readByteNeedMore(buffer.get(), true))
	            	continue;
	        
	            if (this. != -1) {
	            	if (partSep.getCode() != this.) {
	                    List<StringBuilder32res = this.;
	            		this. = new ArrayList<StringBuilder32>();		
	            		return res;
	            	}
                	sb = new StringBuilder32();
                	this..add(sb);
	                this.reset();
	                continue;
	            }
	            
	            sb.append(this.getCharacterAndReset());
	        }	        
        }
        catch (Exception x) {
        	// TODO
        }
    	
    	return null;
	}
	// look for string from buffer, up to the char.  no special chars allowed 
	public StringBuilder32 processBytesUntil(ByteBuffer bufferint partChar) {
        StringBuilder32 sb = null;
        
        // continue to build up strings from last call
        if (this..size() > 0)
        	sb = this..get(this..size() - 1);
        else {
        	sb = new StringBuilder32();
        	this..add(sb);
        }
        
        this. = -1;
        
        try {
        	while (buffer.hasRemaining()) {
	            if (this.readByteNeedMore(buffer.get(), true))
	            	continue;
	        
	            // ignore special chars and CR
	            if ((this. != -1) || (this. == '\r')) {
	                this. = -1;
	                continue;
	            }
            
            	if (partChar == this.) {
            		this. = new ArrayList<StringBuilder32>();		
            		return sb;
            	}
	            
	            sb.append(this.getCharacterAndReset());
	        }	        
        }
        catch (Exception x) {
        	// TODO
        }
    	
    	return null;
	}
	public StringBuilder32 processBytesUntil(ByteBuffer bufferSpecial partSep) {
        StringBuilder32 sb = null;
        
        // continue to build up strings from last call
        if (this..size() > 0)
        	sb = this..get(this..size() - 1);
        else {
        	sb = new StringBuilder32();
        	this..add(sb);
        }
        
        this. = -1;
        
        try {
        	while (buffer.hasRemaining()) {
	            if (this.readByteNeedMore(buffer.get(), true))
	            	continue;
	        
	            if (this. != -1) {
	            	if (partSep.getCode() == this.) {
	            		this. = new ArrayList<StringBuilder32>();		
	            		return sb;
	            	}
	            }
	            
	            sb.append(this.getCharacterAndReset());
	        }	        
        }
        catch (Exception x) {
        	// TODO
        }
    	
    	return null;
	}
		if (buffer == null)
			return null;
        StringBuilder32 sb = null;
        
        // continue to build up strings from last call
        if (this..size() > 0)
        	sb = this..get(this..size() - 1);
        else {
        	sb = new StringBuilder32();
        	this..add(sb);
        }
        
        this. = -1;
        
        try {
        	while (buffer.hasRemaining()) {
	            if (this.readByteNeedMore(buffer.get(), true))
	            	continue;
	        
	            if (this. != -1) {
            		this. = new ArrayList<StringBuilder32>();		
            		return sb;
	            }
	            
	            sb.append(this.getCharacterAndReset());
	        }	        
        }
        catch (Exception x) {
        	// TODO
        }
    	
    	return null;
	}
		if (buffer == null)
			return null;
        StringBuilder32 sb = null;
        
        // continue to build up strings from last call
        if (this..size() > 0)
        	sb = this..get(this..size() - 1);
        else {
        	sb = new StringBuilder32();
        	this..add(sb);
        }
        
        this. = -1;
        
        try {
        	while (buffer.readableBytes() > 0) {
	            if (this.readByteNeedMore(buffer.readByte(), true))
	            	continue;
	        
	            if (this. != -1) {
            		this. = new ArrayList<StringBuilder32>();		
            		return sb;
	            }
	            
	            sb.append(this.getCharacterAndReset());
	        }	        
        }
        catch (Exception x) {
        	// TODO
        }
    	
    	return null;
	}
	/*
	public boolean processBytesUntil(byte[] values, int offset, int len, Special sectionSep) {
        this.lastSpecial = -1;
        
        try {
	        for (int pos = offset; pos < len; pos++) { 
	            if (this.readByteNeedMore(values[pos], true))
	            	return false;
	        
	            if (this.lastSpecial != -1) {
	            	if (sectionSep.getCode() == this.lastSpecial)
	            		return true;
	            	
	                this.lastSpecial = -1;
	            }
	        }	               
        }
        catch (Exception x) {
        	// TODO
        }
        
    	return false;
	}
	*/
    private void processFirstByte(int chboolean safethrows Exception {
        if (ch < (int)0x80) {
        	// unsafe characters get turned into spaces
            if (safe && ((ch < (int)0x9) || ((ch < (int)0x20) && (ch > (int)0xD)) || (ch == (int)0x7F))) {
            	this. = ch;
            	ch = (int)0x20;
            }
            
            this. = (int)ch;
            return;
        }
        this. = true;
        if ((ch & (int)0xE0) == (int)0xC0) {
            // Double-byte UTF-8 character.
        	this. = (ch & (int)0x1F);
        	this. = 1;
        	this. = 2;
            return;
        }
        if ((ch & (int)0xF0) == (int)0xE0) {
            // Three-byte UTF-8 character.
        	this. = (ch & (int)0x0F);
        	this. = 1;
        	this. = 3;
            return;
        }
        if ((ch & (int)0xF8) == (int)0xF0) {
            // Four-byte UTF-8 character.
        	this. = (ch & (int)0x07);
        	this. = 1;
        	this. = 4;
            return;
        }
        if ((ch & (int)0xFC) == (int)0xF8) {
            // Five-byte UTF-8 character.
        	this. = (ch & (int)0x03);
        	this. = 1;
        	this. = 5;
            return;
        }
        if ((ch & (int)0xFE) == (int)0xFC) {
            // Six-byte UTF-8 character.
        	this. = (ch & (int)0x03);
        	this. = 1;
        	this. = 6;
            return;
        }
        throw new Exception("UTF decoder error: Invalid UTF-8 start character.");
    }
	public boolean readByteNeedMore(byte bchboolean safethrows Exception {
		int ch = 0xFF & bch;
        // read first byte
        if (this. == 0) {
        	this.processFirstByte(chsafe);
            return this.;
        }
        // Process an extra byte in a multi-byte sequence.
        if ((ch & (int)0xC0) == (int)0x80) {
        	this. = ((this. << 6) | (ch & (int)0x3F));
            if (++this. >= this.) {
                // We have a complete character now.
                if (this. < (int)0x10000) {
                    // is it an overlong ?
                    boolean overlong = false;
                    switch (this.) {
                        case 2:
                            overlong = (this. <= 0x7F);
                            break;
                        case 3:
                            overlong = (this. <= 0x07FF);
                            break;
                        case 4:
                            overlong = (this. <= 0xFFFF);
                            break;
                        case 5:
                            overlong = (this. <= 0x1FFFFF);
                            break;
                        case 6:
                            overlong = (this. <= 0x03FFFFFF);
                            break;
                    }
                    if (overlong)
                        throw new Exception("UTF decoder error: Invalid UTF-8 sequence, overlong value.");
                    else if ((this. & 0xF800) == 0xD800)
                        throw new Exception("UTF decoder error: Invalid UTF-8 sequence, surrogate characters not allowed.");
                    else
                    	this. = this.;
                }
                else if (this. < (int)0x110000)
                	this. = this.;
                else
                    throw new Exception("UTF decoder error: Invalid UTF-8 sequence.");
                this. = 0;  // signal end
                return false;
            }
        }
        else
            throw new Exception("UTF decoder error: Invalid UTF-8 sequence.");
        return true;
	}
	// must pass in a complete buffer
	public static CharSequence decode(byte[] buffer) {
		if (buffer == null)
			return null;
		Utf8Decoder decoder = new Utf8Decoder();
		return decoder.processBytes(buffer);
	}
	// TODO by directly reading the byte buf, no copy
	public static CharSequence decode(ByteBuf buffer) {
		byte[] dest = new byte[buffer.readableBytes()];
		buffer.readBytes(dest);
		return Utf8Decoder.decode(dest);		
	}
	// TODO by directly reading the byte buf, no copy
	public static CharSequence decode(ByteBuf bufferint max) {
		byte[] dest = new byte[Math.min(buffer.readableBytes(), max)];
		buffer.readBytes(dest);
		return Utf8Decoder.decode(dest);		
	}
New to GrepCode? Check out our FAQ X