1/**
2 * \file
3 * \brief Set of default filters for terminal client library.
4 */
5
6/*
7 * Copyright (c) 2012, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
13 * Attn: Systems Group.
14 */
15
16#include <assert.h>
17#include <stdbool.h>
18#include <stdlib.h>
19
20#include <term/client/default_filters.h>
21
22/* internal functions */
23static bool is_ctrlhat(char c);
24
25/**
26 * \brief Translate carriage return (\r) to line feed (\n).
27 *
28 * \param data   in:  characters before translation
29 *               out: characters after tnaslation
30 * \param length in:  length before translation
31 *               out: length after translation
32 */
33void term_filter_cr2lf(char **data, size_t *length)
34{
35    assert((data != NULL) && (*data != NULL));
36    assert(length != NULL);
37
38    for (int i = 0; i < *length; i++) {
39        if ((*data)[i] == '\r') {
40            (*data)[i] = '\n';
41        }
42    }
43}
44
45/**
46 * \brief Translate ASCII control characters (ASCII characters in the range
47 *        0x00 - 0x1f), other than ASCII TAB, ASCII NL, ASCII CR and ASCII BS to
48 *        ^X, where X is the character formed by adding 0x40 to the control
49 *        character.
50 *
51 * \param data   in:  characters before translation
52 *               out: characters after tnaslation
53 * \param length in:  length before translation
54 *               out: length after translation
55 */
56void term_filter_ctrlhat(char **data, size_t *length)
57{
58    size_t additional_length = 0;
59    size_t new_length = 0;
60    char *new_data = NULL;
61
62    assert((data != NULL) && (*data != NULL));
63    assert(length != NULL);
64
65    /* calculate new lenght */
66    for (int i = 0; i < *length; i++) {
67        if (is_ctrlhat((*data)[i])) {
68            additional_length++;
69        }
70    }
71
72    /* if no translation necessary, bail out */
73    if (additional_length == 0) {
74        return;
75    }
76    new_length = *length + additional_length;
77
78    /* allocate space for translated data */
79    new_data = malloc(sizeof(char) * new_length);
80    assert(new_data != NULL);
81
82    /* translate characters */
83    char *c = *data;
84    for (int i = 0; i < new_length; ) {
85        if (is_ctrlhat(*c)) {
86            new_data[i++] = '^';
87            new_data[i++] = (*c) + 0x40;
88        } else {
89            new_data[i++] = *c;
90        }
91    }
92
93    free(*data);
94    *data = new_data;
95    *length = new_length;
96}
97
98/**
99 * \brief Translate line feed (\n) to carriage return plus line feed (\r\n).
100 * \param data   in:  characters before translation
101 *               out: characters after tnaslation
102 * \param length in:  length before translation
103 *               out: length after translation
104 */
105void term_filter_lf2crlf(char **data, size_t *length)
106{
107    size_t additional_length = 0;
108    size_t new_length = 0;
109    char *new_data = NULL;
110
111    assert((data != NULL) && (*data != NULL));
112    assert(length != NULL);
113
114    /* calculate new length */
115    for (int i = 0; i < *length; i++) {
116        if ((*data)[i] == '\n') {
117            additional_length++;
118        }
119    }
120
121    /* if no translation necessary, bail out */
122    if (additional_length == 0) {
123        return;
124    }
125    new_length = *length + additional_length;
126
127    /* allocate space for translated data */
128    new_data = malloc(sizeof(char) * new_length);
129    assert(new_data != NULL);
130
131    /* translate characters */
132    char *c = *data;
133    for (int i = 0; i < new_length; ) {
134        if (*c == '\n') {
135            new_data[i++] = '\r';
136        }
137        new_data[i++] = *c;
138        c++;
139    }
140
141    free(*data);
142    *data = new_data;
143    *length = new_length;
144}
145
146/**
147 * \privatesection
148 * Internal functions.
149 */
150static bool is_ctrlhat(char c)
151{
152    if ((c <= 0x1f) && (c != '\n') && (c != '\t') && (c != '\r') && (c != '\b')) {
153        return true;
154    } else {
155        return false;
156    }
157}
158