1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-08-20 20:54:47 -04:00

[qs_parse] Added qs_parse code from https://github.com/bartgrantham/qs_parse

This commit is contained in:
Witold Filipczyk 2021-12-29 21:01:47 +01:00
parent ae6bfdd4dd
commit edddb70200
10 changed files with 665 additions and 1 deletions

View File

@ -3,6 +3,8 @@ include $(top_builddir)/Makefile.config
INCLUDES += $(GNUTLS_CFLAGS) $(OPENSSL_CFLAGS)
SUBDIRS = qs_parse
OBJS-unless$(CONFIG_SMALL) += fastfind.o
OBJS-$(CONFIG_CSS) += scanner.o
OBJS-$(CONFIG_DEBUG) += memdebug.o

View File

@ -1,4 +1,4 @@
#INCLUDES += $(GNUTLS_CFLAGS) $(OPENSSL_CFLAGS)
subdir('qs_parse')
if not conf_data.get('CONFIG_SMALL')
srcs += files('fastfind.c')

19
src/util/qs_parse/LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2010 Bart Grantham
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,6 @@
top_builddir=../../..
include $(top_builddir)/Makefile.config
OBJS = qs_parse.o
include $(top_srcdir)/Makefile.lib

View File

@ -0,0 +1,66 @@
# qs_parse #
## Description ##
A set of simple and easy functions for parsing URL query strings, such as
those generated in an HTTP GET form submission.
## How to Use ##
These qs_* functions can be used in two different ways:
`qs_parse()`/`qs_k2v()`: A faster version that requires a pre-processing stage
and **is destructive to the query string**
* Better for repeated lookups of k/v pairs
* Does all decoding/processing in-place, so no memory copying
* Requires an array of pointers to strings to be passed to the preprocessing stage
* Cannot be used where the query string is const
`qs_scanvalue()`: A slower version that will scan for the given key and will
decode the value into a user-provided string
* Doesn't alter the query string so can be used where it is const, or cannot be altered
* Only needs a user-passed char string for copying into
* Scans the entire qs on each call, so isn't as fast as qs_k2v()
Since `qs_parse()`/`qs_k2v()` alters the query string that is passed to it in a way
that defeats `qs_scanvalue()`, do not mix these two methods (or if you must,
either don't call `qs_scanvalue()` after a call to `qs_parse()` or be sure make
a copy of the query string beforehand)
[note: speed comparisons will be more relevant when the sorting the k/v pairs
code is implemented]
## Installation ##
All you really need is qs_parse.h and qs_parse.c. I've included my test program
("qs_test.c") and an example program that shows how to use these functions
("qs_example.c"). Also included is a quick Makefile. If you want to see it
come to life just get all the files and:
# make
# ./qs_example
## Bugs, etc. ##
Please let me know if you find any, or if you have license-friendly enhancements
to add.
## License ##
MIT License. See ./LICENSE or <http://www.opensource.org/licenses/mit-license.php>
Few things are more enjoyable than the knowledge that you've helped another
person. If you do use these functions for anything, I'd love to hear about it:
<bart@bartgrantham.com>
Enjoy!
-Bart

View File

@ -0,0 +1 @@
srcs += files('qs_parse.c')

View File

