LCOV - code coverage report
Current view: top level - libsd - project.c (source / functions) Hit Total Coverage
Test: app.info Lines: 111 117 94.9 %
Date: 2015-08-29 Functions: 10 10 100.0 %

          Line data    Source code
       1             : // Copyright 2014 Bobby Powers. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style
       3             : // license that can be found in the LICENSE file.
       4             : 
       5             : #include <libgen.h>
       6             : #include <errno.h>
       7             : #include <stdbool.h>
       8             : #include <stdint.h>
       9             : #include <stdlib.h>
      10             : #include <string.h>
      11             : #include <fcntl.h>
      12             : #include <unistd.h>
      13             : #include <ctype.h>
      14             : 
      15             : #include "utf.h"
      16             : #include "sd.h"
      17             : #include "sd_internal.h"
      18             : 
      19             : 
      20             : #define INITIAL_CAP 8
      21             : 
      22             : 
      23             : static void file_free(File *f);
      24             : 
      25             : 
      26             : static const char *SD_ERROR_MSGS[] = {
      27             :         "no error",          // SD_ERR_NO_ERROR
      28             :         "no memory",         // SD_ERR_NOMEM
      29             :         "bad file",          // SD_ERR_BAD_FILE
      30             :         "unspecified error", // SD_ERR_UNSPECIFIED
      31             :         "bad XML",           // SD_ERR_BAD_XML
      32             :         "bad equation lex",  // SD_ERR_BAD_LEX
      33             :         "EOF",               // SD_ERR_EOF
      34             :         "circularity error", // SD_ERR_CIRCULAR
      35             : };
      36             : 
      37             : 
      38             : SDProject *
      39          20 : sd_project_open(const char *path, int *err)
      40             : {
      41          20 :         FILE *f = NULL;
      42             :         char *dir, *dir_str;
      43          20 :         SDProject *p = NULL;
      44             :         int parse_err;
      45             : 
      46          20 :         dir_str = strdup(path);
      47          20 :         dir = dirname(dir_str);
      48             : 
      49          20 :         f = fopen(path, "r");
      50          20 :         if (!f) {
      51           2 :                 if (err)
      52           2 :                         *err = SD_ERR_BAD_FILE;
      53           2 :                 goto error;
      54             :         }
      55             : 
      56          18 :         p = calloc(1, sizeof(*p));
      57          18 :         if (!p) {
      58           0 :                 if (err)
      59           0 :                         *err = SD_ERR_NOMEM;
      60           0 :                 goto error;
      61             :         }
      62          18 :         sd_project_ref(p);
      63             : 
      64          18 :         p->dir_path = strdup(dir);
      65             : 
      66          18 :         slice_make(&p->files, 0, INITIAL_CAP);
      67          18 :         if (!p->files.elems) {
      68           0 :                 if (err)
      69           0 :                         *err = SD_ERR_NOMEM;
      70           0 :                 goto error;
      71             :         }
      72             : 
      73          18 :         parse_err = project_parse_file(p, f);
      74          18 :         if (parse_err) {
      75           1 :                 if (err)
      76           1 :                         *err = SD_ERR_BAD_XML;
      77           1 :                 goto error;
      78             :         }
      79             : 
      80          17 :         free(dir_str);
      81          17 :         if (f)
      82          17 :                 fclose(f);
      83          17 :         return p;
      84             : 
      85             : error:
      86           3 :         free(dir_str);
      87           3 :         if (f)
      88           1 :                 fclose(f);
      89           3 :         sd_project_unref(p);
      90           3 :         return NULL;
      91             : }
      92             : 
      93             : void
      94          34 : sd_project_ref(SDProject *p)
      95             : {
      96          34 :         __sync_fetch_and_add(&p->refcount, 1);
      97          34 : }
      98             : 
      99             : void
     100          37 : sd_project_unref(SDProject *p)
     101             : {
     102          37 :         if (!p)
     103           3 :                 return;
     104          34 :         if (__sync_sub_and_fetch(&p->refcount, 1) == 0) {
     105          18 :                 free(p->dir_path);
     106          35 :                 for (size_t i = 0; i < p->files.len; ++i)
     107          17 :                         file_free(p->files.elems[i]);
     108          18 :                 free(p->files.elems);
     109          18 :                 free(p);
     110             :         }
     111             : }
     112             : 
     113             : SDModel *
     114          27 : sd_project_get_model(SDProject *p, const char *n)
     115             : {
     116          27 :         SDModel *m = NULL;
     117          27 :         if (!p)
     118           1 :                 goto out;
     119             : 
     120          28 :         for (size_t i = 0; i < p->files.len; i++) {
     121          26 :                 File *f = p->files.elems[i];
     122          37 :                 for (size_t j = 0; j < f->models.len; j++) {
     123          35 :                         m = f->models.elems[j];
     124             :                         // match root model
     125          35 :                         if (!m->name && !n)
     126             :                                 goto out;
     127             :                         // match named model
     128          16 :                         else if (m->name && n && strcmp(m->name, n) == 0)
     129           5 :                                 goto out;
     130          11 :                         m = NULL;
     131             :                 }
     132             :         }
     133             : out:
     134          27 :         sd_model_ref(m);
     135          27 :         return m;
     136             : }
     137             : 
     138             : int
     139          17 : project_add_file(SDProject *p, File *f)
     140             : {
     141          17 :         return slice_append(&p->files, f);
     142             : }
     143             : 
     144             : void
     145          17 : file_free(File *f)
     146             : {
     147          17 :         free(f->version);
     148          17 :         free(f->header.smile_version);
     149          17 :         free(f->header.smile_namespace);
     150          17 :         free(f->header.name);
     151          17 :         free(f->header.uuid);
     152          17 :         free(f->header.vendor);
     153          17 :         free(f->header.product.name);
     154          17 :         free(f->header.product.version);
     155          17 :         free(f->header.product.lang);
     156          17 :         free(f->sim_specs.method);
     157          17 :         free(f->sim_specs.time_units);
     158          38 :         for (size_t i = 0; i < f->models.len; ++i)
     159          21 :                 sd_model_unref(f->models.elems[i]);
     160          17 :         free(f->models.elems);
     161          17 :         free(f);
     162          17 : }
     163             : 
     164             : const char *
     165           2 : sd_error_str(int err)
     166             : {
     167           2 :         if (err < SD_ERR_NO_ERROR && err > SD_ERR_MIN)
     168           1 :                 return SD_ERROR_MSGS[-err];
     169           1 :         return "unknown error";
     170             : }
     171             : 
     172             : 
     173             : void
     174          48 : sd_model_ref(SDModel *m)
     175             : {
     176          48 :         if (!m)
     177           3 :                 return;
     178          45 :         __sync_fetch_and_add(&m->refcount, 1);
     179             : }
     180             : 
     181             : void
     182         296 : sd_model_unref(SDModel *m)
     183             : {
     184         296 :         if (!m)
     185         251 :                 return;
     186          45 :         if (__sync_sub_and_fetch(&m->refcount, 1) == 0) {
     187          21 :                 free(m->name);
     188         136 :                 for (size_t i = 0; i < m->vars.len; ++i)
     189         115 :                         var_free(m->vars.elems[i]);
     190          21 :                 free(m->vars.elems);
     191          21 :                 free(m);
     192             :         }
     193             : }
     194             : 
     195             : void
     196         255 : var_free(Var *v)
     197             : {
     198         255 :         if (!v)
     199         116 :                 return;
     200             : 
     201         151 :         for (size_t i = 0; i < v->inflows.len; ++i)
     202          12 :                 free(v->inflows.elems[i]);
     203         139 :         free(v->inflows.elems);
     204         155 :         for (size_t i = 0; i < v->outflows.len; ++i)
     205          16 :                 free(v->outflows.elems[i]);
     206         139 :         free(v->outflows.elems);
     207         147 :         for (size_t i = 0; i < v->conns.len; ++i) {
     208           8 :                 Var *ref = v->conns.elems[i];
     209           8 :                 var_free(ref);
     210             :         }
     211         139 :         free(v->conns.elems);
     212         139 :         free(v->name);
     213         139 :         free(v->eqn);
     214         139 :         free(v->src);
     215         139 :         free(v->gf);
     216         139 :         sd_model_unref(v->model);
     217         139 :         free(v);
     218             : }

Generated by: LCOV version 1.10