blob: 920c81625452ea4718383edd7f8ac84a9e5b7e2c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#pragma once
#include "types.h"
#include <proc/kmutex.h>
#define LDISC_BUFFER_SIZE 128
/**
* The line discipline is implemented as a circular buffer containing two
* sections: cooked and raw. These sections are tracked by three indices:
* ldisc_cooked, ldisc_tail, and ldisc_head.
*
* New characters (via ldisc_key_pressed) are put at the head position (and the
* head is incremented). If a newline is received, cooked is moved up to the head.
* Characters are read from tail up until cooked, and the tail is updated
* to equal cooked.
*
* The cooked portion (ready for reading) runs from ldisc_tail (inclusive) to
* ldisc_cooked (exclusive). The raw portion (subject to editing) runs from
* ldisc_cooked (inclusive) to ldisc_head (exclusive).
*
* e.g.
* [..........t........c...h.......]
* (cooked) ^^^^^^^^^
* ^^^^ (raw)
*
* Bear in mind that the buffer is circular, so another possible configuration
* might be
*
* [....h............t......c......]
* (cooked) ^^^^^^^
* ^^^^ ^^^^^^^ (raw)
*
* When incrementing the indices, make sure that you take the circularity of
* the buffer into account! (Hint: using LDISC_BUFFER_SIZE macro will be helpful.)
*
* The field ldisc_full is used to indicate when the circular buffer has been
* completely filled. This is necessary because there are two possible states
* in which cooked == tail == head:
*
* 1) The buffer is empty, or
*
* 2) The buffer is full: head has wrapped around and is equal to tail.
*
* ldisc_full is used to differentiate between these two states.
*/
typedef struct ldisc
{
size_t ldisc_cooked; // Cooked is the index after the most last or most recent '\n' in the buffer.
size_t ldisc_tail; // Tail is the index from which characters are read by processes
size_t ldisc_head; // Head is the index from which new characters are placed
char ldisc_full; // Full identifies if the buffer is full
// 1 -> full
// 0 -> not full
ktqueue_t ldisc_read_queue; // Queue for threads waiting for data to be read
char ldisc_buffer[LDISC_BUFFER_SIZE];
} ldisc_t;
void ldisc_init(ldisc_t *ldisc);
long ldisc_wait_read(ldisc_t *ldisc);
size_t ldisc_read(ldisc_t *ldisc, char *buf, size_t count);
void ldisc_key_pressed(ldisc_t *ldisc, char c);
size_t ldisc_get_current_line_raw(ldisc_t *ldisc, char *s);
|