@ -0,0 +1,106 @@
/* Licensed under the MIT License by Bart Grantham, 2010. See ./LICENSE or
* http://www.opensource.org/licenses/mit-license.php
*/
#include <stdio.h>
#include "qs_parse.h"
#define NUMKVPAIRS 256
#define VALSIZE 256
int main(int argc, char * argv[])
{
int i;
char * kvpairs[NUMKVPAIRS];
char value[VALSIZE];
char * value_ptr;
unsigned char r, g, b, a;
double dr, dg, db, da;
char getstring[] = "scheme://username:password@domain:port/path?foo=bar&frob&baz=quux&color=09FA#anchor";
printf("Our GET string is %s\n\n", getstring);
/********************************************************/
/* The easy, but not as efficient way: qs_scanvalue() */
/********************************************************/
if ( qs_scanvalue("foo", getstring, value, sizeof(value)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "foo", value);
else
printf("Key %s is NOT set\n", "foo");
if ( qs_scanvalue("baz", getstring, value, sizeof(value)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "baz", value);
else
printf("Key %s is NOT set\n", "baz");
if ( qs_scanvalue("frob", getstring, value, sizeof(value)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "frob", value);
else
printf("Key %s is NOT set\n", "frob");
if ( qs_scanvalue("blah", getstring, value, sizeof(value)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "blah", value);
else
printf("Key %s is NOT set\n", "blah");
if ( qs_scanvalue("color", getstring, value, sizeof(value)) != NULL )
{
printf("Key %s is set, and the value is: \"%s\"\n", "color", value);
if ( hex2ccolor(value, &r, &g, &b, &a) != 0 && hex2dcolor(value, &dr, &dg, &db, &da) != 0 )
{
printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a);
printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da);
}
else
printf(" \"%s\" NOT successfully decoded\n", "color");
}
else
printf("Key %s is NOT set\n", "color");
printf("\n");
/*************************************************************************/
/* The faster, more complex, and destructive way: qs_parse() / qs_k2v() */
/*************************************************************************/
/* ***THIS WILL ALTER getstring*** */
i = qs_parse(getstring, kvpairs, 256);
/* At this point qs_scanvalue() will no longer work with this query string */
if ( (value_ptr = qs_k2v("foo", kvpairs, i)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "foo", value_ptr);
else
printf("Key %s is NOT set\n", "foo");
if ( (value_ptr = qs_k2v("baz", kvpairs, i)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "baz", value_ptr);
else
printf("Key %s is NOT set\n", "baz");
if ( (value_ptr = qs_k2v("frob", kvpairs, i)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "frob", value_ptr);
else
printf("Key %s is NOT set\n", "frob");
if ( (value_ptr = qs_k2v("blah", kvpairs, i)) != NULL )
printf("Key %s is set, and the value is: \"%s\"\n", "blah", value_ptr);
else
printf("Key %s is NOT set\n", "blah");
if ( (value_ptr = qs_k2v("color", kvpairs, i)) != NULL )
{
printf("Key %s is set, and the value is: \"%s\"\n", "color", value_ptr);
if ( hex2ccolor(value_ptr, &r, &g, &b, &a) != 0 && hex2dcolor(value_ptr, &dr, &dg, &db, &da) != 0 )
{
printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a);
printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da);
}
else
printf(" \"%s\" NOT successfully decoded\n", "color");
}
else
printf("Key %s is NOT set\n", "color");
return 0;
}

View File

@ -0,0 +1,272 @@
#include "qs_parse.h"
#include <stdio.h>
// TODO: implement sorting of the qs_kv array; for now ensure it's not compiled
#undef _qsSORTING
// isxdigit _is_ available in <ctype.h>, but let's avoid another header instead
#define ISHEX(x) ((((x)>='0'&&(x)<='9') || ((x)>='A'&&(x)<='F') || ((x)>='a'&&(x)<='f')) ? 1 : 0)
#define HEX2DEC(x) (((x)>='0'&&(x)<='9') ? (x)-48 : ((x)>='A'&&(x)<='F') ? (x)-55 : ((x)>='a'&&(x)<='f') ? (x)-87 : 0)
#define ISQSCHR(x) ((((x)=='=')||((x)=='#')||((x)=='&')||((x)=='\0')) ? 0 : 1)
int qs_strncmp(const char * s, const char * qs, register size_t n)
{
int i=0;
register unsigned char u1, u2, unyb, lnyb;
while(n-- > 0)
{
u1 = (unsigned char) *s++;
u2 = (unsigned char) *qs++;
if ( ! ISQSCHR(u1) ) { u1 = '\0'; }
if ( ! ISQSCHR(u2) ) { u2 = '\0'; }
if ( u1 == '+' ) { u1 = ' '; }
if ( u1 == '%' ) // easier/safer than scanf
{
unyb = (unsigned char) *s++;
lnyb = (unsigned char) *s++;
if ( ISHEX(unyb) && ISHEX(lnyb) )
u1 = (HEX2DEC(unyb) * 16) + HEX2DEC(lnyb);
else
u1 = '\0';
}
if ( u2 == '+' ) { u2 = ' '; }
if ( u2 == '%' ) // easier/safer than scanf
{
unyb = (unsigned char) *qs++;
lnyb = (unsigned char) *qs++;
if ( ISHEX(unyb) && ISHEX(lnyb) )
u2 = (HEX2DEC(unyb) * 16) + HEX2DEC(lnyb);
else
u2 = '\0';
}
if ( u1 != u2 )
return u1 - u2;
if ( u1 == '\0' )
return 0;
i++;
}
if ( ISQSCHR(*qs) )
return -1;
else
return 0;
}
int qs_parse(char * qs, char * qs_kv[], int qs_kv_size)
{
int i, j;
char * substr_ptr;
for(i=0; i<qs_kv_size; i++) qs_kv[i] = NULL;
// find the beginning of the k/v substrings
if ( (substr_ptr = strchr(qs, '?')) != NULL )
substr_ptr++;
else
substr_ptr = qs;
i=0;
while(i<qs_kv_size)
{
qs_kv[i] = substr_ptr;
j = strcspn(substr_ptr, "&");
if ( substr_ptr[j] == '\0' ) { break; }
substr_ptr += j + 1;
i++;
}
i++; // x &'s -> means x iterations of this loop -> means *x+1* k/v pairs
// we only decode the values in place, the keys could have '='s in them
// which will hose our ability to distinguish keys from values later
for(j=0; j<i; j++)
{
substr_ptr = qs_kv[j] + strcspn(qs_kv[j], "=&#");
if ( substr_ptr[0] == '&' ) // blank value: skip decoding
substr_ptr[0] = '\0';
else
qs_decode(++substr_ptr);
}
#ifdef _qsSORTING
// TODO: qsort qs_kv, using qs_strncmp() for the comparison
#endif
return i;
}
int qs_decode(char * qs)
{
int i=0, j=0;
while( ISQSCHR(qs[j]) )
{
if ( qs[j] == '+' ) { qs[i] = ' '; }
else if ( qs[j] == '%' ) // easier/safer than scanf
{
if ( ! ISHEX(qs[j+1]) || ! ISHEX(qs[j+2]) )
{
qs[i] = '\0';
return i;
}
qs[i] = (HEX2DEC(qs[j+1]) * 16) + HEX2DEC(qs[j+2]);
j+=2;
}
else
{
qs[i] = qs[j];
}
i++; j++;
}
qs[i] = '\0';
return i;
}
char * qs_k2v(const char * key, char * qs_kv[], int qs_kv_size)
{
int i;
size_t key_len, skip;
key_len = strlen(key);
#ifdef _qsSORTING
// TODO: binary search for key in the sorted qs_kv
#else // _qsSORTING
for(i=0; i<qs_kv_size; i++)
{
// we rely on the unambiguous '=' to find the value in our k/v pair
if ( qs_strncmp(key, qs_kv[i], key_len) == 0 )
{
skip = strcspn(qs_kv[i], "=");
if ( qs_kv[i][skip] == '=' )
skip++;
// return (zero-char value) ? ptr to trailing '\0' : ptr to value
return qs_kv[i] + skip;
}
}
#endif // _qsSORTING
return NULL;
}
char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len)
{
int i, key_len;
char * tmp;
// find the beginning of the k/v substrings
if ( (tmp = strchr(qs, '?')) != NULL )
qs = tmp + 1;
key_len = strlen(key);
while(qs[0] != '#' && qs[0] != '\0')
{
if ( qs_strncmp(key, qs, key_len) == 0 )
break;
qs += strcspn(qs, "&") + 1;
}
if ( qs[0] == '\0' ) return NULL;
qs += strcspn(qs, "=&#");
if ( qs[0] == '=' )
{
qs++;
i = strcspn(qs, "&=#");
strncpy(val, qs, (val_len-1)<(i+1) ? (val_len-1) : (i+1));
qs_decode(val);
}
else
{
if ( val_len > 0 )
val[0] = '\0';
}
return val;
}
int hex2dcolor(char * color, double * r, double * g, double * b, double * a)
{
int i, j;
if ( color == NULL ) return 0;
i = strlen(color);
if ( i != 8 && i != 6 && i != 4 && i != 3 ) return 0;
for(j=0; j<i; j++) if ( ! ISHEX(color[j]) ) return 0;
switch(i)
{
// (H*16+H)/255 == H*17/255 == H/15
case 3:
*r = HEX2DEC(color[0]) / 15.0;
*g = HEX2DEC(color[1]) / 15.0;
*b = HEX2DEC(color[2]) / 15.0;
break;
case 4:
*r = HEX2DEC(color[0]) / 15.0;
*g = HEX2DEC(color[1]) / 15.0;
*b = HEX2DEC(color[2]) / 15.0;
*a = HEX2DEC(color[3]) / 15.0;
break;
case 6:
*r = ((HEX2DEC(color[0]) * 16) + HEX2DEC(color[1])) / 255.0;
*g = ((HEX2DEC(color[2]) * 16) + HEX2DEC(color[3])) / 255.0;
*b = ((HEX2DEC(color[4]) * 16) + HEX2DEC(color[5])) / 255.0;
break;
case 8:
*r = ((HEX2DEC(color[0]) * 16) + HEX2DEC(color[1])) / 255.0;
*g = ((HEX2DEC(color[2]) * 16) + HEX2DEC(color[3])) / 255.0;
*b = ((HEX2DEC(color[4]) * 16) + HEX2DEC(color[5])) / 255.0;
*a = ((HEX2DEC(color[6]) * 16) + HEX2DEC(color[7])) / 255.0;
break;
}
return i;
}
int hex2ccolor(char * color, unsigned char * r, unsigned char * g, unsigned char * b, unsigned char * a)
{
int i, j;
if ( color == NULL ) return 0;
i = strlen(color);
if ( i != 8 && i != 6 && i != 4 && i != 3 ) return 0;
for(j=0; j<i; j++) if ( ! ISHEX(color[j]) ) return 0;
switch(i)
{
// (H*16+H) == H*17
case 3:
*r = HEX2DEC(color[0]) * 17;
*g = HEX2DEC(color[1]) * 17;
*b = HEX2DEC(color[2]) * 17;
break;
case 4:
*r = HEX2DEC(color[0]) * 17;
*g = HEX2DEC(color[1]) * 17;
*b = HEX2DEC(color[2]) * 17;
*a = HEX2DEC(color[3]) * 17;
break;
case 6:
*r = (HEX2DEC(color[0]) * 16) + HEX2DEC(color[1]);
*g = (HEX2DEC(color[2]) * 16) + HEX2DEC(color[3]);
*b = (HEX2DEC(color[4]) * 16) + HEX2DEC(color[5]);
break;
case 8:
*r = (HEX2DEC(color[0]) * 16) + HEX2DEC(color[1]);
*g = (HEX2DEC(color[2]) * 16) + HEX2DEC(color[3]);
*b = (HEX2DEC(color[4]) * 16) + HEX2DEC(color[5]);
*a = (HEX2DEC(color[6]) * 16) + HEX2DEC(color[7]);
break;
}
return i;
}

View File

@ -0,0 +1,54 @@
#include <string.h>
#ifndef BG_QSPARSE_H_
#define BG_QSPARSE_H_
#ifdef __cplusplus
extern "C" {
#endif
/* string.h needed for strcspn() and strlen() */
/* Similar to strncmp, but handles URL-encoding for either string */
int qs_strncmp(const char * s, const char * qs, register size_t n);
/* Finds the beginning of each key/value pair and stores a pointer in qs_kv.
* Also decodes the value portion of the k/v pair *in-place*. In a future
* enhancement it will also have a compile-time option of sorting qs_kv
* alphabetically by key. */
int qs_parse(char * qs, char * qs_kv[], int qs_kv_size);
/* Used by qs_parse to decode the value portion of a k/v pair */
int qs_decode(char * qs);
/* Looks up the value according to the key on a pre-processed query string
* A future enhancement will be a compile-time option to look up the key
* in a pre-sorted qs_kv array via a binary search. */
char * qs_k2v(const char * key, char * qs_kv[], int qs_kv_size);
/* Non-destructive lookup of value, based on key. User provides the
* destinaton string and length. */
char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len);
/* Converts the 3 or 6 (RGB), or 4 or 8 (RGBA) hex chars in the color string
* to double values in the range 0.0-1.0. Returns the number of converted
* chars. */
int hex2dcolor(char * color, double * r, double * g, double * b, double * a);
/* Converts the 3/6 (RGB) or 4/8 (RGBA) hex chars in the color string to
* values spanning the full range of unsigned char, 0-255. Returns the
* number of converted chars. */
int hex2ccolor(char * color, unsigned char * r, unsigned char * g, unsigned char * b, unsigned char * a);
#ifdef __cplusplus
}
#endif
#endif // BG_QSPARSE_H_

138
src/util/qs_parse/qs_test.c Normal file
View File

@ -0,0 +1,138 @@
/* Licensed under the MIT License by Bart Grantham, 2010. See ./LICENSE or
* http://www.opensource.org/licenses/mit-license.php
*/
#include <stdio.h>
#include "qs_parse.h"
int main(int argc, char * argv[])
{
int i,j;
char * kvpairs[256];
char value[256];
unsigned char r, g, b, a;
double dr, dg, db, da;
char foo[] = "foo";
char foobar[] = "foobar";
char foo_enc[] = "fo%6f";
char foobar_enc[] = "fo%6fbar";
char foo_mal[] = "fo%6";
char foo_mal2[] = "foo%6";
char foo_end[] = "foo&";
/* This test query string includes:
* - URL encoded values (percent-encoded and +-as-space)
* - URL encoded keys (percent-encoded +-as-space)
* - Incorrectly encoded values (FFFFFF%f)
* - A trailing anchor
* - null (0-char) values
*
* I should add:
* - leading URL junk (before a ?)
*/
char getstring[] = "FUNNYJUNK://@?t%65xt=bleh+bleh%20!&font=Vera.ttf&size=40.3&fg=Fa98BF44%f&debug1&bg=0C0&color=FF4455F&hash=24a%62cdef%7a&rot=123.1&tr+i=cky&debug2#don'tparseme,bro";
printf("Testing qs_* functions\n");
printf(" Testing qs_strncmp():\n");
printf(" %s, %s, 3 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 3));
printf(" %s, %s, 4 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 4));
printf(" %s, %s, 99 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 99));
printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 3));
printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 4));
printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 99));
printf(" %s, %s, 3 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 3));
printf(" %s, %s, 4 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 4));
printf(" %s, %s, 99 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 99));
printf(" %s, %s, 3 should be 0 : %d\n", foo, foobar, qs_strncmp(foo, foobar, 3));
printf(" %s, %s, 4 should be - : %d\n", foo, foobar, qs_strncmp(foo, foobar, 4));
printf(" %s, %s, 99 should be - : %d\n", foo, foobar, qs_strncmp(foo, foobar, 99));
printf(" %s, %s, 3 should be 0 : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 3));
printf(" %s, %s, 4 should be - : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 4));
printf(" %s, %s, 99 should be - : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 99));
printf(" %s, %s, 3 should be 0 : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 3));
printf(" %s, %s, 4 should be - : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 4));
printf(" %s, %s, 99 should be - : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 99));
printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 2));
printf(" %s, %s, 3 should be + : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 3));
printf(" %s, %s, 99 should be + : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 99));
printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 2));
printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 3));
printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 4));
printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 99));
printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 2));
printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 3));
printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 4));
printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 99));
printf("\n");
printf(" Testing qs_scanvalue() with query string:\n %s\n", getstring);
printf(" The following should say \"bleh bleh !\" : \"%s\"\n", qs_scanvalue("text", getstring, value, 256));
printf(" The following should say \"Vera.ttf\" : \"%s\"\n", qs_scanvalue("font", getstring, value, 256));
printf(" The following should say \"40.3\" : \"%s\"\n", qs_scanvalue("size", getstring, value, 256));
printf(" The following should say \"Fa98BF44\" : \"%s\"\n", qs_scanvalue("fg", getstring, value, 256));
printf(" The following should say \"\" : \"%s\"\n", qs_scanvalue("debug1", getstring, value, 256));
printf(" The following should say \"0C0\" : \"%s\"\n", qs_scanvalue("bg", getstring, value, 256));
printf(" The following should say \"FF4455F\" : \"%s\"\n", qs_scanvalue("color", getstring, value, 256));
printf(" The following should say \"24abcdefz\" : \"%s\"\n", qs_scanvalue("hash", getstring, value, 256));
printf(" The following should say \"123.1\" : \"%s\"\n", qs_scanvalue("rot", getstring, value, 256));
printf(" The following should say \"cky\" : \"%s\"\n", qs_scanvalue("tr i", getstring, value, 256));
printf(" The following should say \"\" : \"%s\"\n", qs_scanvalue("debug2", getstring, value, 256));
printf("\n");
printf(" Running qs_parse() against query string (also exersizes qs_decode()):\n %s\n", getstring);
i = qs_parse(getstring, kvpairs, 256);
printf(" I should have found 11 k/v substrings, actually found: %d\n", i);
printf("\n");
printf(" Testing qs_k2v() against our kv pair substrings:\n");
printf(" The following should say \"bleh bleh !\" : \"%s\"\n", qs_k2v("text", kvpairs, i));
printf(" The following should say \"Vera.ttf\" : \"%s\"\n", qs_k2v("font", kvpairs, i));
printf(" The following should say \"40.3\" : \"%s\"\n", qs_k2v("size", kvpairs, i));
printf(" The following should say \"Fa98BF44\" : \"%s\"\n", qs_k2v("fg", kvpairs, i));
printf(" The following should say \"\" : \"%s\"\n", qs_k2v("debug1", kvpairs, i));
printf(" The following should say \"0C0\" : \"%s\"\n", qs_k2v("bg", kvpairs, i));
printf(" The following should say \"FF4455F\" : \"%s\"\n", qs_k2v("color", kvpairs, i));
printf(" The following should say \"24abcdefz\" : \"%s\"\n", qs_k2v("hash", kvpairs, i));
printf(" The following should say \"123.1\" : \"%s\"\n", qs_k2v("rot", kvpairs, i));
printf(" The following should say \"cky\" : \"%s\"\n", qs_k2v("tr i", kvpairs, i));
printf(" The following should say \"\" : \"%s\"\n", qs_k2v("debug2", kvpairs, i));
printf("\n");
printf(" Testing hex2ccolor() and hex2dcolor() with fg (\"%s\"):\n", qs_k2v("fg", kvpairs, i));
j = hex2ccolor(qs_k2v("fg", kvpairs, i), &r, &g, &b, &a);
printf(" hex2ccolor() should have decoded 8 chars, r/g/b/a should be 250/152/191/68 : %d chars decoded, r/g/b/a is %d/%d/%d/%d\n", j, r, g, b, a);
j = hex2dcolor(qs_k2v("fg", kvpairs, i), &dr, &dg, &db, &da);
printf(" hex2dcolor() should have decoded 8 chars, r/g/b/a should be 0.98/0.60/0.75/0.27 : %d chars decoded, r/g/b/a is %.2f/%.2f/%.2f/%.2f\n", j, dr, dg, db, da);
printf(" Testing hex2ccolor() and hex2dcolor() with bg (\"%s\"):\n", qs_k2v("bg", kvpairs, i));
j = hex2ccolor(qs_k2v("bg", kvpairs, i), &r, &g, &b, &a);
printf(" hex2ccolor() should have decoded 3 chars, r/g/b should be 0/204/0 : %d chars decoded, r/g/b is %d/%d/%d\n", j, r, g, b);
j = hex2dcolor(qs_k2v("bg", kvpairs, i), &dr, &dg, &db, &da);
printf(" hex2dcolor() should have decoded 3 chars, r/g/b should be 0.00/0.80/0.00 : %d chars decoded, r/g/b is %.2f/%.2f/%.2f\n", j, dr, dg, db);
printf(" Testing hex2ccolor() and hex2dcolor() with color (\"%s\"):\n", qs_k2v("color", kvpairs, i));
j = hex2ccolor(qs_k2v("color", kvpairs, i), &r, &g, &b, &a);
printf(" hex2ccolor() should have decoded 0 chars : %d chars decoded\n", j);
j = hex2dcolor(qs_k2v("color", kvpairs, i), &dr, &dg, &db, &da);
printf(" hex2dcolor() should have decoded 0 chars : %d chars decoded\n", j);
/*
print
if ( qs_scanvalue("color", getstring, value, sizeof(value)) != NULL )
{
printf("Key %s is set, and the value is: \"%s\"\n", "color", value);
if ( hex2ccolor(value, &r, &g, &b, &a) != 0 && hex2dcolor(value, &dr, &dg, &db, &da) != 0 )
{
printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a);
printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da);
}
else
printf(" \"%s\" NOT successfully decoded\n", "color");
}
*/
return 0;
}