LCOV - code coverage report
Current view: top level - src/plugins/rgbcolor - rgbcolor.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 95 95 100.0 %
Date: 2022-05-21 16:19:22 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Source for rgbcolor plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include "rgbcolor.h"
      11             : #include <kdberrors.h>
      12             : #include <kdbhelper.h>
      13             : #include <kdbtypes.h>
      14             : #include <regex.h>
      15             : #include <stdio.h>
      16             : #include <stdlib.h>
      17             : 
      18             : typedef struct
      19             : {
      20             :         const char * name;
      21             :         const kdb_unsigned_long_t value;
      22             : } NamedColor;
      23             : 
      24             : static const NamedColor NamedColors[] = { { "aliceblue", 0xf0f8ffff },
      25             :                                           { "antiquewhite", 0xfaebd7ff },
      26             :                                           { "aqua", 0x00ffffff },
      27             :                                           { "aquamarine", 0x7fffd4ff },
      28             :                                           { "azure", 0xf0ffffff },
      29             :                                           { "beige", 0xf5f5dcff },
      30             :                                           { "bisque", 0xffe4c4ff },
      31             :                                           { "black", 0x000000ff },
      32             :                                           { "blanchedalmond", 0xffebcdff },
      33             :                                           { "blue", 0x0000ffff },
      34             :                                           { "blueviolet", 0x8a2be2ff },
      35             :                                           { "brown", 0xa52a2aff },
      36             :                                           { "burlywood", 0xdeb887ff },
      37             :                                           { "cadetblue", 0x5f9ea0ff },
      38             :                                           { "chartreuse", 0x7fff00ff },
      39             :                                           { "chocolate", 0xd2691eff },
      40             :                                           { "coral", 0xff7f50ff },
      41             :                                           { "cornflowerblue", 0x6495edff },
      42             :                                           { "cornsilk", 0xfff8dcff },
      43             :                                           { "crimson", 0xdc143cff },
      44             :                                           { "cyan", 0x00ffffff },
      45             :                                           { "darkblue", 0x00008bff },
      46             :                                           { "darkcyan", 0x008b8bff },
      47             :                                           { "darkgoldenrod", 0xb8860bff },
      48             :                                           { "darkgray", 0xa9a9a9ff },
      49             :                                           { "darkgreen", 0x006400ff },
      50             :                                           { "darkgrey", 0xa9a9a9ff },
      51             :                                           { "darkkhaki", 0xbdb76bff },
      52             :                                           { "darkmagenta", 0x8b008bff },
      53             :                                           { "darkolivegreen", 0x556b2fff },
      54             :                                           { "darkorange", 0xff8c00ff },
      55             :                                           { "darkorchid", 0x9932ccff },
      56             :                                           { "darkred", 0x8b0000ff },
      57             :                                           { "darksalmon", 0xe9967aff },
      58             :                                           { "darkseagreen", 0x8fbc8fff },
      59             :                                           { "darkslateblue", 0x483d8bff },
      60             :                                           { "darkslategray", 0x2f4f4fff },
      61             :                                           { "darkslategrey", 0x2f4f4fff },
      62             :                                           { "darkturquoise", 0x00ced1ff },
      63             :                                           { "darkviolet", 0x9400d3ff },
      64             :                                           { "deeppink", 0xff1493ff },
      65             :                                           { "deepskyblue", 0x00bfffff },
      66             :                                           { "dimgray", 0x696969ff },
      67             :                                           { "dimgrey", 0x696969ff },
      68             :                                           { "dodgerblue", 0x1e90ffff },
      69             :                                           { "firebrick", 0xb22222ff },
      70             :                                           { "floralwhite", 0xfffaf0ff },
      71             :                                           { "forestgreen", 0x228b22ff },
      72             :                                           { "fuchsia", 0xff00ffff },
      73             :                                           { "gainsboro", 0xdcdcdcff },
      74             :                                           { "ghostwhite", 0xf8f8ffff },
      75             :                                           { "gold", 0xffd700ff },
      76             :                                           { "goldenrod", 0xdaa520ff },
      77             :                                           { "gray", 0x808080ff },
      78             :                                           { "green", 0x008000ff },
      79             :                                           { "greenyellow", 0xadff2fff },
      80             :                                           { "grey", 0x808080ff },
      81             :                                           { "honeydew", 0xf0fff0ff },
      82             :                                           { "hotpink", 0xff69b4ff },
      83             :                                           { "indianred", 0xcd5c5cff },
      84             :                                           { "indigo", 0x4b0082ff },
      85             :                                           { "ivory", 0xfffff0ff },
      86             :                                           { "khaki", 0xf0e68cff },
      87             :                                           { "lavender", 0xe6e6faff },
      88             :                                           { "lavenderblush", 0xfff0f5ff },
      89             :                                           { "lawngreen", 0x7cfc00ff },
      90             :                                           { "lemonchiffon", 0xfffacdff },
      91             :                                           { "lightblue", 0xadd8e6ff },
      92             :                                           { "lightcoral", 0xf08080ff },
      93             :                                           { "lightcyan", 0xe0ffffff },
      94             :                                           { "lightgoldenrodyellow", 0xfafad2ff },
      95             :                                           { "lightgray", 0xd3d3d3ff },
      96             :                                           { "lightgreen", 0x90ee90ff },
      97             :                                           { "lightgrey", 0xd3d3d3ff },
      98             :                                           { "lightpink", 0xffb6c1ff },
      99             :                                           { "lightsalmon", 0xffa07aff },
     100             :                                           { "lightseagreen", 0x20b2aaff },
     101             :                                           { "lightskyblue", 0x87cefaff },
     102             :                                           { "lightslategray", 0x778899ff },
     103             :                                           { "lightslategrey", 0x778899ff },
     104             :                                           { "lightsteelblue", 0xb0c4deff },
     105             :                                           { "lightyellow", 0xffffe0ff },
     106             :                                           { "lime", 0x00ff00ff },
     107             :                                           { "limegreen", 0x32cd32ff },
     108             :                                           { "linen", 0xfaf0e6ff },
     109             :                                           { "magenta", 0xff00ffff },
     110             :                                           { "maroon", 0x800000ff },
     111             :                                           { "mediumaquamarine", 0x66cdaaff },
     112             :                                           { "mediumblue", 0x0000cdff },
     113             :                                           { "mediumorchid", 0xba55d3ff },
     114             :                                           { "mediumpurple", 0x9370dbff },
     115             :                                           { "mediumseagreen", 0x3cb371ff },
     116             :                                           { "mediumslateblue", 0x7b68eeff },
     117             :                                           { "mediumspringgreen", 0x00fa9aff },
     118             :                                           { "mediumturquoise", 0x48d1ccff },
     119             :                                           { "mediumvioletred", 0xc71585ff },
     120             :                                           { "midnightblue", 0x191970ff },
     121             :                                           { "mintcream", 0xf5fffaff },
     122             :                                           { "mistyrose", 0xffe4e1ff },
     123             :                                           { "moccasin", 0xffe4b5ff },
     124             :                                           { "navajowhite", 0xffdeadff },
     125             :                                           { "navy", 0x000080ff },
     126             :                                           { "oldlace", 0xfdf5e6ff },
     127             :                                           { "olive", 0x808000ff },
     128             :                                           { "olivedrab", 0x6b8e23ff },
     129             :                                           { "orange", 0xffa500ff },
     130             :                                           { "orangered", 0xff4500ff },
     131             :                                           { "orchid", 0xda70d6ff },
     132             :                                           { "palegoldenrod", 0xeee8aaff },
     133             :                                           { "palegreen", 0x98fb98ff },
     134             :                                           { "paleturquoise", 0xafeeeeff },
     135             :                                           { "palevioletred", 0xdb7093ff },
     136             :                                           { "papayawhip", 0xffefd5ff },
     137             :                                           { "peachpuff", 0xffdab9ff },
     138             :                                           { "peru", 0xcd853fff },
     139             :                                           { "pink", 0xffc0cbff },
     140             :                                           { "plum", 0xdda0ddff },
     141             :                                           { "powderblue", 0xb0e0e6ff },
     142             :                                           { "purple", 0x800080ff },
     143             :                                           { "red", 0xff0000ff },
     144             :                                           { "rosybrown", 0xbc8f8fff },
     145             :                                           { "royalblue", 0x4169e1ff },
     146             :                                           { "saddlebrown", 0x8b4513ff },
     147             :                                           { "salmon", 0xfa8072ff },
     148             :                                           { "sandybrown", 0xf4a460ff },
     149             :                                           { "seagreen", 0x2e8b57ff },
     150             :                                           { "seashell", 0xfff5eeff },
     151             :                                           { "sienna", 0xa0522dff },
     152             :                                           { "silver", 0xc0c0c0ff },
     153             :                                           { "skyblue", 0x87ceebff },
     154             :                                           { "slateblue", 0x6a5acdff },
     155             :                                           { "slategray", 0x708090ff },
     156             :                                           { "slategrey", 0x708090ff },
     157             :                                           { "snow", 0xfffafaff },
     158             :                                           { "springgreen", 0x00ff7fff },
     159             :                                           { "steelblue", 0x4682b4ff },
     160             :                                           { "tan", 0xd2b48cff },
     161             :                                           { "teal", 0x008080ff },
     162             :                                           { "thistle", 0xd8bfd8ff },
     163             :                                           { "tomato", 0xff6347ff },
     164             :                                           { "turquoise", 0x40e0d0ff },
     165             :                                           { "violet", 0xee82eeff },
     166             :                                           { "wheat", 0xf5deb3ff },
     167             :                                           { "white", 0xffffffff },
     168             :                                           { "whitesmoke", 0xf5f5f5ff },
     169             :                                           { "yellow", 0xffff00ff },
     170             :                                           { "yellowgreen", 0x9acd32ff } };
     171             : 
     172             : typedef enum
     173             : {
     174             :         COLOR_INVALID,
     175             :         HEX_THREE,
     176             :         HEX_FOUR,
     177             :         HEX_SIX,
     178             :         HEX_EIGHT,
     179             :         NAMED_COLOR
     180             : } ColorVariant;
     181             : 
     182             : /**
     183             :  * Internal function used for bsearch
     184             :  */
     185        1334 : static int compareNamedColors (const void * c1, const void * c2)
     186             : {
     187        1334 :         NamedColor * nc1 = (NamedColor *) c1;
     188        1334 :         NamedColor * nc2 = (NamedColor *) c2;
     189        1334 :         return strcmp (nc1->name, nc2->name);
     190             : }
     191             : 
     192             : /**
     193             :  * Finds a named color with the given name
     194             :  *
     195             :  * @param colorName the color name to search for
     196             :  * @retval NULL if no color with the given name exists
     197             :  * @retval The NamedColor with the given name
     198             :  */
     199         181 : static const NamedColor * findNamedColor (const char * colorName)
     200             : {
     201         181 :         const NamedColor key = { .name = colorName };
     202         181 :         void * found;
     203         181 :         found = bsearch (&key, &NamedColors[0], 147, sizeof (NamedColor), compareNamedColors);
     204         181 :         if (found == NULL) return NULL;
     205             :         return (NamedColor *) found;
     206             : }
     207             : 
     208             : /**
     209             :  * Checks wheter the given key contains a valid hex-formatted string or a named color
     210             :  *
     211             :  * @param key the key whose value should be checked
     212             :  * @param parentKey the parent key
     213             :  */
     214         158 : static ColorVariant is_valid_key (Key * key, Key * parentKey)
     215             : {
     216         158 :         const Key * meta = keyGetMeta (key, "check/rgbcolor");
     217         158 :         if (!meta) return 1;
     218         158 :         const char * value = keyString (key);
     219             : 
     220         158 :         const NamedColor * namedColor = findNamedColor (value);
     221             : 
     222         158 :         if (namedColor != NULL)
     223             :         {
     224             :                 return NAMED_COLOR;
     225             :         }
     226             : 
     227         111 :         if (*value == '#')
     228             :         {
     229          99 :                 size_t len = strlen (value + 1);
     230          99 :                 size_t lengthValidChars = strspn (value + 1, "0123456789abcdefABCDEF");
     231          99 :                 if (len == lengthValidChars)
     232             :                 {
     233          96 :                         switch (len)
     234             :                         {
     235             :                         case 3:
     236             :                                 return HEX_THREE;
     237          18 :                         case 4:
     238          18 :                                 return HEX_FOUR;
     239          29 :                         case 6:
     240          29 :                                 return HEX_SIX;
     241          21 :                         case 8:
     242          21 :                                 return HEX_EIGHT;
     243             :                         }
     244             :                 }
     245             :         }
     246             : 
     247          19 :         ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey,
     248             :                                                  "Key '%s' with value '%s' is neither a valid hex formatted color nor a named color",
     249             :                                                  keyName (key), keyString (key));
     250          19 :         return COLOR_INVALID;
     251             : }
     252             : 
     253             : /**
     254             :  * Sets the keys value to the given integer formatted as a string
     255             :  *
     256             :  * @param key the key to set the value for
     257             :  * @param c the integer to set as the new value
     258             :  */
     259          60 : static void elektraColorSetInteger (Key * key, kdb_unsigned_long_t c)
     260             : {
     261          60 :         char colorStr[11];
     262          60 :         snprintf (colorStr, 11, "%u", c);
     263             : 
     264          60 :         ELEKTRA_LOG_DEBUG ("Set %s to integer %s", keyName (key), colorStr);
     265          60 :         keySetString (key, colorStr);
     266          60 : }
     267             : 
     268             : /**
     269             :  * Expands all color variants to the full RRGGBBAA variant.
     270             :  *
     271             :  * @param str the string to expand.
     272             :  * @param colVar the ColorVariant of str
     273             :  * @param expandedStr pre-allocated memory of length 10 to store the expanded string.
     274             :  */
     275          31 : static void elektraColorExpand (const char * str, ColorVariant colVar, char * expandedStr)
     276             : {
     277          31 :         if (colVar == HEX_THREE || colVar == HEX_FOUR)
     278             :         {
     279          16 :                 expandedStr[0] = '#';
     280             : 
     281          72 :                 for (size_t i = 1; i < strlen (str); i++)
     282             :                 {
     283          56 :                         expandedStr[2 * i - 1] = str[i];
     284          56 :                         expandedStr[2 * i] = str[i];
     285             :                 }
     286             :         }
     287             :         else
     288             :         {
     289          15 :                 strcpy (expandedStr, str);
     290             :         }
     291             : 
     292          31 :         if (colVar == HEX_THREE || colVar == HEX_SIX)
     293             :         {
     294          23 :                 expandedStr[7] = 'f';
     295          23 :                 expandedStr[8] = 'f';
     296             :         }
     297             : 
     298          31 :         expandedStr[9] = '\0';
     299          31 : }
     300             : 
     301             : /**
     302             :  * Normalizes a rgb, rgba, rrggbb hexstring to rrggbbaa
     303             :  *
     304             :  * @param key the key to normalize
     305             :  * @param colVar the ColorVariant of the string in key
     306             :  */
     307          60 : static void elektraColorNormalizeHexString (Key * key, ColorVariant colVar)
     308             : {
     309          60 :         const char * str = keyString (key);
     310          60 :         char * origvalue = elektraStrDup (str);
     311             : 
     312          60 :         kdb_unsigned_long_t color;
     313          60 :         if (colVar == NAMED_COLOR)
     314             :         {
     315          23 :                 const NamedColor * namedColor = findNamedColor (str);
     316          23 :                 color = namedColor->value;
     317             :         }
     318          37 :         else if (colVar != HEX_EIGHT)
     319             :         {
     320          31 :                 char expandedStr[10];
     321          31 :                 elektraColorExpand (str, colVar, expandedStr);
     322          31 :                 ELEKTRA_LOG_DEBUG ("Expanded %s to %s", str, expandedStr);
     323          31 :                 color = ELEKTRA_UNSIGNED_LONG_LONG_S (expandedStr + 1, NULL, 16);
     324             :         }
     325             :         else
     326             :         {
     327           6 :                 color = ELEKTRA_UNSIGNED_LONG_LONG_S (str + 1, NULL, 16);
     328             :         }
     329          60 :         elektraColorSetInteger (key, color);
     330             : 
     331          60 :         ELEKTRA_LOG_DEBUG ("Setting origvalue of %s to %s", keyName (key), origvalue);
     332          60 :         keySetMeta (key, "origvalue", origvalue);
     333          60 :         elektraFree (origvalue);
     334          60 : }
     335             : 
     336             : /**
     337             :  * Restores the original value
     338             :  *
     339             :  * @param key the key to restore the value for
     340             :  */
     341          98 : static void elektraColorRestore (Key * key)
     342             : {
     343          98 :         const Key * orig = keyGetMeta (key, "origvalue");
     344          98 :         if (orig != NULL)
     345             :         {
     346           5 :                 ELEKTRA_LOG_DEBUG ("Restore %s to %s", keyName (key), keyString (orig));
     347           5 :                 keySetString (key, keyString (orig));
     348             :         }
     349          98 : }
     350             : 
     351          85 : int elektraRgbcolorGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
     352             : {
     353          85 :         if (!elektraStrCmp (keyName (parentKey), "system:/elektra/modules/rgbcolor"))
     354             :         {
     355          35 :                 KeySet * contract =
     356          35 :                         ksNew (30, keyNew ("system:/elektra/modules/rgbcolor", KEY_VALUE, "rgbcolor plugin waits for your orders", KEY_END),
     357             :                                keyNew ("system:/elektra/modules/rgbcolor/exports", KEY_END),
     358             :                                keyNew ("system:/elektra/modules/rgbcolor/exports/get", KEY_FUNC, elektraRgbcolorGet, KEY_END),
     359             :                                keyNew ("system:/elektra/modules/rgbcolor/exports/set", KEY_FUNC, elektraRgbcolorSet, KEY_END),
     360             : #include ELEKTRA_README
     361             :                                keyNew ("system:/elektra/modules/rgbcolor/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
     362          35 :                 ksAppend (returned, contract);
     363          35 :                 ksDel (contract);
     364             : 
     365          35 :                 return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     366             :         }
     367             : 
     368          50 :         Key * cur;
     369          50 :         ksRewind (returned);
     370         112 :         while ((cur = ksNext (returned)) != NULL)
     371             :         {
     372          62 :                 const Key * meta = keyGetMeta (cur, "check/rgbcolor");
     373          62 :                 if (!meta) continue;
     374          60 :                 ColorVariant colVar = is_valid_key (cur, parentKey);
     375          60 :                 elektraColorNormalizeHexString (cur, colVar);
     376             :         }
     377             : 
     378             :         return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     379             : }
     380             : 
     381          95 : int elektraRgbcolorSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     382             : {
     383             :         // set all keys
     384             :         // this function is optional
     385          95 :         Key * cur;
     386          95 :         ksRewind (returned);
     387         176 :         while ((cur = ksNext (returned)) != NULL)
     388             :         {
     389         100 :                 const Key * meta = keyGetMeta (cur, "check/rgbcolor");
     390         100 :                 if (!meta) continue;
     391             : 
     392          98 :                 elektraColorRestore (cur);
     393             : 
     394          98 :                 ColorVariant colVar = is_valid_key (cur, parentKey);
     395          98 :                 if (colVar == COLOR_INVALID) return ELEKTRA_PLUGIN_STATUS_ERROR;
     396             :         }
     397             :         return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     398             : }
     399             : 
     400         195 : Plugin * ELEKTRA_PLUGIN_EXPORT
     401             : {
     402             :         // clang-format off
     403         195 :         return elektraPluginExport ("rgbcolor",
     404             :                 ELEKTRA_PLUGIN_GET,     &elektraRgbcolorGet,
     405             :                 ELEKTRA_PLUGIN_SET,     &elektraRgbcolorSet,
     406             :                 ELEKTRA_PLUGIN_END);
     407             : }

Generated by: LCOV version 1.13