├── Makefile ├── LICENSE ├── qs_parse.h ├── README.md ├── qs_example.c ├── qs_parse.c └── qs_test.c /Makefile: -------------------------------------------------------------------------------- 1 | # Quick and dirty Makefile for qs_parse 2 | 3 | ALL = qs_parse.o qs_test qs_example 4 | 5 | all: $(ALL) 6 | 7 | clean: 8 | rm -f $(ALL) 9 | 10 | qs_test: qs_parse.o qs_test.c 11 | $(CC) qs_parse.o qs_test.c -o $@ 12 | 13 | qs_example: qs_parse.o qs_example.c 14 | $(CC) qs_parse.o qs_example.c -o $@ 15 | 16 | qs_parse.o: qs_parse.h 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Bart Grantham 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /qs_parse.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef BG_QSPARSE_H_ 4 | #define BG_QSPARSE_H_ 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /* string.h needed for strcspn() and strlen() */ 11 | 12 | 13 | /* Similar to strncmp, but handles URL-encoding for either string */ 14 | int qs_strncmp(const char * s, const char * qs, register size_t n); 15 | 16 | 17 | /* Finds the beginning of each key/value pair and stores a pointer in qs_kv. 18 | * Also decodes the value portion of the k/v pair *in-place*. In a future 19 | * enhancement it will also have a compile-time option of sorting qs_kv 20 | * alphabetically by key. */ 21 | int qs_parse(char * qs, char * qs_kv[], int qs_kv_size); 22 | 23 | 24 | /* Used by qs_parse to decode the value portion of a k/v pair */ 25 | int qs_decode(char * qs); 26 | 27 | 28 | /* Looks up the value according to the key on a pre-processed query string 29 | * A future enhancement will be a compile-time option to look up the key 30 | * in a pre-sorted qs_kv array via a binary search. */ 31 | char * qs_k2v(const char * key, char * qs_kv[], int qs_kv_size); 32 | 33 | 34 | /* Non-destructive lookup of value, based on key. User provides the 35 | * destinaton string and length. */ 36 | char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len); 37 | 38 | 39 | /* Converts the 3 or 6 (RGB), or 4 or 8 (RGBA) hex chars in the color string 40 | * to double values in the range 0.0-1.0. Returns the number of converted 41 | * chars. */ 42 | int hex2dcolor(char * color, double * r, double * g, double * b, double * a); 43 | 44 | 45 | /* Converts the 3/6 (RGB) or 4/8 (RGBA) hex chars in the color string to 46 | * values spanning the full range of unsigned char, 0-255. Returns the 47 | * number of converted chars. */ 48 | int hex2ccolor(char * color, unsigned char * r, unsigned char * g, unsigned char * b, unsigned char * a); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif // BG_QSPARSE_H_ 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qs_parse # 2 | 3 | ## Description ## 4 | 5 | A set of simple and easy functions for parsing URL query strings, such as 6 | those generated in an HTTP GET form submission. 7 | 8 | 9 | ## How to Use ## 10 | 11 | These qs_* functions can be used in two different ways: 12 | 13 | `qs_parse()`/`qs_k2v()`: A faster version that requires a pre-processing stage 14 | and **is destructive to the query string** 15 | 16 | * Better for repeated lookups of k/v pairs 17 | * Does all decoding/processing in-place, so no memory copying 18 | * Requires an array of pointers to strings to be passed to the preprocessing stage 19 | * Cannot be used where the query string is const 20 | 21 | `qs_scanvalue()`: A slower version that will scan for the given key and will 22 | decode the value into a user-provided string 23 | 24 | * Doesn't alter the query string so can be used where it is const, or cannot be altered 25 | * Only needs a user-passed char string for copying into 26 | * Scans the entire qs on each call, so isn't as fast as qs_k2v() 27 | 28 | 29 | Since `qs_parse()`/`qs_k2v()` alters the query string that is passed to it in a way 30 | that defeats `qs_scanvalue()`, do not mix these two methods (or if you must, 31 | either don't call `qs_scanvalue()` after a call to `qs_parse()` or be sure make 32 | a copy of the query string beforehand) 33 | 34 | [note: speed comparisons will be more relevant when the sorting the k/v pairs 35 | code is implemented] 36 | 37 | 38 | ## Installation ## 39 | All you really need is qs_parse.h and qs_parse.c. I've included my test program 40 | ("qs_test.c") and an example program that shows how to use these functions 41 | ("qs_example.c"). Also included is a quick Makefile. If you want to see it 42 | come to life just get all the files and: 43 | 44 | # make 45 | # ./qs_example 46 | 47 | 48 | ## Bugs, etc. ## 49 | 50 | Please let me know if you find any, or if you have license-friendly enhancements 51 | to add. 52 | 53 | 54 | ## License ## 55 | 56 | MIT License. See ./LICENSE or 57 | 58 | Few things are more enjoyable than the knowledge that you've helped another 59 | person. If you do use these functions for anything, I'd love to hear about it: 60 | 61 | 62 | 63 | 64 | Enjoy! 65 | 66 | -Bart 67 | -------------------------------------------------------------------------------- /qs_example.c: -------------------------------------------------------------------------------- 1 | /* Licensed under the MIT License by Bart Grantham, 2010. See ./LICENSE or 2 | * http://www.opensource.org/licenses/mit-license.php 3 | */ 4 | #include 5 | #include "qs_parse.h" 6 | 7 | #define NUMKVPAIRS 256 8 | #define VALSIZE 256 9 | 10 | int main(int argc, char * argv[]) 11 | { 12 | int i; 13 | char * kvpairs[NUMKVPAIRS]; 14 | char value[VALSIZE]; 15 | char * value_ptr; 16 | unsigned char r, g, b, a; 17 | double dr, dg, db, da; 18 | 19 | char getstring[] = "scheme://username:password@domain:port/path?foo=bar&frob&baz=quux&color=09FA#anchor"; 20 | 21 | printf("Our GET string is %s\n\n", getstring); 22 | 23 | /********************************************************/ 24 | /* The easy, but not as efficient way: qs_scanvalue() */ 25 | /********************************************************/ 26 | if ( qs_scanvalue("foo", getstring, value, sizeof(value)) != NULL ) 27 | printf("Key %s is set, and the value is: \"%s\"\n", "foo", value); 28 | else 29 | printf("Key %s is NOT set\n", "foo"); 30 | 31 | if ( qs_scanvalue("baz", getstring, value, sizeof(value)) != NULL ) 32 | printf("Key %s is set, and the value is: \"%s\"\n", "baz", value); 33 | else 34 | printf("Key %s is NOT set\n", "baz"); 35 | 36 | if ( qs_scanvalue("frob", getstring, value, sizeof(value)) != NULL ) 37 | printf("Key %s is set, and the value is: \"%s\"\n", "frob", value); 38 | else 39 | printf("Key %s is NOT set\n", "frob"); 40 | 41 | if ( qs_scanvalue("blah", getstring, value, sizeof(value)) != NULL ) 42 | printf("Key %s is set, and the value is: \"%s\"\n", "blah", value); 43 | else 44 | printf("Key %s is NOT set\n", "blah"); 45 | 46 | if ( qs_scanvalue("color", getstring, value, sizeof(value)) != NULL ) 47 | { 48 | printf("Key %s is set, and the value is: \"%s\"\n", "color", value); 49 | if ( hex2ccolor(value, &r, &g, &b, &a) != 0 && hex2dcolor(value, &dr, &dg, &db, &da) != 0 ) 50 | { 51 | printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a); 52 | printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da); 53 | } 54 | else 55 | printf(" \"%s\" NOT successfully decoded\n", "color"); 56 | } 57 | else 58 | printf("Key %s is NOT set\n", "color"); 59 | 60 | printf("\n"); 61 | 62 | 63 | /*************************************************************************/ 64 | /* The faster, more complex, and destructive way: qs_parse() / qs_k2v() */ 65 | /*************************************************************************/ 66 | 67 | /* ***THIS WILL ALTER getstring*** */ 68 | i = qs_parse(getstring, kvpairs, 256); 69 | /* At this point qs_scanvalue() will no longer work with this query string */ 70 | 71 | if ( (value_ptr = qs_k2v("foo", kvpairs, i)) != NULL ) 72 | printf("Key %s is set, and the value is: \"%s\"\n", "foo", value_ptr); 73 | else 74 | printf("Key %s is NOT set\n", "foo"); 75 | 76 | if ( (value_ptr = qs_k2v("baz", kvpairs, i)) != NULL ) 77 | printf("Key %s is set, and the value is: \"%s\"\n", "baz", value_ptr); 78 | else 79 | printf("Key %s is NOT set\n", "baz"); 80 | 81 | if ( (value_ptr = qs_k2v("frob", kvpairs, i)) != NULL ) 82 | printf("Key %s is set, and the value is: \"%s\"\n", "frob", value_ptr); 83 | else 84 | printf("Key %s is NOT set\n", "frob"); 85 | 86 | if ( (value_ptr = qs_k2v("blah", kvpairs, i)) != NULL ) 87 | printf("Key %s is set, and the value is: \"%s\"\n", "blah", value_ptr); 88 | else 89 | printf("Key %s is NOT set\n", "blah"); 90 | 91 | if ( (value_ptr = qs_k2v("color", kvpairs, i)) != NULL ) 92 | { 93 | printf("Key %s is set, and the value is: \"%s\"\n", "color", value_ptr); 94 | if ( hex2ccolor(value_ptr, &r, &g, &b, &a) != 0 && hex2dcolor(value_ptr, &dr, &dg, &db, &da) != 0 ) 95 | { 96 | printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a); 97 | printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da); 98 | } 99 | else 100 | printf(" \"%s\" NOT successfully decoded\n", "color"); 101 | } 102 | else 103 | printf("Key %s is NOT set\n", "color"); 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /qs_parse.c: -------------------------------------------------------------------------------- 1 | #include "qs_parse.h" 2 | #include 3 | 4 | // TODO: implement sorting of the qs_kv array; for now ensure it's not compiled 5 | #undef _qsSORTING 6 | 7 | // isxdigit _is_ available in , but let's avoid another header instead 8 | #define ISHEX(x) ((((x)>='0'&&(x)<='9') || ((x)>='A'&&(x)<='F') || ((x)>='a'&&(x)<='f')) ? 1 : 0) 9 | #define HEX2DEC(x) (((x)>='0'&&(x)<='9') ? (x)-48 : ((x)>='A'&&(x)<='F') ? (x)-55 : ((x)>='a'&&(x)<='f') ? (x)-87 : 0) 10 | #define ISQSCHR(x) ((((x)=='=')||((x)=='#')||((x)=='&')||((x)=='\0')) ? 0 : 1) 11 | 12 | int qs_strncmp(const char * s, const char * qs, register size_t n) 13 | { 14 | int i=0; 15 | register unsigned char u1, u2, unyb, lnyb; 16 | 17 | while(n-- > 0) 18 | { 19 | u1 = (unsigned char) *s++; 20 | u2 = (unsigned char) *qs++; 21 | 22 | if ( ! ISQSCHR(u1) ) { u1 = '\0'; } 23 | if ( ! ISQSCHR(u2) ) { u2 = '\0'; } 24 | 25 | if ( u1 == '+' ) { u1 = ' '; } 26 | if ( u1 == '%' ) // easier/safer than scanf 27 | { 28 | unyb = (unsigned char) *s++; 29 | lnyb = (unsigned char) *s++; 30 | if ( ISHEX(unyb) && ISHEX(lnyb) ) 31 | u1 = (HEX2DEC(unyb) * 16) + HEX2DEC(lnyb); 32 | else 33 | u1 = '\0'; 34 | } 35 | 36 | if ( u2 == '+' ) { u2 = ' '; } 37 | if ( u2 == '%' ) // easier/safer than scanf 38 | { 39 | unyb = (unsigned char) *qs++; 40 | lnyb = (unsigned char) *qs++; 41 | if ( ISHEX(unyb) && ISHEX(lnyb) ) 42 | u2 = (HEX2DEC(unyb) * 16) + HEX2DEC(lnyb); 43 | else 44 | u2 = '\0'; 45 | } 46 | 47 | if ( u1 != u2 ) 48 | return u1 - u2; 49 | if ( u1 == '\0' ) 50 | return 0; 51 | i++; 52 | } 53 | if ( ISQSCHR(*qs) ) 54 | return -1; 55 | else 56 | return 0; 57 | } 58 | 59 | 60 | int qs_parse(char * qs, char * qs_kv[], int qs_kv_size) 61 | { 62 | int i, j; 63 | char * substr_ptr; 64 | 65 | for(i=0; i means x iterations of this loop -> means *x+1* k/v pairs 83 | 84 | // we only decode the values in place, the keys could have '='s in them 85 | // which will hose our ability to distinguish keys from values later 86 | for(j=0; j 5 | #include "qs_parse.h" 6 | 7 | int main(int argc, char * argv[]) 8 | { 9 | int i,j; 10 | char * kvpairs[256]; 11 | char value[256]; 12 | unsigned char r, g, b, a; 13 | double dr, dg, db, da; 14 | 15 | char foo[] = "foo"; 16 | char foobar[] = "foobar"; 17 | char foo_enc[] = "fo%6f"; 18 | char foobar_enc[] = "fo%6fbar"; 19 | char foo_mal[] = "fo%6"; 20 | char foo_mal2[] = "foo%6"; 21 | char foo_end[] = "foo&"; 22 | 23 | /* This test query string includes: 24 | * - URL encoded values (percent-encoded and +-as-space) 25 | * - URL encoded keys (percent-encoded +-as-space) 26 | * - Incorrectly encoded values (FFFFFF%f) 27 | * - A trailing anchor 28 | * - null (0-char) values 29 | * 30 | * I should add: 31 | * - leading URL junk (before a ?) 32 | */ 33 | 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"; 34 | 35 | printf("Testing qs_* functions\n"); 36 | 37 | printf(" Testing qs_strncmp():\n"); 38 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 3)); 39 | printf(" %s, %s, 4 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 4)); 40 | printf(" %s, %s, 99 should be 0 : %d\n", foo, foo, qs_strncmp(foo, foo, 99)); 41 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 3)); 42 | printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 4)); 43 | printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_enc, qs_strncmp(foo, foo_enc, 99)); 44 | printf(" %s, %s, 3 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 3)); 45 | printf(" %s, %s, 4 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 4)); 46 | printf(" %s, %s, 99 should be 0 : %d\n", foo_enc, foo_enc, qs_strncmp(foo_enc, foo_enc, 99)); 47 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foobar, qs_strncmp(foo, foobar, 3)); 48 | printf(" %s, %s, 4 should be - : %d\n", foo, foobar, qs_strncmp(foo, foobar, 4)); 49 | printf(" %s, %s, 99 should be - : %d\n", foo, foobar, qs_strncmp(foo, foobar, 99)); 50 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 3)); 51 | printf(" %s, %s, 4 should be - : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 4)); 52 | printf(" %s, %s, 99 should be - : %d\n", foo, foobar_enc, qs_strncmp(foo, foobar_enc, 99)); 53 | printf(" %s, %s, 3 should be 0 : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 3)); 54 | printf(" %s, %s, 4 should be - : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 4)); 55 | printf(" %s, %s, 99 should be - : %d\n", foo_enc, foobar_enc, qs_strncmp(foo_enc, foobar_enc, 99)); 56 | printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 2)); 57 | printf(" %s, %s, 3 should be + : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 3)); 58 | printf(" %s, %s, 99 should be + : %d\n", foo, foo_mal, qs_strncmp(foo, foo_mal, 99)); 59 | printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 2)); 60 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 3)); 61 | printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 4)); 62 | printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_mal2, qs_strncmp(foo, foo_mal2, 99)); 63 | printf(" %s, %s, 2 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 2)); 64 | printf(" %s, %s, 3 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 3)); 65 | printf(" %s, %s, 4 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 4)); 66 | printf(" %s, %s, 99 should be 0 : %d\n", foo, foo_end, qs_strncmp(foo, foo_end, 99)); 67 | 68 | printf("\n"); 69 | 70 | 71 | printf(" Testing qs_scanvalue() with query string:\n %s\n", getstring); 72 | printf(" The following should say \"bleh bleh !\" : \"%s\"\n", qs_scanvalue("text", getstring, value, 256)); 73 | printf(" The following should say \"Vera.ttf\" : \"%s\"\n", qs_scanvalue("font", getstring, value, 256)); 74 | printf(" The following should say \"40.3\" : \"%s\"\n", qs_scanvalue("size", getstring, value, 256)); 75 | printf(" The following should say \"Fa98BF44\" : \"%s\"\n", qs_scanvalue("fg", getstring, value, 256)); 76 | printf(" The following should say \"\" : \"%s\"\n", qs_scanvalue("debug1", getstring, value, 256)); 77 | printf(" The following should say \"0C0\" : \"%s\"\n", qs_scanvalue("bg", getstring, value, 256)); 78 | printf(" The following should say \"FF4455F\" : \"%s\"\n", qs_scanvalue("color", getstring, value, 256)); 79 | printf(" The following should say \"24abcdefz\" : \"%s\"\n", qs_scanvalue("hash", getstring, value, 256)); 80 | printf(" The following should say \"123.1\" : \"%s\"\n", qs_scanvalue("rot", getstring, value, 256)); 81 | printf(" The following should say \"cky\" : \"%s\"\n", qs_scanvalue("tr i", getstring, value, 256)); 82 | printf(" The following should say \"\" : \"%s\"\n", qs_scanvalue("debug2", getstring, value, 256)); 83 | printf("\n"); 84 | 85 | printf(" Running qs_parse() against query string (also exersizes qs_decode()):\n %s\n", getstring); 86 | i = qs_parse(getstring, kvpairs, 256); 87 | printf(" I should have found 11 k/v substrings, actually found: %d\n", i); 88 | printf("\n"); 89 | 90 | printf(" Testing qs_k2v() against our kv pair substrings:\n"); 91 | printf(" The following should say \"bleh bleh !\" : \"%s\"\n", qs_k2v("text", kvpairs, i)); 92 | printf(" The following should say \"Vera.ttf\" : \"%s\"\n", qs_k2v("font", kvpairs, i)); 93 | printf(" The following should say \"40.3\" : \"%s\"\n", qs_k2v("size", kvpairs, i)); 94 | printf(" The following should say \"Fa98BF44\" : \"%s\"\n", qs_k2v("fg", kvpairs, i)); 95 | printf(" The following should say \"\" : \"%s\"\n", qs_k2v("debug1", kvpairs, i)); 96 | printf(" The following should say \"0C0\" : \"%s\"\n", qs_k2v("bg", kvpairs, i)); 97 | printf(" The following should say \"FF4455F\" : \"%s\"\n", qs_k2v("color", kvpairs, i)); 98 | printf(" The following should say \"24abcdefz\" : \"%s\"\n", qs_k2v("hash", kvpairs, i)); 99 | printf(" The following should say \"123.1\" : \"%s\"\n", qs_k2v("rot", kvpairs, i)); 100 | printf(" The following should say \"cky\" : \"%s\"\n", qs_k2v("tr i", kvpairs, i)); 101 | printf(" The following should say \"\" : \"%s\"\n", qs_k2v("debug2", kvpairs, i)); 102 | printf("\n"); 103 | 104 | printf(" Testing hex2ccolor() and hex2dcolor() with fg (\"%s\"):\n", qs_k2v("fg", kvpairs, i)); 105 | j = hex2ccolor(qs_k2v("fg", kvpairs, i), &r, &g, &b, &a); 106 | 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); 107 | j = hex2dcolor(qs_k2v("fg", kvpairs, i), &dr, &dg, &db, &da); 108 | 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); 109 | 110 | printf(" Testing hex2ccolor() and hex2dcolor() with bg (\"%s\"):\n", qs_k2v("bg", kvpairs, i)); 111 | j = hex2ccolor(qs_k2v("bg", kvpairs, i), &r, &g, &b, &a); 112 | 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); 113 | j = hex2dcolor(qs_k2v("bg", kvpairs, i), &dr, &dg, &db, &da); 114 | 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); 115 | 116 | printf(" Testing hex2ccolor() and hex2dcolor() with color (\"%s\"):\n", qs_k2v("color", kvpairs, i)); 117 | j = hex2ccolor(qs_k2v("color", kvpairs, i), &r, &g, &b, &a); 118 | printf(" hex2ccolor() should have decoded 0 chars : %d chars decoded\n", j); 119 | j = hex2dcolor(qs_k2v("color", kvpairs, i), &dr, &dg, &db, &da); 120 | printf(" hex2dcolor() should have decoded 0 chars : %d chars decoded\n", j); 121 | 122 | /* 123 | print 124 | 125 | if ( qs_scanvalue("color", getstring, value, sizeof(value)) != NULL ) 126 | { 127 | printf("Key %s is set, and the value is: \"%s\"\n", "color", value); 128 | if ( hex2ccolor(value, &r, &g, &b, &a) != 0 && hex2dcolor(value, &dr, &dg, &db, &da) != 0 ) 129 | { 130 | printf(" \"%s\" successfully decoded as uchar : r=%d, g=%d, b=%d, a=%d\n", "color", r, g, b, a); 131 | printf(" \"%s\" successfully decoded as double : r=%.2f, g=%.2f, b=%.2f, a=%.2f\n", "color", dr, dg, db, da); 132 | } 133 | else 134 | printf(" \"%s\" NOT successfully decoded\n", "color"); 135 | } 136 | */ 137 | return 0; 138 | } 139 | --------------------------------------------------------------------------------