LCOV - code coverage report
Current view: top level - lib - ovsdb-types.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 294 319 92.2 %
Date: 2016-09-14 01:02:56 Functions: 21 21 100.0 %
Branches: 194 231 84.0 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2009, 2010, 2011, 2013 Nicira, Inc.
       2                 :            :  *
       3                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            :  * you may not use this file except in compliance with the License.
       5                 :            :  * You may obtain a copy of the License at:
       6                 :            :  *
       7                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            :  *
       9                 :            :  * Unless required by applicable law or agreed to in writing, software
      10                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            :  * See the License for the specific language governing permissions and
      13                 :            :  * limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #include <config.h>
      17                 :            : 
      18                 :            : #include "ovsdb-types.h"
      19                 :            : 
      20                 :            : #include <float.h>
      21                 :            : #include <limits.h>
      22                 :            : 
      23                 :            : #include "openvswitch/dynamic-string.h"
      24                 :            : #include "openvswitch/json.h"
      25                 :            : #include "ovs-thread.h"
      26                 :            : #include "ovsdb-data.h"
      27                 :            : #include "ovsdb-error.h"
      28                 :            : #include "ovsdb-parser.h"
      29                 :            : #include "util.h"
      30                 :            : 
      31                 :            : const struct ovsdb_type ovsdb_type_integer =
      32                 :            :     OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_INTEGER_INIT);
      33                 :            : const struct ovsdb_type ovsdb_type_real =
      34                 :            :     OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_REAL_INIT);
      35                 :            : const struct ovsdb_type ovsdb_type_boolean =
      36                 :            :     OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_BOOLEAN_INIT);
      37                 :            : const struct ovsdb_type ovsdb_type_string =
      38                 :            :     OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_STRING_INIT);
      39                 :            : const struct ovsdb_type ovsdb_type_uuid =
      40                 :            :     OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_UUID_INIT);
      41                 :            : 
      42                 :            : /* ovsdb_atomic_type */
      43                 :            : const char *
      44                 :    1401883 : ovsdb_atomic_type_to_string(enum ovsdb_atomic_type type)
      45                 :            : {
      46   [ +  +  +  +  :    1401883 :     switch (type) {
                +  +  - ]
      47                 :            :     case OVSDB_TYPE_VOID:
      48                 :         58 :         return "void";
      49                 :            : 
      50                 :            :     case OVSDB_TYPE_INTEGER:
      51                 :     325397 :         return "integer";
      52                 :            : 
      53                 :            :     case OVSDB_TYPE_REAL:
      54                 :        450 :         return "real";
      55                 :            : 
      56                 :            :     case OVSDB_TYPE_BOOLEAN:
      57                 :      81914 :         return "boolean";
      58                 :            : 
      59                 :            :     case OVSDB_TYPE_STRING:
      60                 :     852873 :         return "string";
      61                 :            : 
      62                 :            :     case OVSDB_TYPE_UUID:
      63                 :     141191 :         return "uuid";
      64                 :            : 
      65                 :            :     case OVSDB_N_TYPES:
      66                 :            :     default:
      67                 :          0 :         return "<invalid>";
      68                 :            :     }
      69                 :            : }
      70                 :            : 
      71                 :            : struct json *
      72                 :          5 : ovsdb_atomic_type_to_json(enum ovsdb_atomic_type type)
      73                 :            : {
      74                 :          5 :     return json_string_create(ovsdb_atomic_type_to_string(type));
      75                 :            : }
      76                 :            : 
      77                 :            : bool
      78                 :     341235 : ovsdb_atomic_type_from_string(const char *string, enum ovsdb_atomic_type *type)
      79                 :            : {
      80         [ +  + ]:     341235 :     if (!strcmp(string, "integer")) {
      81                 :      81173 :         *type = OVSDB_TYPE_INTEGER;
      82         [ +  + ]:     260062 :     } else if (!strcmp(string, "real")) {
      83                 :        776 :         *type = OVSDB_TYPE_REAL;
      84         [ +  + ]:     259286 :     } else if (!strcmp(string, "boolean")) {
      85                 :      20181 :         *type = OVSDB_TYPE_BOOLEAN;
      86         [ +  + ]:     239105 :     } else if (!strcmp(string, "string")) {
      87                 :     203415 :         *type = OVSDB_TYPE_STRING;
      88         [ +  + ]:      35690 :     } else if (!strcmp(string, "uuid")) {
      89                 :      35687 :         *type = OVSDB_TYPE_UUID;
      90                 :            :     } else {
      91                 :          3 :         return false;
      92                 :            :     }
      93                 :     341232 :     return true;
      94                 :            : }
      95                 :            : 
      96                 :            : struct ovsdb_error *
      97                 :     341235 : ovsdb_atomic_type_from_json(enum ovsdb_atomic_type *type,
      98                 :            :                             const struct json *json)
      99                 :            : {
     100         [ +  - ]:     341235 :     if (json->type == JSON_STRING) {
     101         [ +  + ]:     341235 :         if (ovsdb_atomic_type_from_string(json_string(json), type)) {
     102                 :     341232 :             return NULL;
     103                 :            :         } else {
     104                 :          3 :             *type = OVSDB_TYPE_VOID;
     105                 :          3 :             return ovsdb_syntax_error(json, NULL,
     106                 :            :                                       "\"%s\" is not an atomic-type",
     107                 :            :                                       json_string(json));
     108                 :            :         }
     109                 :            :     } else {
     110                 :          0 :         *type = OVSDB_TYPE_VOID;
     111                 :          0 :         return ovsdb_syntax_error(json, NULL, "atomic-type expected");
     112                 :            :     }
     113                 :            : }
     114                 :            : 
     115                 :            : /* ovsdb_base_type */
     116                 :            : 
     117                 :            : void
     118                 :    2693368 : ovsdb_base_type_init(struct ovsdb_base_type *base, enum ovsdb_atomic_type type)
     119                 :            : {
     120                 :    2693368 :     base->type = type;
     121                 :    2693368 :     base->enum_ = NULL;
     122                 :            : 
     123   [ +  +  +  +  :    2693368 :     switch (base->type) {
             +  +  -  - ]
     124                 :            :     case OVSDB_TYPE_VOID:
     125                 :    1057155 :         break;
     126                 :            : 
     127                 :            :     case OVSDB_TYPE_INTEGER:
     128                 :     381087 :         base->u.integer.min = INT64_MIN;
     129                 :     381087 :         base->u.integer.max = INT64_MAX;
     130                 :     381087 :         break;
     131                 :            : 
     132                 :            :     case OVSDB_TYPE_REAL:
     133                 :       2621 :         base->u.real.min = -DBL_MAX;
     134                 :       2621 :         base->u.real.max = DBL_MAX;
     135                 :       2621 :         break;
     136                 :            : 
     137                 :            :     case OVSDB_TYPE_BOOLEAN:
     138                 :      96729 :         break;
     139                 :            : 
     140                 :            :     case OVSDB_TYPE_STRING:
     141                 :     989471 :         base->u.string.minLen = 0;
     142                 :     989471 :         base->u.string.maxLen = UINT_MAX;
     143                 :     989471 :         break;
     144                 :            : 
     145                 :            :     case OVSDB_TYPE_UUID:
     146                 :     166305 :         base->u.uuid.refTableName = NULL;
     147                 :     166305 :         base->u.uuid.refTable = NULL;
     148                 :     166305 :         break;
     149                 :            : 
     150                 :            :     case OVSDB_N_TYPES:
     151                 :          0 :         OVS_NOT_REACHED();
     152                 :            : 
     153                 :            :     default:
     154                 :          0 :         OVS_NOT_REACHED();
     155                 :            :     }
     156                 :    2693368 : }
     157                 :            : 
     158                 :            : /* Returns the type of the 'enum_' member for an ovsdb_base_type whose 'type'
     159                 :            :  * is 'atomic_type'. */
     160                 :            : const struct ovsdb_type *
     161                 :     164010 : ovsdb_base_type_get_enum_type(enum ovsdb_atomic_type atomic_type)
     162                 :            : {
     163                 :            :     static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     164                 :            :     static struct ovsdb_type *types[OVSDB_N_TYPES];
     165                 :            : 
     166         [ +  + ]:     164010 :     if (ovsthread_once_start(&once)) {
     167                 :            :         enum ovsdb_atomic_type i;
     168                 :            : 
     169         [ +  + ]:      12257 :         for (i = 0; i < OVSDB_N_TYPES; i++) {
     170                 :            :             struct ovsdb_type *type;
     171                 :            : 
     172                 :      10506 :             types[i] = type = xmalloc(sizeof *type);
     173                 :      10506 :             ovsdb_base_type_init(&type->key, i);
     174                 :      10506 :             ovsdb_base_type_init(&type->value, OVSDB_TYPE_VOID);
     175                 :      10506 :             type->n_min = 1;
     176                 :      10506 :             type->n_max = UINT_MAX;
     177                 :            :         }
     178                 :            : 
     179                 :       1751 :         ovsthread_once_done(&once);
     180                 :            :     }
     181                 :     164010 :     return types[atomic_type];
     182                 :            : }
     183                 :            : 
     184                 :            : void
     185                 :     676920 : ovsdb_base_type_clone(struct ovsdb_base_type *dst,
     186                 :            :                       const struct ovsdb_base_type *src)
     187                 :            : {
     188                 :     676920 :     *dst = *src;
     189                 :            : 
     190         [ +  + ]:     676920 :     if (src->enum_) {
     191                 :      20020 :         dst->enum_ = xmalloc(sizeof *dst->enum_);
     192                 :      20020 :         ovsdb_datum_clone(dst->enum_, src->enum_,
     193                 :            :                           ovsdb_base_type_get_enum_type(dst->type));
     194                 :            :     }
     195                 :            : 
     196   [ +  +  +  - ]:     676920 :     switch (dst->type) {
     197                 :            :     case OVSDB_TYPE_VOID:
     198                 :            :     case OVSDB_TYPE_INTEGER:
     199                 :            :     case OVSDB_TYPE_REAL:
     200                 :            :     case OVSDB_TYPE_BOOLEAN:
     201                 :     375835 :         break;
     202                 :            : 
     203                 :            :     case OVSDB_TYPE_STRING:
     204                 :     203423 :         break;
     205                 :            : 
     206                 :            :     case OVSDB_TYPE_UUID:
     207         [ +  + ]:      97662 :         if (dst->u.uuid.refTableName) {
     208                 :      34610 :             dst->u.uuid.refTableName = xstrdup(dst->u.uuid.refTableName);
     209                 :            :         }
     210                 :      97662 :         break;
     211                 :            : 
     212                 :            :     case OVSDB_N_TYPES:
     213                 :            :     default:
     214                 :          0 :         OVS_NOT_REACHED();
     215                 :            :     }
     216                 :     676920 : }
     217                 :            : 
     218                 :            : void
     219                 :    1226661 : ovsdb_base_type_destroy(struct ovsdb_base_type *base)
     220                 :            : {
     221         [ +  - ]:    1226661 :     if (base) {
     222         [ +  + ]:    1226661 :         if (base->enum_) {
     223                 :      40024 :             ovsdb_datum_destroy(base->enum_,
     224                 :            :                                 ovsdb_base_type_get_enum_type(base->type));
     225                 :      40024 :             free(base->enum_);
     226                 :            :         }
     227                 :            : 
     228   [ +  +  +  -  :    1226661 :         switch (base->type) {
                      - ]
     229                 :            :         case OVSDB_TYPE_VOID:
     230                 :            :         case OVSDB_TYPE_INTEGER:
     231                 :            :         case OVSDB_TYPE_REAL:
     232                 :            :         case OVSDB_TYPE_BOOLEAN:
     233                 :     686913 :             break;
     234                 :            : 
     235                 :            :         case OVSDB_TYPE_STRING:
     236                 :     406553 :             break;
     237                 :            : 
     238                 :            :         case OVSDB_TYPE_UUID:
     239                 :     133195 :             free(base->u.uuid.refTableName);
     240                 :     133195 :             break;
     241                 :            : 
     242                 :            :         case OVSDB_N_TYPES:
     243                 :          0 :             OVS_NOT_REACHED();
     244                 :            : 
     245                 :            :         default:
     246                 :          0 :             OVS_NOT_REACHED();
     247                 :            :         }
     248                 :            :     }
     249                 :    1226661 : }
     250                 :            : 
     251                 :            : bool
     252                 :     506776 : ovsdb_base_type_is_valid(const struct ovsdb_base_type *base)
     253                 :            : {
     254   [ +  +  +  +  :     506776 :     switch (base->type) {
                +  +  - ]
     255                 :            :     case OVSDB_TYPE_VOID:
     256                 :     186394 :         return true;
     257                 :            : 
     258                 :            :     case OVSDB_TYPE_INTEGER:
     259                 :      83101 :         return base->u.integer.min <= base->u.integer.max;
     260                 :            : 
     261                 :            :     case OVSDB_TYPE_REAL:
     262                 :        415 :         return base->u.real.min <= base->u.real.max;
     263                 :            : 
     264                 :            :     case OVSDB_TYPE_BOOLEAN:
     265                 :       5135 :         return true;
     266                 :            : 
     267                 :            :     case OVSDB_TYPE_STRING:
     268                 :     191291 :         return base->u.string.minLen <= base->u.string.maxLen;
     269                 :            : 
     270                 :            :     case OVSDB_TYPE_UUID:
     271                 :      40440 :         return true;
     272                 :            : 
     273                 :            :     case OVSDB_N_TYPES:
     274                 :            :     default:
     275                 :          0 :         return false;
     276                 :            :     }
     277                 :            : }
     278                 :            : 
     279                 :            : bool
     280                 :    1663352 : ovsdb_base_type_has_constraints(const struct ovsdb_base_type *base)
     281                 :            : {
     282         [ +  + ]:    1663352 :     if (base->enum_) {
     283                 :      89802 :         return true;
     284                 :            :     }
     285                 :            : 
     286   [ -  +  +  +  :    1573550 :     switch (base->type) {
             +  +  -  - ]
     287                 :            :     case OVSDB_TYPE_VOID:
     288                 :          0 :         OVS_NOT_REACHED();
     289                 :            : 
     290                 :            :     case OVSDB_TYPE_INTEGER:
     291                 :     383162 :         return (base->u.integer.min != INT64_MIN
     292 [ +  + ][ +  + ]:     383162 :                 || base->u.integer.max != INT64_MAX);
     293                 :            : 
     294                 :            :     case OVSDB_TYPE_REAL:
     295                 :        631 :         return (base->u.real.min != -DBL_MAX
     296 [ +  + ][ +  + ]:        631 :                 || base->u.real.max != DBL_MAX);
     297                 :            : 
     298                 :            :     case OVSDB_TYPE_BOOLEAN:
     299                 :     142504 :         return false;
     300                 :            : 
     301                 :            :     case OVSDB_TYPE_STRING:
     302 [ +  + ][ +  + ]:     889353 :         return base->u.string.minLen != 0 || base->u.string.maxLen != UINT_MAX;
     303                 :            : 
     304                 :            :     case OVSDB_TYPE_UUID:
     305                 :     157900 :         return base->u.uuid.refTableName != NULL;
     306                 :            : 
     307                 :            :     case OVSDB_N_TYPES:
     308                 :          0 :         OVS_NOT_REACHED();
     309                 :            : 
     310                 :            :     default:
     311                 :          0 :         OVS_NOT_REACHED();
     312                 :            :     }
     313                 :            : }
     314                 :            : 
     315                 :            : void
     316                 :       2198 : ovsdb_base_type_clear_constraints(struct ovsdb_base_type *base)
     317                 :            : {
     318                 :       2198 :     enum ovsdb_atomic_type type = base->type;
     319                 :       2198 :     ovsdb_base_type_destroy(base);
     320                 :       2198 :     ovsdb_base_type_init(base, type);
     321                 :       2198 : }
     322                 :            : 
     323                 :            : static struct ovsdb_error *
     324                 :      20056 : parse_optional_uint(struct ovsdb_parser *parser, const char *member,
     325                 :            :                     unsigned int *uint)
     326                 :            : {
     327                 :            :     const struct json *json;
     328                 :            : 
     329                 :      20056 :     json = ovsdb_parser_member(parser, member, OP_INTEGER | OP_OPTIONAL);
     330         [ +  + ]:      20056 :     if (json) {
     331 [ +  + ][ -  + ]:          9 :         if (json->u.integer < 0 || json->u.integer > UINT_MAX) {
     332                 :          1 :             return ovsdb_syntax_error(json, NULL,
     333                 :            :                                       "%s out of valid range 0 to %u",
     334                 :            :                                       member, UINT_MAX);
     335                 :            :         }
     336                 :          8 :         *uint = json->u.integer;
     337                 :            :     }
     338                 :      20055 :     return NULL;
     339                 :            : }
     340                 :            : 
     341                 :            : struct ovsdb_error *
     342                 :     341230 : ovsdb_base_type_from_json(struct ovsdb_base_type *base,
     343                 :            :                           const struct json *json)
     344                 :            : {
     345                 :            :     struct ovsdb_parser parser;
     346                 :            :     struct ovsdb_error *error;
     347                 :            :     const struct json *type, *enum_;
     348                 :            : 
     349         [ +  + ]:     341230 :     if (json->type == JSON_STRING) {
     350                 :     224836 :         error = ovsdb_atomic_type_from_json(&base->type, json);
     351         [ +  + ]:     224836 :         if (error) {
     352                 :          2 :             return error;
     353                 :            :         }
     354                 :     224834 :         ovsdb_base_type_init(base, base->type);
     355                 :     224834 :         return NULL;
     356                 :            :     }
     357                 :            : 
     358                 :     116394 :     ovsdb_parser_init(&parser, json, "ovsdb type");
     359                 :     116394 :     type = ovsdb_parser_member(&parser, "type", OP_STRING);
     360         [ +  + ]:     116394 :     if (ovsdb_parser_has_error(&parser)) {
     361                 :          1 :         base->type = OVSDB_TYPE_VOID;
     362                 :          1 :         return ovsdb_parser_finish(&parser);
     363                 :            :     }
     364                 :            : 
     365                 :     116393 :     error = ovsdb_atomic_type_from_json(&base->type, type);
     366         [ -  + ]:     116393 :     if (error) {
     367                 :          0 :         return error;
     368                 :            :     }
     369                 :            : 
     370                 :     116393 :     ovsdb_base_type_init(base, base->type);
     371                 :            : 
     372                 :     116393 :     enum_ = ovsdb_parser_member(&parser, "enum", OP_ANY | OP_OPTIONAL);
     373         [ +  + ]:     116393 :     if (enum_) {
     374                 :      20030 :         base->enum_ = xmalloc(sizeof *base->enum_);
     375                 :      20030 :         error = ovsdb_datum_from_json(
     376                 :            :             base->enum_, ovsdb_base_type_get_enum_type(base->type),
     377                 :            :             enum_, NULL);
     378         [ -  + ]:      20030 :         if (error) {
     379                 :          0 :             free(base->enum_);
     380                 :      20030 :             base->enum_ = NULL;
     381                 :            :         }
     382         [ +  + ]:      96363 :     } else if (base->type == OVSDB_TYPE_INTEGER) {
     383                 :            :         const struct json *min, *max;
     384                 :            : 
     385                 :      49535 :         min = ovsdb_parser_member(&parser, "minInteger",
     386                 :            :                                   OP_INTEGER | OP_OPTIONAL);
     387                 :      49535 :         max = ovsdb_parser_member(&parser, "maxInteger",
     388                 :            :                                   OP_INTEGER | OP_OPTIONAL);
     389         [ +  + ]:      49535 :         base->u.integer.min = min ? min->u.integer : INT64_MIN;
     390         [ +  + ]:      49535 :         base->u.integer.max = max ? max->u.integer : INT64_MAX;
     391         [ +  + ]:      49535 :         if (base->u.integer.min > base->u.integer.max) {
     392                 :      49535 :             error = ovsdb_syntax_error(json, NULL,
     393                 :            :                                        "minInteger exceeds maxInteger");
     394                 :            :         }
     395         [ +  + ]:      46828 :     } else if (base->type == OVSDB_TYPE_REAL) {
     396                 :            :         const struct json *min, *max;
     397                 :            : 
     398                 :          9 :         min = ovsdb_parser_member(&parser, "minReal", OP_NUMBER | OP_OPTIONAL);
     399                 :          9 :         max = ovsdb_parser_member(&parser, "maxReal", OP_NUMBER | OP_OPTIONAL);
     400         [ +  + ]:          9 :         base->u.real.min = min ? json_real(min) : -DBL_MAX;
     401         [ +  + ]:          9 :         base->u.real.max = max ? json_real(max) : DBL_MAX;
     402         [ +  + ]:          9 :         if (base->u.real.min > base->u.real.max) {
     403                 :          9 :             error = ovsdb_syntax_error(json, NULL, "minReal exceeds maxReal");
     404                 :            :         }
     405         [ +  + ]:      46819 :     } else if (base->type == OVSDB_TYPE_STRING) {
     406         [ +  - ]:      10028 :         if (!error) {
     407                 :      10028 :             error = parse_optional_uint(&parser, "minLength",
     408                 :            :                                         &base->u.string.minLen);
     409                 :            :         }
     410         [ +  - ]:      10028 :         if (!error) {
     411                 :      10028 :             error = parse_optional_uint(&parser, "maxLength",
     412                 :            :                                         &base->u.string.maxLen);
     413                 :            :         }
     414 [ +  + ][ +  + ]:      10028 :         if (!error && base->u.string.minLen > base->u.string.maxLen) {
     415                 :      10028 :             error = ovsdb_syntax_error(json, NULL,
     416                 :            :                                        "minLength exceeds maxLength");
     417                 :            :         }
     418         [ +  + ]:      36791 :     } else if (base->type == OVSDB_TYPE_UUID) {
     419                 :            :         const struct json *refTable;
     420                 :            : 
     421                 :      34738 :         refTable = ovsdb_parser_member(&parser, "refTable",
     422                 :            :                                        OP_ID | OP_OPTIONAL);
     423         [ +  + ]:      34738 :         if (refTable) {
     424                 :            :             const struct json *refType;
     425                 :            : 
     426                 :      34556 :             base->u.uuid.refTableName = xstrdup(refTable->u.string);
     427                 :            : 
     428                 :            :             /* We can't set base->u.uuid.refTable here because we don't have
     429                 :            :              * enough context (we might not even be running in ovsdb-server).
     430                 :            :              * ovsdb_create() will set refTable later. */
     431                 :            : 
     432                 :      34556 :             refType = ovsdb_parser_member(&parser, "refType",
     433                 :            :                                           OP_ID | OP_OPTIONAL);
     434         [ +  + ]:      34556 :             if (refType) {
     435                 :       5568 :                 const char *refType_s = json_string(refType);
     436         [ +  + ]:       5568 :                 if (!strcmp(refType_s, "strong")) {
     437                 :        531 :                     base->u.uuid.refType = OVSDB_REF_STRONG;
     438         [ +  - ]:       5037 :                 } else if (!strcmp(refType_s, "weak")) {
     439                 :       5037 :                     base->u.uuid.refType = OVSDB_REF_WEAK;
     440                 :            :                 } else {
     441                 :       5568 :                     error = ovsdb_syntax_error(json, NULL, "refType must be "
     442                 :            :                                                "\"strong\" or \"weak\" (not "
     443                 :            :                                                "\"%s\")", refType_s);
     444                 :            :                 }
     445                 :            :             } else {
     446                 :      28988 :                 base->u.uuid.refType = OVSDB_REF_STRONG;
     447                 :            :             }
     448                 :            :         }
     449                 :            :     }
     450                 :            : 
     451         [ +  + ]:     116393 :     if (error) {
     452                 :          4 :         ovsdb_error_destroy(ovsdb_parser_finish(&parser));
     453                 :            :     } else {
     454                 :     116389 :         error = ovsdb_parser_finish(&parser);
     455                 :            :     }
     456         [ +  + ]:     116393 :     if (error) {
     457                 :          5 :         ovsdb_base_type_destroy(base);
     458                 :          5 :         base->type = OVSDB_TYPE_VOID;
     459                 :            :     }
     460                 :     341230 :     return error;
     461                 :            : }
     462                 :            : 
     463                 :            : struct json *
     464                 :    1401654 : ovsdb_base_type_to_json(const struct ovsdb_base_type *base)
     465                 :            : {
     466                 :            :     struct json *json;
     467                 :            : 
     468         [ +  + ]:    1401654 :     if (!ovsdb_base_type_has_constraints(base)) {
     469                 :     987254 :         return json_string_create(ovsdb_atomic_type_to_string(base->type));
     470                 :            :     }
     471                 :            : 
     472                 :     414400 :     json = json_object_create();
     473                 :     414400 :     json_object_put_string(json, "type",
     474                 :            :                            ovsdb_atomic_type_to_string(base->type));
     475                 :            : 
     476         [ +  + ]:     414400 :     if (base->enum_) {
     477                 :            :         const struct ovsdb_type *type;
     478                 :            : 
     479                 :      83918 :         type = ovsdb_base_type_get_enum_type(base->type);
     480                 :      83918 :         json_object_put(json, "enum", ovsdb_datum_to_json(base->enum_, type));
     481                 :            :     }
     482                 :            : 
     483   [ -  +  +  +  :     414400 :     switch (base->type) {
             +  +  -  - ]
     484                 :            :     case OVSDB_TYPE_VOID:
     485                 :          0 :         OVS_NOT_REACHED();
     486                 :            : 
     487                 :            :     case OVSDB_TYPE_INTEGER:
     488         [ +  + ]:     189984 :         if (base->u.integer.min != INT64_MIN) {
     489                 :     189982 :             json_object_put(json, "minInteger",
     490                 :     189982 :                             json_integer_create(base->u.integer.min));
     491                 :            :         }
     492         [ +  + ]:     189984 :         if (base->u.integer.max != INT64_MAX) {
     493                 :     136298 :             json_object_put(json, "maxInteger",
     494                 :     136298 :                             json_integer_create(base->u.integer.max));
     495                 :            :         }
     496                 :     189984 :         break;
     497                 :            : 
     498                 :            :     case OVSDB_TYPE_REAL:
     499         [ +  + ]:          4 :         if (base->u.real.min != -DBL_MAX) {
     500                 :          2 :             json_object_put(json, "minReal",
     501                 :            :                             json_real_create(base->u.real.min));
     502                 :            :         }
     503         [ +  + ]:          4 :         if (base->u.real.max != DBL_MAX) {
     504                 :          2 :             json_object_put(json, "maxReal",
     505                 :            :                             json_real_create(base->u.real.max));
     506                 :            :         }
     507                 :          4 :         break;
     508                 :            : 
     509                 :            :     case OVSDB_TYPE_BOOLEAN:
     510                 :          1 :         break;
     511                 :            : 
     512                 :            :     case OVSDB_TYPE_STRING:
     513         [ +  + ]:      83917 :         if (base->u.string.minLen != 0) {
     514                 :          2 :             json_object_put(json, "minLength",
     515                 :          2 :                             json_integer_create(base->u.string.minLen));
     516                 :            :         }
     517         [ +  + ]:      83917 :         if (base->u.string.maxLen != UINT_MAX) {
     518                 :          2 :             json_object_put(json, "maxLength",
     519                 :          2 :                             json_integer_create(base->u.string.maxLen));
     520                 :            :         }
     521                 :      83917 :         break;
     522                 :            : 
     523                 :            :     case OVSDB_TYPE_UUID:
     524         [ +  + ]:     140494 :         if (base->u.uuid.refTableName) {
     525                 :     140493 :             json_object_put_string(json, "refTable",
     526                 :     140493 :                                    base->u.uuid.refTableName);
     527         [ +  + ]:     140493 :             if (base->u.uuid.refType == OVSDB_REF_WEAK) {
     528                 :      19904 :                 json_object_put_string(json, "refType", "weak");
     529                 :            :             }
     530                 :            :         }
     531                 :     140494 :         break;
     532                 :            : 
     533                 :            :     case OVSDB_N_TYPES:
     534                 :          0 :         OVS_NOT_REACHED();
     535                 :            : 
     536                 :            :     default:
     537                 :          0 :         OVS_NOT_REACHED();
     538                 :            :     }
     539                 :            : 
     540                 :     414400 :     return json;
     541                 :            : }
     542                 :            : 
     543                 :            : /* ovsdb_type */
     544                 :            : 
     545                 :            : void
     546                 :     338460 : ovsdb_type_clone(struct ovsdb_type *dst, const struct ovsdb_type *src)
     547                 :            : {
     548                 :     338460 :     ovsdb_base_type_clone(&dst->key, &src->key);
     549                 :     338460 :     ovsdb_base_type_clone(&dst->value, &src->value);
     550                 :     338460 :     dst->n_min = src->n_min;
     551                 :     338460 :     dst->n_max = src->n_max;
     552                 :     338460 : }
     553                 :            : 
     554                 :            : void
     555                 :     612204 : ovsdb_type_destroy(struct ovsdb_type *type)
     556                 :            : {
     557                 :     612204 :     ovsdb_base_type_destroy(&type->key);
     558                 :     612204 :     ovsdb_base_type_destroy(&type->value);
     559                 :     612204 : }
     560                 :            : 
     561                 :            : bool
     562                 :     253388 : ovsdb_type_is_valid(const struct ovsdb_type *type)
     563                 :            : {
     564                 :     253388 :     return (type->key.type != OVSDB_TYPE_VOID
     565         [ +  - ]:     253388 :             && ovsdb_base_type_is_valid(&type->key)
     566         [ +  - ]:     253388 :             && ovsdb_base_type_is_valid(&type->value)
     567         [ +  + ]:     253388 :             && type->n_min <= 1
     568 [ +  - ][ +  - ]:     506776 :             && type->n_max >= 1);
     569                 :            : }
     570                 :            : 
     571                 :            : static struct ovsdb_error *
     572                 :     343063 : n_from_json(const struct json *json, unsigned int *n)
     573                 :            : {
     574         [ +  + ]:     343063 :     if (!json) {
     575                 :      78986 :         return NULL;
     576         [ +  - ]:     264077 :     } else if (json->type == JSON_INTEGER
     577 [ +  + ][ +  - ]:     264077 :                && json->u.integer >= 0 && json->u.integer < UINT_MAX) {
     578                 :     264075 :         *n = json->u.integer;
     579                 :     264075 :         return NULL;
     580                 :            :     } else {
     581                 :          2 :         return ovsdb_syntax_error(json, NULL, "bad min or max value");
     582                 :            :     }
     583                 :            : }
     584                 :            : 
     585                 :            : char *
     586                 :         48 : ovsdb_type_to_english(const struct ovsdb_type *type)
     587                 :            : {
     588                 :         48 :     const char *key = ovsdb_atomic_type_to_string(type->key.type);
     589                 :         48 :     const char *value = ovsdb_atomic_type_to_string(type->value.type);
     590         [ +  + ]:         48 :     if (ovsdb_type_is_scalar(type)) {
     591                 :         37 :         return xstrdup(key);
     592                 :            :     } else {
     593                 :         11 :         struct ds s = DS_EMPTY_INITIALIZER;
     594         [ +  - ]:         11 :         ds_put_cstr(&s, ovsdb_type_is_set(type) ? "set" : "map");
     595         [ -  + ]:         11 :         if (type->n_max == UINT_MAX) {
     596         [ #  # ]:          0 :             if (type->n_min) {
     597                 :          0 :                 ds_put_format(&s, " of %u or more", type->n_min);
     598                 :            :             } else {
     599                 :          0 :                 ds_put_cstr(&s, " of");
     600                 :            :             }
     601         [ +  - ]:         11 :         } else if (type->n_min) {
     602                 :         11 :             ds_put_format(&s, " of %u to %u", type->n_min, type->n_max);
     603                 :            :         } else {
     604                 :          0 :             ds_put_format(&s, " of up to %u", type->n_max);
     605                 :            :         }
     606         [ +  - ]:         11 :         if (ovsdb_type_is_set(type)) {
     607                 :         11 :             ds_put_format(&s, " %ss", key);
     608                 :            :         } else {
     609                 :          0 :             ds_put_format(&s, " (%s, %s) pairs", key, value);
     610                 :            :         }
     611                 :         11 :         return ds_cstr(&s);
     612                 :            :     }
     613                 :            : }
     614                 :            : 
     615                 :            : struct ovsdb_error *
     616                 :     274249 : ovsdb_type_from_json(struct ovsdb_type *type, const struct json *json)
     617                 :            : {
     618                 :     274249 :     ovsdb_base_type_init(&type->value, OVSDB_TYPE_VOID);
     619                 :     274249 :     type->n_min = 1;
     620                 :     274249 :     type->n_max = 1;
     621                 :            : 
     622         [ +  + ]:     274249 :     if (json->type == JSON_STRING) {
     623                 :      53726 :         return ovsdb_base_type_from_json(&type->key, json);
     624         [ +  - ]:     220523 :     } else if (json->type == JSON_OBJECT) {
     625                 :            :         const struct json *key, *value, *min, *max;
     626                 :            :         struct ovsdb_error *error;
     627                 :            :         struct ovsdb_parser parser;
     628                 :            : 
     629                 :     220523 :         ovsdb_parser_init(&parser, json, "ovsdb type");
     630                 :     220523 :         key = ovsdb_parser_member(&parser, "key", OP_STRING | OP_OBJECT);
     631                 :     220523 :         value = ovsdb_parser_member(&parser, "value",
     632                 :            :                                     OP_STRING | OP_OBJECT | OP_OPTIONAL);
     633                 :     220523 :         min = ovsdb_parser_member(&parser, "min", OP_INTEGER | OP_OPTIONAL);
     634                 :     220523 :         max = ovsdb_parser_member(&parser, "max",
     635                 :            :                                   OP_INTEGER | OP_STRING | OP_OPTIONAL);
     636                 :     220523 :         error = ovsdb_parser_finish(&parser);
     637         [ +  + ]:     220523 :         if (error) {
     638                 :          2 :             return error;
     639                 :            :         }
     640                 :            : 
     641                 :     220521 :         error = ovsdb_base_type_from_json(&type->key, key);
     642         [ -  + ]:     220521 :         if (error) {
     643                 :          0 :             return error;
     644                 :            :         }
     645                 :            : 
     646         [ +  + ]:     220521 :         if (value) {
     647                 :      66919 :             error = ovsdb_base_type_from_json(&type->value, value);
     648         [ -  + ]:      66919 :             if (error) {
     649                 :          0 :                 return error;
     650                 :            :             }
     651                 :            :         }
     652                 :            : 
     653                 :     220521 :         error = n_from_json(min, &type->n_min);
     654         [ +  + ]:     220521 :         if (error) {
     655                 :          1 :             return error;
     656                 :            :         }
     657                 :            : 
     658 [ +  + ][ +  + ]:     220520 :         if (max && max->type == JSON_STRING
     659         [ +  - ]:      97978 :             && !strcmp(max->u.string, "unlimited")) {
     660                 :      97978 :             type->n_max = UINT_MAX;
     661                 :            :         } else {
     662                 :     122542 :             error = n_from_json(max, &type->n_max);
     663         [ +  + ]:     122542 :             if (error) {
     664                 :          1 :                 return error;
     665                 :            :             }
     666                 :            :         }
     667                 :            : 
     668         [ +  + ]:     220519 :         if (!ovsdb_type_is_valid(type)) {
     669                 :          2 :             return ovsdb_syntax_error(json, NULL,
     670                 :            :                                       "ovsdb type fails constraint checks");
     671                 :            :         }
     672                 :            : 
     673                 :     220523 :         return NULL;
     674                 :            :     } else {
     675                 :          0 :         return ovsdb_syntax_error(json, NULL, "ovsdb type expected");
     676                 :            :     }
     677                 :            : }
     678                 :            : 
     679                 :            : struct json *
     680                 :    1121819 : ovsdb_type_to_json(const struct ovsdb_type *type)
     681                 :            : {
     682         [ +  + ]:    1121819 :     if (ovsdb_type_is_scalar(type)
     683         [ +  + ]:     261698 :         && !ovsdb_base_type_has_constraints(&type->key)) {
     684                 :     213242 :         return ovsdb_base_type_to_json(&type->key);
     685                 :            :     } else {
     686                 :     908577 :         struct json *json = json_object_create();
     687                 :     908577 :         json_object_put(json, "key", ovsdb_base_type_to_json(&type->key));
     688         [ +  + ]:     908577 :         if (type->value.type != OVSDB_TYPE_VOID) {
     689                 :     279819 :             json_object_put(json, "value",
     690                 :            :                             ovsdb_base_type_to_json(&type->value));
     691                 :            :         }
     692         [ +  + ]:     908577 :         if (type->n_min != 1) {
     693                 :     839542 :             json_object_put(json, "min", json_integer_create(type->n_min));
     694                 :            :         }
     695         [ +  + ]:     908577 :         if (type->n_max == UINT_MAX) {
     696                 :     402263 :             json_object_put_string(json, "max", "unlimited");
     697         [ +  + ]:     506314 :         } else if (type->n_max != 1) {
     698                 :      23557 :             json_object_put(json, "max", json_integer_create(type->n_max));
     699                 :            :         }
     700                 :     908577 :         return json;
     701                 :            :     }
     702                 :            : }

Generated by: LCOV version 1.12