
static int gd_EntityToUniChar(const char *str, uint32_t *chPtr){
	// str is the UTF8 next character pointer, or a pointer to a string of 4 different kinds of html entity notation
	// chPtr is the int for the result
	// return value is the offset from str to the char for the next search to start
	// function falls through and returns 0 if no valid entity detected, leaving chPtr alone.
	// HTML4.0/5.0 entities in hexadecimal form (e.g. &#x00021; and &#X00021;), in decimal form (e.g. &#33;),  or in string form (e.g. &excl;)
	char entity_name_buf[ENTITY_NAME_LENGTH_MAX+1];
	uint32_t n = 0;
	uint32_t i = 0;
	uint32_t b0 = (uint8_t)str[i++];
	static const uint8_t first_digit = '0';
	static const uint8_t bound_low_digit = '/';
	static const uint8_t bound_hi_digit = ':';
	static const uint8_t first_ucase = 'A';
	static const uint8_t bound_low_ucase = '@';
	static const uint8_t bound_hi_ucase = 'G';
	static const uint8_t first_lcase = 'a';
	static const uint8_t bound_low_lcase = '`';
	static const uint8_t bound_hi_lcase = 'g';
	static const uint8_t prefix0 = '&';
	static const uint8_t prefix1 = '#';
	static const uint8_t prefix2 = 'x';
	static const uint8_t prefix3 = 'X';
	static const uint8_t suffix = ';';
	static const uint8_t ten = 10;

	if(b0 != prefix0)
		return 0;

	b0=(uint8_t)str[i++];
	if(b0 == prefix1){
		//hex or decimal
		b0=(uint8_t)str[i++];
		if(b0 == prefix2 || b0 == prefix3){
			//is hex
			while(i<ENTITY_HEX_LENGTH_MAX+3){
				b0=(uint8_t)str[i++];
				if(b0 > bound_low_digit && b0 < bound_hi_digit)
					b0 -= first_digit + ten;
				else if(b0 > bound_low_ucase && b0 < bound_hi_ucase)
					b0 -= first_ucase + ten;
				else if(b0 > bound_low_lcase && b0 < bound_hi_lcase)
					b0 -= first_lcase + ten;
				else
					break;
				n = n * 16 + b0;
			}
			if(b0 == suffix){
				*chPtr = n;
				return ++i;
			}
		}else{
			//is dec
			while(i<ENTITY_DEC_LENGTH_MAX+2){
				if(b0 > bound_low_digit && b0 < bound_hi_digit)
					n = n * ten + b0 - first_digit;
				else
					break;

				b0=(uint8_t)str[i++];
			}
			if(b0 == suffix){
				*chPtr = n;
				return ++i;
			}
		}
	}else{
		//string format alphanumeric
		//copy str into buffer untill '\0' or ;
		while(i<ENTITY_NAME_LENGTH_MAX+1){
			//not an entity
			if(b0 == '\0')
				return 0;
			entity_name_buf[n++] = str[i++];
			//have complete copy
			if(b0 == suffix){
				entity_name_buf[n] = '\0';
				break;
			}
			b0=(uint8_t)str[i];
		}
		//not an entity, too long
		if(b0 != suffix)
			return 0;
		while(n < NR_OF_ENTITIES){
			if(strcmp((const char *)entities[n].name, (const char *)entity_name_buf) == 0){
				*chPtr = entities[n].value;
				return ++i;
			}
			n++;
		}
	}
	//no match
	return 0;
}
