• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/libcroco/
1/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2
3/*
4 * This file is part of The Croco Library
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2.1 of the GNU General Public
8 * License as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 *
20 * Author: Dodji Seketeli
21 * See COPYRIGHTS file for copyright information.
22 */
23
24#include <config.h>
25#include <stdio.h>
26#include <string.h>
27#include "cr-term.h"
28#include "cr-num.h"
29#include "cr-parser.h"
30
31/**
32 *@file
33 *Definition of the #CRTem class.
34 */
35
36static void
37cr_term_clear (CRTerm * a_this)
38{
39        g_return_if_fail (a_this);
40
41        switch (a_this->type) {
42        case TERM_NUMBER:
43                if (a_this->content.num) {
44                        cr_num_destroy (a_this->content.num);
45                        a_this->content.num = NULL;
46                }
47                break;
48
49        case TERM_FUNCTION:
50                if (a_this->ext_content.func_param) {
51                        cr_term_destroy (a_this->ext_content.func_param);
52                        a_this->ext_content.func_param = NULL;
53                }
54        case TERM_STRING:
55        case TERM_IDENT:
56        case TERM_URI:
57        case TERM_HASH:
58                if (a_this->content.str) {
59                        cr_string_destroy (a_this->content.str);
60                        a_this->content.str = NULL;
61                }
62                break;
63
64        case TERM_RGB:
65                if (a_this->content.rgb) {
66                        cr_rgb_destroy (a_this->content.rgb);
67                        a_this->content.rgb = NULL;
68                }
69                break;
70
71        case TERM_UNICODERANGE:
72        case TERM_NO_TYPE:
73        default:
74                break;
75        }
76
77        a_this->type = TERM_NO_TYPE;
78}
79
80/**
81 *Instanciate a #CRTerm.
82 *@return the newly build instance
83 *of #CRTerm.
84 */
85CRTerm *
86cr_term_new (void)
87{
88        CRTerm *result = NULL;
89
90        result = g_try_malloc (sizeof (CRTerm));
91        if (!result) {
92                cr_utils_trace_info ("Out of memory");
93                return NULL;
94        }
95        memset (result, 0, sizeof (CRTerm));
96        return result;
97}
98
99/**
100 *Parses an expresion as defined by the css2 spec
101 *and builds the expression as a list of terms.
102 *@param a_buf the buffer to parse.
103 *@return a pointer to the first term of the expression or
104 *NULL if parsing failed.
105 */
106CRTerm *
107cr_term_parse_expression_from_buf (const guchar * a_buf,
108                                   enum CREncoding a_encoding)
109{
110        CRParser *parser = NULL;
111        CRTerm *result = NULL;
112        enum CRStatus status = CR_OK;
113
114        g_return_val_if_fail (a_buf, NULL);
115
116        parser = cr_parser_new_from_buf ((guchar*)a_buf, strlen (a_buf),
117                                         a_encoding, FALSE);
118        g_return_val_if_fail (parser, NULL);
119
120        status = cr_parser_try_to_skip_spaces_and_comments (parser);
121        if (status != CR_OK) {
122                goto cleanup;
123        }
124        status = cr_parser_parse_expr (parser, &result);
125        if (status != CR_OK) {
126                if (result) {
127                        cr_term_destroy (result);
128                        result = NULL;
129                }
130        }
131
132      cleanup:
133        if (parser) {
134                cr_parser_destroy (parser);
135                parser = NULL;
136        }
137
138        return result;
139}
140
141enum CRStatus
142cr_term_set_number (CRTerm * a_this, CRNum * a_num)
143{
144        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
145
146        cr_term_clear (a_this);
147
148        a_this->type = TERM_NUMBER;
149        a_this->content.num = a_num;
150        return CR_OK;
151}
152
153enum CRStatus
154cr_term_set_function (CRTerm * a_this, CRString * a_func_name,
155                      CRTerm * a_func_param)
156{
157        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
158
159        cr_term_clear (a_this);
160
161        a_this->type = TERM_FUNCTION;
162        a_this->content.str = a_func_name;
163        a_this->ext_content.func_param = a_func_param;
164        return CR_OK;
165}
166
167enum CRStatus
168cr_term_set_string (CRTerm * a_this, CRString * a_str)
169{
170        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
171
172        cr_term_clear (a_this);
173
174        a_this->type = TERM_STRING;
175        a_this->content.str = a_str;
176        return CR_OK;
177}
178
179enum CRStatus
180cr_term_set_ident (CRTerm * a_this, CRString * a_str)
181{
182        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
183
184        cr_term_clear (a_this);
185
186        a_this->type = TERM_IDENT;
187        a_this->content.str = a_str;
188        return CR_OK;
189}
190
191enum CRStatus
192cr_term_set_uri (CRTerm * a_this, CRString * a_str)
193{
194        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
195
196        cr_term_clear (a_this);
197
198        a_this->type = TERM_URI;
199        a_this->content.str = a_str;
200        return CR_OK;
201}
202
203enum CRStatus
204cr_term_set_rgb (CRTerm * a_this, CRRgb * a_rgb)
205{
206        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
207
208        cr_term_clear (a_this);
209
210        a_this->type = TERM_RGB;
211        a_this->content.rgb = a_rgb;
212        return CR_OK;
213}
214
215enum CRStatus
216cr_term_set_hash (CRTerm * a_this, CRString * a_str)
217{
218        g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
219
220        cr_term_clear (a_this);
221
222        a_this->type = TERM_HASH;
223        a_this->content.str = a_str;
224        return CR_OK;
225}
226
227/**
228 *Appends a new term to the current list of #CRTerm.
229 *
230 *@param a_this the "this pointer" of the current instance
231 *of #CRTerm .
232 *@param a_new_term the term to append.
233 *@return the list of terms with the a_new_term appended to it.
234 */
235CRTerm *
236cr_term_append_term (CRTerm * a_this, CRTerm * a_new_term)
237{
238        CRTerm *cur = NULL;
239
240        g_return_val_if_fail (a_new_term, NULL);
241
242        if (a_this == NULL)
243                return a_new_term;
244
245        for (cur = a_this; cur->next; cur = cur->next) ;
246
247        cur->next = a_new_term;
248        a_new_term->prev = cur;
249
250        return a_this;
251}
252
253/**
254 *Prepends a term to the list of terms represented by a_this.
255 *
256 *@param a_this the "this pointer" of the current instance of
257 *#CRTerm .
258 *@param a_new_term the term to prepend.
259 *@return the head of the new list.
260 */
261CRTerm *
262cr_term_prepend_term (CRTerm * a_this, CRTerm * a_new_term)
263{
264        g_return_val_if_fail (a_this && a_new_term, NULL);
265
266        a_new_term->next = a_this;
267        a_this->prev = a_new_term;
268
269        return a_new_term;
270}
271
272/**
273 *Serializes the expression represented by
274 *the chained instances of #CRterm.
275 *@param a_this the current instance of #CRTerm
276 *@return the zero terminated string containing the serialized
277 *form of #CRTerm. MUST BE FREED BY THE CALLER using g_free().
278 */
279guchar *
280cr_term_to_string (CRTerm * a_this)
281{
282        GString *str_buf = NULL;
283        CRTerm *cur = NULL;
284        guchar *result = NULL,
285                *content = NULL;
286
287        g_return_val_if_fail (a_this, NULL);
288
289        str_buf = g_string_new (NULL);
290        g_return_val_if_fail (str_buf, NULL);
291
292        for (cur = a_this; cur; cur = cur->next) {
293                if ((cur->content.str == NULL)
294                    && (cur->content.num == NULL)
295                    && (cur->content.str == NULL)
296                    && (cur->content.rgb == NULL))
297                        continue;
298
299                switch (cur->the_operator) {
300                case DIVIDE:
301                        g_string_append (str_buf, " / ");
302                        break;
303
304                case COMMA:
305                        g_string_append (str_buf, ", ");
306                        break;
307
308                case NO_OP:
309                        if (cur->prev) {
310                                g_string_append (str_buf, " ");
311                        }
312                        break;
313                default:
314
315                        break;
316                }
317
318                switch (cur->unary_op) {
319                case PLUS_UOP:
320                        g_string_append (str_buf, "+");
321                        break;
322
323                case MINUS_UOP:
324                        g_string_append (str_buf, "-");
325                        break;
326
327                default:
328                        break;
329                }
330
331                switch (cur->type) {
332                case TERM_NUMBER:
333                        if (cur->content.num) {
334                                content = cr_num_to_string (cur->content.num);
335                        }
336
337                        if (content) {
338                                g_string_append (str_buf, content);
339                                g_free (content);
340                                content = NULL;
341                        }
342
343                        break;
344
345                case TERM_FUNCTION:
346                        if (cur->content.str) {
347                                content = g_strndup
348                                        (cur->content.str->stryng->str,
349                                         cur->content.str->stryng->len);
350                        }
351
352                        if (content) {
353                                g_string_append_printf (str_buf, "%s(",
354                                                        content);
355
356                                if (cur->ext_content.func_param) {
357                                        guchar *tmp_str = NULL;
358
359                                        tmp_str = cr_term_to_string
360                                                (cur->
361                                                 ext_content.func_param);
362
363                                        if (tmp_str) {
364                                                g_string_append (str_buf,
365								 tmp_str);
366                                                g_free (tmp_str);
367                                                tmp_str = NULL;
368                                        }
369
370                                        g_free (content);
371                                        content = NULL;
372                                }
373                                g_string_append (str_buf, ")");
374                        }
375
376                        break;
377
378                case TERM_STRING:
379                        if (cur->content.str) {
380                                content = g_strndup
381                                        (cur->content.str->stryng->str,
382                                         cur->content.str->stryng->len);
383                        }
384
385                        if (content) {
386                                g_string_append_printf (str_buf,
387                                                        "\"%s\"", content);
388                                g_free (content);
389                                content = NULL;
390                        }
391                        break;
392
393                case TERM_IDENT:
394                        if (cur->content.str) {
395                                content = g_strndup
396                                        (cur->content.str->stryng->str,
397                                         cur->content.str->stryng->len);
398                        }
399
400                        if (content) {
401                                g_string_append (str_buf, content);
402                                g_free (content);
403                                content = NULL;
404                        }
405                        break;
406
407                case TERM_URI:
408                        if (cur->content.str) {
409                                content = g_strndup
410                                        (cur->content.str->stryng->str,
411                                         cur->content.str->stryng->len);
412                        }
413
414                        if (content) {
415                                g_string_append_printf
416                                        (str_buf, "url(%s)", content);
417                                g_free (content);
418                                content = NULL;
419                        }
420                        break;
421
422                case TERM_RGB:
423                        if (cur->content.rgb) {
424                                guchar *tmp_str = NULL;
425
426                                g_string_append (str_buf, "rgb(");
427                                tmp_str = cr_rgb_to_string (cur->content.rgb);
428
429                                if (tmp_str) {
430                                        g_string_append (str_buf, tmp_str);
431                                        g_free (tmp_str);
432                                        tmp_str = NULL;
433                                }
434                                g_string_append (str_buf, ")");
435                        }
436
437                        break;
438
439                case TERM_UNICODERANGE:
440                        g_string_append
441                                (str_buf,
442                                 "?found unicoderange: dump not supported yet?");
443                        break;
444
445                case TERM_HASH:
446                        if (cur->content.str) {
447                                content = g_strndup
448                                        (cur->content.str->stryng->str,
449                                         cur->content.str->stryng->len);
450                        }
451
452                        if (content) {
453                                g_string_append_printf (str_buf,
454                                                        "#%s", content);
455                                g_free (content);
456                                content = NULL;
457                        }
458                        break;
459
460                default:
461                        g_string_append (str_buf,
462                                         "Unrecognized Term type");
463                        break;
464                }
465        }
466
467        if (str_buf) {
468                result = str_buf->str;
469                g_string_free (str_buf, FALSE);
470                str_buf = NULL;
471        }
472
473        return result;
474}
475
476guchar *
477cr_term_one_to_string (CRTerm * a_this)
478{
479        GString *str_buf = NULL;
480        guchar *result = NULL,
481                *content = NULL;
482
483        g_return_val_if_fail (a_this, NULL);
484
485        str_buf = g_string_new (NULL);
486        g_return_val_if_fail (str_buf, NULL);
487
488        if ((a_this->content.str == NULL)
489            && (a_this->content.num == NULL)
490            && (a_this->content.str == NULL)
491            && (a_this->content.rgb == NULL))
492                return NULL ;
493
494        switch (a_this->the_operator) {
495        case DIVIDE:
496                g_string_append_printf (str_buf, " / ");
497                break;
498
499        case COMMA:
500                g_string_append_printf (str_buf, ", ");
501                break;
502
503        case NO_OP:
504                if (a_this->prev) {
505                        g_string_append_printf (str_buf, " ");
506                }
507                break;
508        default:
509
510                break;
511        }
512
513        switch (a_this->unary_op) {
514        case PLUS_UOP:
515                g_string_append_printf (str_buf, "+");
516                break;
517
518        case MINUS_UOP:
519                g_string_append_printf (str_buf, "-");
520                break;
521
522        default:
523                break;
524        }
525
526        switch (a_this->type) {
527        case TERM_NUMBER:
528                if (a_this->content.num) {
529                        content = cr_num_to_string (a_this->content.num);
530                }
531
532                if (content) {
533                        g_string_append (str_buf, content);
534                        g_free (content);
535                        content = NULL;
536                }
537
538                break;
539
540        case TERM_FUNCTION:
541                if (a_this->content.str) {
542                        content = g_strndup
543                                (a_this->content.str->stryng->str,
544                                 a_this->content.str->stryng->len);
545                }
546
547                if (content) {
548                        g_string_append_printf (str_buf, "%s(",
549                                                content);
550
551                        if (a_this->ext_content.func_param) {
552                                guchar *tmp_str = NULL;
553
554                                tmp_str = cr_term_to_string
555                                        (a_this->
556                                         ext_content.func_param);
557
558                                if (tmp_str) {
559                                        g_string_append_printf
560                                                (str_buf,
561                                                 "%s", tmp_str);
562                                        g_free (tmp_str);
563                                        tmp_str = NULL;
564                                }
565
566                                g_string_append_printf (str_buf, ")");
567                                g_free (content);
568                                content = NULL;
569                        }
570                }
571
572                break;
573
574        case TERM_STRING:
575                if (a_this->content.str) {
576                        content = g_strndup
577                                (a_this->content.str->stryng->str,
578                                 a_this->content.str->stryng->len);
579                }
580
581                if (content) {
582                        g_string_append_printf (str_buf,
583                                                "\"%s\"", content);
584                        g_free (content);
585                        content = NULL;
586                }
587                break;
588
589        case TERM_IDENT:
590                if (a_this->content.str) {
591                        content = g_strndup
592                                (a_this->content.str->stryng->str,
593                                 a_this->content.str->stryng->len);
594                }
595
596                if (content) {
597                        g_string_append (str_buf, content);
598                        g_free (content);
599                        content = NULL;
600                }
601                break;
602
603        case TERM_URI:
604                if (a_this->content.str) {
605                        content = g_strndup
606                                (a_this->content.str->stryng->str,
607                                 a_this->content.str->stryng->len);
608                }
609
610                if (content) {
611                        g_string_append_printf
612                                (str_buf, "url(%s)", content);
613                        g_free (content);
614                        content = NULL;
615                }
616                break;
617
618        case TERM_RGB:
619                if (a_this->content.rgb) {
620                        guchar *tmp_str = NULL;
621
622                        g_string_append_printf (str_buf, "rgb(");
623                        tmp_str = cr_rgb_to_string (a_this->content.rgb);
624
625                        if (tmp_str) {
626                                g_string_append (str_buf, tmp_str);
627                                g_free (tmp_str);
628                                tmp_str = NULL;
629                        }
630                        g_string_append_printf (str_buf, ")");
631                }
632
633                break;
634
635        case TERM_UNICODERANGE:
636                g_string_append_printf
637                        (str_buf,
638                         "?found unicoderange: dump not supported yet?");
639                break;
640
641        case TERM_HASH:
642                if (a_this->content.str) {
643                        content = g_strndup
644                                (a_this->content.str->stryng->str,
645                                 a_this->content.str->stryng->len);
646                }
647
648                if (content) {
649                        g_string_append_printf (str_buf,
650                                                "#%s", content);
651                        g_free (content);
652                        content = NULL;
653                }
654                break;
655
656        default:
657                g_string_append_printf (str_buf,
658                                        "%s",
659                                        "Unrecognized Term type");
660                break;
661        }
662
663        if (str_buf) {
664                result = str_buf->str;
665                g_string_free (str_buf, FALSE);
666                str_buf = NULL;
667        }
668
669        return result;
670}
671
672/**
673 *Dumps the expression (a list of terms connected by operators)
674 *to a file.
675 *TODO: finish the dump. The dump of some type of terms have not yet been
676 *implemented.
677 *@param a_this the current instance of #CRTerm.
678 *@param a_fp the destination file pointer.
679 */
680void
681cr_term_dump (CRTerm * a_this, FILE * a_fp)
682{
683        guchar *content = NULL;
684
685        g_return_if_fail (a_this);
686
687        content = cr_term_to_string (a_this);
688
689        if (content) {
690                fprintf (a_fp, "%s", content);
691                g_free (content);
692        }
693}
694
695/**
696 *Return the number of terms in the expression.
697 *@param a_this the current instance of #CRTerm.
698 *@return number of terms in the expression.
699 */
700int
701cr_term_nr_values (CRTerm *a_this)
702{
703	CRTerm *cur = NULL ;
704	int nr = 0;
705
706	g_return_val_if_fail (a_this, -1) ;
707
708	for (cur = a_this ; cur ; cur = cur->next)
709		nr ++;
710	return nr;
711}
712
713/**
714 *Use an index to get a CRTerm from the expression.
715 *@param a_this the current instance of #CRTerm.
716 *@param itemnr the index into the expression.
717 *@return CRTerm at position itemnr, if itemnr > number of terms - 1,
718 *it will return NULL.
719 */
720CRTerm *
721cr_term_get_from_list (CRTerm *a_this, int itemnr)
722{
723	CRTerm *cur = NULL ;
724	int nr = 0;
725
726	g_return_val_if_fail (a_this, NULL) ;
727
728	for (cur = a_this ; cur ; cur = cur->next)
729		if (nr++ == itemnr)
730			return cur;
731	return NULL;
732}
733
734/**
735 *Increments the reference counter of the current instance
736 *of #CRTerm.*
737 *@param a_this the current instance of #CRTerm.
738 */
739void
740cr_term_ref (CRTerm * a_this)
741{
742        g_return_if_fail (a_this);
743
744        a_this->ref_count++;
745}
746
747/**
748 *Decrements the ref count of the current instance of
749 *#CRTerm. If the ref count reaches zero, the instance is
750 *destroyed.
751 *@param a_this the current instance of #CRTerm.
752 *@return TRUE if the current instance has been destroyed, FALSE otherwise.
753 */
754gboolean
755cr_term_unref (CRTerm * a_this)
756{
757        g_return_val_if_fail (a_this, FALSE);
758
759        if (a_this->ref_count) {
760                a_this->ref_count--;
761        }
762
763        if (a_this->ref_count == 0) {
764                cr_term_destroy (a_this);
765                return TRUE;
766        }
767
768        return FALSE;
769}
770
771/**
772 *The destructor of the the #CRTerm class.
773 *@param a_this the "this pointer" of the current instance
774 *of #CRTerm.
775 */
776void
777cr_term_destroy (CRTerm * a_this)
778{
779        g_return_if_fail (a_this);
780
781        cr_term_clear (a_this);
782
783        if (a_this->next) {
784                cr_term_destroy (a_this->next);
785                a_this->next = NULL;
786        }
787
788        if (a_this) {
789                g_free (a_this);
790        }
791
792}
793