Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
OSCData.cpp@7:98280cef1c4f, 2018-12-03 (annotated)
- Committer:
- Ibiltari
- Date:
- Mon Dec 03 20:27:07 2018 +0100
- Revision:
- 7:98280cef1c4f
- Child:
- 9:e4528f622bcc
Cambio de libreria base a CNMAT OSC Arduino
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Ibiltari |
7:98280cef1c4f | 1 | |
Ibiltari |
7:98280cef1c4f | 2 | #include "OSCData.h" |
Ibiltari |
7:98280cef1c4f | 3 | |
Ibiltari |
7:98280cef1c4f | 4 | |
Ibiltari |
7:98280cef1c4f | 5 | |
Ibiltari |
7:98280cef1c4f | 6 | /*============================================================================= |
Ibiltari |
7:98280cef1c4f | 7 | CONSTRUCTORS |
Ibiltari |
7:98280cef1c4f | 8 | |
Ibiltari |
7:98280cef1c4f | 9 | overloaded methods for each of the types which will |
Ibiltari |
7:98280cef1c4f | 10 | set the type flag, the size (in bytes), and the data |
Ibiltari |
7:98280cef1c4f | 11 | =============================================================================*/ |
Ibiltari |
7:98280cef1c4f | 12 | |
Ibiltari |
7:98280cef1c4f | 13 | /* |
Ibiltari |
7:98280cef1c4f | 14 | OSCData::OSCData(const char * s){ |
Ibiltari |
7:98280cef1c4f | 15 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 16 | type = 's'; |
Ibiltari |
7:98280cef1c4f | 17 | bytes = (strlen(s) + 1); |
Ibiltari |
7:98280cef1c4f | 18 | //own the data |
Ibiltari |
7:98280cef1c4f | 19 | char * mem = (char *) malloc(bytes); |
Ibiltari |
7:98280cef1c4f | 20 | if (mem == NULL){ |
Ibiltari |
7:98280cef1c4f | 21 | error = ALLOCFAILED; |
Ibiltari |
7:98280cef1c4f | 22 | } else { |
Ibiltari |
7:98280cef1c4f | 23 | strcpy(mem, s); |
Ibiltari |
7:98280cef1c4f | 24 | data.s = mem; |
Ibiltari |
7:98280cef1c4f | 25 | } |
Ibiltari |
7:98280cef1c4f | 26 | } |
Ibiltari |
7:98280cef1c4f | 27 | |
Ibiltari |
7:98280cef1c4f | 28 | */ |
Ibiltari |
7:98280cef1c4f | 29 | |
Ibiltari |
7:98280cef1c4f | 30 | |
Ibiltari |
7:98280cef1c4f | 31 | OSCData::OSCData(int i){ |
Ibiltari |
7:98280cef1c4f | 32 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 33 | type = 'i'; |
Ibiltari |
7:98280cef1c4f | 34 | bytes = 4; |
Ibiltari |
7:98280cef1c4f | 35 | data.i = i; |
Ibiltari |
7:98280cef1c4f | 36 | } |
Ibiltari |
7:98280cef1c4f | 37 | OSCData::OSCData(long int i){ |
Ibiltari |
7:98280cef1c4f | 38 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 39 | type = 'i'; |
Ibiltari |
7:98280cef1c4f | 40 | bytes = 4; |
Ibiltari |
7:98280cef1c4f | 41 | data.i = i; |
Ibiltari |
7:98280cef1c4f | 42 | } |
Ibiltari |
7:98280cef1c4f | 43 | /* |
Ibiltari |
7:98280cef1c4f | 44 | OSCData::OSCData(unsigned int i){ |
Ibiltari |
7:98280cef1c4f | 45 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 46 | type = 'i'; |
Ibiltari |
7:98280cef1c4f | 47 | bytes = 4; |
Ibiltari |
7:98280cef1c4f | 48 | data.i = i; |
Ibiltari |
7:98280cef1c4f | 49 | } |
Ibiltari |
7:98280cef1c4f | 50 | */ |
Ibiltari |
7:98280cef1c4f | 51 | |
Ibiltari |
7:98280cef1c4f | 52 | OSCData::OSCData(float f){ |
Ibiltari |
7:98280cef1c4f | 53 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 54 | type = 'f'; |
Ibiltari |
7:98280cef1c4f | 55 | bytes = 4; |
Ibiltari |
7:98280cef1c4f | 56 | data.f = f; |
Ibiltari |
7:98280cef1c4f | 57 | } |
Ibiltari |
7:98280cef1c4f | 58 | |
Ibiltari |
7:98280cef1c4f | 59 | |
Ibiltari |
7:98280cef1c4f | 60 | OSCData::OSCData(bool b){ |
Ibiltari |
7:98280cef1c4f | 61 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 62 | type = b?'T':'F'; |
Ibiltari |
7:98280cef1c4f | 63 | bytes = 0; |
Ibiltari |
7:98280cef1c4f | 64 | } |
Ibiltari |
7:98280cef1c4f | 65 | |
Ibiltari |
7:98280cef1c4f | 66 | |
Ibiltari |
7:98280cef1c4f | 67 | OSCData::OSCData(double d){ |
Ibiltari |
7:98280cef1c4f | 68 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 69 | bytes = sizeof(double); |
Ibiltari |
7:98280cef1c4f | 70 | //if it's not 8 bytes it's not a true double |
Ibiltari |
7:98280cef1c4f | 71 | if (bytes == 8){ |
Ibiltari |
7:98280cef1c4f | 72 | type = 'd'; |
Ibiltari |
7:98280cef1c4f | 73 | data.d = d; |
Ibiltari |
7:98280cef1c4f | 74 | } else { |
Ibiltari |
7:98280cef1c4f | 75 | type = 'f'; |
Ibiltari |
7:98280cef1c4f | 76 | data.f = d; |
Ibiltari |
7:98280cef1c4f | 77 | } |
Ibiltari |
7:98280cef1c4f | 78 | } |
Ibiltari |
7:98280cef1c4f | 79 | /* |
Ibiltari |
7:98280cef1c4f | 80 | OSCData::OSCData(uint8_t * b, int len){ |
Ibiltari |
7:98280cef1c4f | 81 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 82 | type = 'b'; |
Ibiltari |
7:98280cef1c4f | 83 | bytes = len + 4; |
Ibiltari |
7:98280cef1c4f | 84 | //add the size to the front of the blob |
Ibiltari |
7:98280cef1c4f | 85 | uint32_t len32 = (uint32_t) len; |
Ibiltari |
7:98280cef1c4f | 86 | //make sure the length is endian-safe |
Ibiltari |
7:98280cef1c4f | 87 | len32 = BigEndian(len32); |
Ibiltari |
7:98280cef1c4f | 88 | uint8_t * lenPtr = (uint8_t *) (& len32); |
Ibiltari |
7:98280cef1c4f | 89 | //own the data |
Ibiltari |
7:98280cef1c4f | 90 | if(bytes>0) |
Ibiltari |
7:98280cef1c4f | 91 | { |
Ibiltari |
7:98280cef1c4f | 92 | |
Ibiltari |
7:98280cef1c4f | 93 | uint8_t * mem = (uint8_t * ) malloc(bytes); |
Ibiltari |
7:98280cef1c4f | 94 | if (mem == NULL){ |
Ibiltari |
7:98280cef1c4f | 95 | error = ALLOCFAILED; |
Ibiltari |
7:98280cef1c4f | 96 | } else { |
Ibiltari |
7:98280cef1c4f | 97 | //copy over the blob length |
Ibiltari |
7:98280cef1c4f | 98 | memcpy(mem, lenPtr, 4); |
Ibiltari |
7:98280cef1c4f | 99 | //copy over the blob data |
Ibiltari |
7:98280cef1c4f | 100 | memcpy(mem + 4, b, len); |
Ibiltari |
7:98280cef1c4f | 101 | data.b = mem; |
Ibiltari |
7:98280cef1c4f | 102 | } |
Ibiltari |
7:98280cef1c4f | 103 | } |
Ibiltari |
7:98280cef1c4f | 104 | else |
Ibiltari |
7:98280cef1c4f | 105 | data.b = 0; |
Ibiltari |
7:98280cef1c4f | 106 | } |
Ibiltari |
7:98280cef1c4f | 107 | */ |
Ibiltari |
7:98280cef1c4f | 108 | OSCData::OSCData (OSCData * datum){ |
Ibiltari |
7:98280cef1c4f | 109 | error = OSC_OK; |
Ibiltari |
7:98280cef1c4f | 110 | type = datum->type; |
Ibiltari |
7:98280cef1c4f | 111 | bytes = datum->bytes; |
Ibiltari |
7:98280cef1c4f | 112 | if ( (type == 'i') || (type == 'f') || (type == 'd') || (type == 't') |
Ibiltari |
7:98280cef1c4f | 113 | || (type == 'h') || (type == 'c') || (type == 'r') || (type == 'm') |
Ibiltari |
7:98280cef1c4f | 114 | ) |
Ibiltari |
7:98280cef1c4f | 115 | { |
Ibiltari |
7:98280cef1c4f | 116 | data = datum->data; |
Ibiltari |
7:98280cef1c4f | 117 | } /* else if ((type == 's') || (type == 'b')){ |
Ibiltari |
7:98280cef1c4f | 118 | //allocate a new piece of memory |
Ibiltari |
7:98280cef1c4f | 119 | uint8_t * mem = (uint8_t * ) malloc(bytes); |
Ibiltari |
7:98280cef1c4f | 120 | if (mem == NULL){ |
Ibiltari |
7:98280cef1c4f | 121 | error = ALLOCFAILED; |
Ibiltari |
7:98280cef1c4f | 122 | } else { |
Ibiltari |
7:98280cef1c4f | 123 | //copy over the blob length |
Ibiltari |
7:98280cef1c4f | 124 | memcpy(mem, datum->data.b, bytes); |
Ibiltari |
7:98280cef1c4f | 125 | data.b = mem; |
Ibiltari |
7:98280cef1c4f | 126 | } |
Ibiltari |
7:98280cef1c4f | 127 | } */ |
Ibiltari |
7:98280cef1c4f | 128 | } |
Ibiltari |
7:98280cef1c4f | 129 | |
Ibiltari |
7:98280cef1c4f | 130 | //DESTRUCTOR |
Ibiltari |
7:98280cef1c4f | 131 | OSCData::~OSCData(){ |
Ibiltari |
7:98280cef1c4f | 132 | /* |
Ibiltari |
7:98280cef1c4f | 133 | //if there are no bytes, there is nothing to free |
Ibiltari |
7:98280cef1c4f | 134 | if (bytes>0){ |
Ibiltari |
7:98280cef1c4f | 135 | //if the data is of type 's' or 'b', need to free that memory |
Ibiltari |
7:98280cef1c4f | 136 | if (type == 's'){ |
Ibiltari |
7:98280cef1c4f | 137 | free(data.s); |
Ibiltari |
7:98280cef1c4f | 138 | }else if( type == 'b'){ |
Ibiltari |
7:98280cef1c4f | 139 | free(data.b); |
Ibiltari |
7:98280cef1c4f | 140 | } |
Ibiltari |
7:98280cef1c4f | 141 | } |
Ibiltari |
7:98280cef1c4f | 142 | */ |
Ibiltari |
7:98280cef1c4f | 143 | } |
Ibiltari |
7:98280cef1c4f | 144 | |
Ibiltari |
7:98280cef1c4f | 145 | //sets just the type as a message placeholder |
Ibiltari |
7:98280cef1c4f | 146 | //no data |
Ibiltari |
7:98280cef1c4f | 147 | OSCData::OSCData(char t){ |
Ibiltari |
7:98280cef1c4f | 148 | error = INVALID_OSC; |
Ibiltari |
7:98280cef1c4f | 149 | type = t; |
Ibiltari |
7:98280cef1c4f | 150 | bytes = 0; |
Ibiltari |
7:98280cef1c4f | 151 | } |
Ibiltari |
7:98280cef1c4f | 152 | |
Ibiltari |
7:98280cef1c4f | 153 | /*============================================================================= |
Ibiltari |
7:98280cef1c4f | 154 | GETTERS |
Ibiltari |
7:98280cef1c4f | 155 | |
Ibiltari |
7:98280cef1c4f | 156 | perform a safety check to make sure the data type matches the request |
Ibiltari |
7:98280cef1c4f | 157 | otherwise returns NULL |
Ibiltari |
7:98280cef1c4f | 158 | =============================================================================*/ |
Ibiltari |
7:98280cef1c4f | 159 | |
Ibiltari |
7:98280cef1c4f | 160 | int32_t OSCData::getInt(){ |
Ibiltari |
7:98280cef1c4f | 161 | if (type == 'i'){ |
Ibiltari |
7:98280cef1c4f | 162 | return data.i; |
Ibiltari |
7:98280cef1c4f | 163 | } else { |
Ibiltari |
7:98280cef1c4f | 164 | return -1; |
Ibiltari |
7:98280cef1c4f | 165 | } |
Ibiltari |
7:98280cef1c4f | 166 | } |
Ibiltari |
7:98280cef1c4f | 167 | |
Ibiltari |
7:98280cef1c4f | 168 | float OSCData::getFloat(){ |
Ibiltari |
7:98280cef1c4f | 169 | if (type == 'f'){ |
Ibiltari |
7:98280cef1c4f | 170 | return data.f; |
Ibiltari |
7:98280cef1c4f | 171 | } else { |
Ibiltari |
7:98280cef1c4f | 172 | return -1; |
Ibiltari |
7:98280cef1c4f | 173 | } |
Ibiltari |
7:98280cef1c4f | 174 | } |
Ibiltari |
7:98280cef1c4f | 175 | |
Ibiltari |
7:98280cef1c4f | 176 | double OSCData::getDouble(){ |
Ibiltari |
7:98280cef1c4f | 177 | if (type == 'd'){ |
Ibiltari |
7:98280cef1c4f | 178 | return data.d; |
Ibiltari |
7:98280cef1c4f | 179 | } else { |
Ibiltari |
7:98280cef1c4f | 180 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 181 | return (double)NULL; |
Ibiltari |
7:98280cef1c4f | 182 | #else |
Ibiltari |
7:98280cef1c4f | 183 | return -1; |
Ibiltari |
7:98280cef1c4f | 184 | #endif |
Ibiltari |
7:98280cef1c4f | 185 | } |
Ibiltari |
7:98280cef1c4f | 186 | } |
Ibiltari |
7:98280cef1c4f | 187 | bool OSCData::getBoolean(){ |
Ibiltari |
7:98280cef1c4f | 188 | if (type == 'T'){ |
Ibiltari |
7:98280cef1c4f | 189 | return true; |
Ibiltari |
7:98280cef1c4f | 190 | } else if (type=='F'){ |
Ibiltari |
7:98280cef1c4f | 191 | return false; |
Ibiltari |
7:98280cef1c4f | 192 | } |
Ibiltari |
7:98280cef1c4f | 193 | else |
Ibiltari |
7:98280cef1c4f | 194 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 195 | return NULL; |
Ibiltari |
7:98280cef1c4f | 196 | #else |
Ibiltari |
7:98280cef1c4f | 197 | return -1; |
Ibiltari |
7:98280cef1c4f | 198 | #endif |
Ibiltari |
7:98280cef1c4f | 199 | } |
Ibiltari |
7:98280cef1c4f | 200 | |
Ibiltari |
7:98280cef1c4f | 201 | |
Ibiltari |
7:98280cef1c4f | 202 | // no-safety-check straightforward way to fill the passed buffer |
Ibiltari |
7:98280cef1c4f | 203 | // with the received string |
Ibiltari |
7:98280cef1c4f | 204 | int OSCData::getString(char * strBuffer){ |
Ibiltari |
7:98280cef1c4f | 205 | if (type == 's'){ |
Ibiltari |
7:98280cef1c4f | 206 | strncpy(strBuffer, data.s, bytes); |
Ibiltari |
7:98280cef1c4f | 207 | return bytes; |
Ibiltari |
7:98280cef1c4f | 208 | } else { |
Ibiltari |
7:98280cef1c4f | 209 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 210 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 211 | #else |
Ibiltari |
7:98280cef1c4f | 212 | return -1; |
Ibiltari |
7:98280cef1c4f | 213 | #endif |
Ibiltari |
7:98280cef1c4f | 214 | } |
Ibiltari |
7:98280cef1c4f | 215 | } |
Ibiltari |
7:98280cef1c4f | 216 | |
Ibiltari |
7:98280cef1c4f | 217 | // it's possible to pass strBuffer's size as argument (length) |
Ibiltari |
7:98280cef1c4f | 218 | // in order to check that it won't be overflown |
Ibiltari |
7:98280cef1c4f | 219 | int OSCData::getString(char * strBuffer, int length){ |
Ibiltari |
7:98280cef1c4f | 220 | if (type == 's' && bytes <= length){ |
Ibiltari |
7:98280cef1c4f | 221 | strncpy(strBuffer, data.s, bytes); |
Ibiltari |
7:98280cef1c4f | 222 | return bytes; |
Ibiltari |
7:98280cef1c4f | 223 | } else { |
Ibiltari |
7:98280cef1c4f | 224 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 225 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 226 | #else |
Ibiltari |
7:98280cef1c4f | 227 | return -1; |
Ibiltari |
7:98280cef1c4f | 228 | #endif |
Ibiltari |
7:98280cef1c4f | 229 | } |
Ibiltari |
7:98280cef1c4f | 230 | } |
Ibiltari |
7:98280cef1c4f | 231 | |
Ibiltari |
7:98280cef1c4f | 232 | // Here we can get only a part of the blob |
Ibiltari |
7:98280cef1c4f | 233 | int OSCData::getString(char * strBuffer, int length, int offset, int size){ |
Ibiltari |
7:98280cef1c4f | 234 | if (type == 's' && size <= bytes && size <= length){ |
Ibiltari |
7:98280cef1c4f | 235 | strncpy(strBuffer, data.s + offset, size); |
Ibiltari |
7:98280cef1c4f | 236 | return size; |
Ibiltari |
7:98280cef1c4f | 237 | } else { |
Ibiltari |
7:98280cef1c4f | 238 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 239 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 240 | #else |
Ibiltari |
7:98280cef1c4f | 241 | return -1; |
Ibiltari |
7:98280cef1c4f | 242 | #endif |
Ibiltari |
7:98280cef1c4f | 243 | } |
Ibiltari |
7:98280cef1c4f | 244 | } |
Ibiltari |
7:98280cef1c4f | 245 | /* |
Ibiltari |
7:98280cef1c4f | 246 | // no-safety-check straightforward way to fill the passed buffer |
Ibiltari |
7:98280cef1c4f | 247 | // with the contents of the received blob |
Ibiltari |
7:98280cef1c4f | 248 | int OSCData::getBlob(uint8_t * blobBuffer){ |
Ibiltari |
7:98280cef1c4f | 249 | // read the blob length |
Ibiltari |
7:98280cef1c4f | 250 | int blobLength = getBlobLength(); |
Ibiltari |
7:98280cef1c4f | 251 | |
Ibiltari |
7:98280cef1c4f | 252 | if (type == 'b'){ |
Ibiltari |
7:98280cef1c4f | 253 | memcpy(blobBuffer, data.b + 4, blobLength); |
Ibiltari |
7:98280cef1c4f | 254 | return blobLength; |
Ibiltari |
7:98280cef1c4f | 255 | } else { |
Ibiltari |
7:98280cef1c4f | 256 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 257 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 258 | #else |
Ibiltari |
7:98280cef1c4f | 259 | return -1; |
Ibiltari |
7:98280cef1c4f | 260 | #endif |
Ibiltari |
7:98280cef1c4f | 261 | } |
Ibiltari |
7:98280cef1c4f | 262 | } |
Ibiltari |
7:98280cef1c4f | 263 | |
Ibiltari |
7:98280cef1c4f | 264 | // it's possible to pass blobBuffer's size as argument (length) |
Ibiltari |
7:98280cef1c4f | 265 | // in order to check that it won't be overflown |
Ibiltari |
7:98280cef1c4f | 266 | int OSCData::getBlob(uint8_t * blobBuffer, int length){ |
Ibiltari |
7:98280cef1c4f | 267 | //jump over the first 4 bytes which encode the length |
Ibiltari |
7:98280cef1c4f | 268 | int blobLength = bytes-4; |
Ibiltari |
7:98280cef1c4f | 269 | if (type == 'b' && blobLength <= length){ |
Ibiltari |
7:98280cef1c4f | 270 | memcpy(blobBuffer, data.b + 4, blobLength); |
Ibiltari |
7:98280cef1c4f | 271 | return blobLength; |
Ibiltari |
7:98280cef1c4f | 272 | } else { |
Ibiltari |
7:98280cef1c4f | 273 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 274 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 275 | #else |
Ibiltari |
7:98280cef1c4f | 276 | return -1; |
Ibiltari |
7:98280cef1c4f | 277 | #endif |
Ibiltari |
7:98280cef1c4f | 278 | } |
Ibiltari |
7:98280cef1c4f | 279 | } |
Ibiltari |
7:98280cef1c4f | 280 | |
Ibiltari |
7:98280cef1c4f | 281 | // Here we can get only a part of the blob |
Ibiltari |
7:98280cef1c4f | 282 | int OSCData::getBlob(uint8_t * blobBuffer, int length, int offset, int size){ |
Ibiltari |
7:98280cef1c4f | 283 | //jump over the first 4 bytes which encode the length |
Ibiltari |
7:98280cef1c4f | 284 | int blobLength = bytes-4; |
Ibiltari |
7:98280cef1c4f | 285 | if (type == 'b' && size <= blobLength && size <= length){ |
Ibiltari |
7:98280cef1c4f | 286 | memcpy(blobBuffer, data.b + 4 + offset, size); |
Ibiltari |
7:98280cef1c4f | 287 | return size; |
Ibiltari |
7:98280cef1c4f | 288 | } else { |
Ibiltari |
7:98280cef1c4f | 289 | #ifndef ESPxx |
Ibiltari |
7:98280cef1c4f | 290 | return (int)NULL; |
Ibiltari |
7:98280cef1c4f | 291 | #else |
Ibiltari |
7:98280cef1c4f | 292 | return -1; |
Ibiltari |
7:98280cef1c4f | 293 | #endif |
Ibiltari |
7:98280cef1c4f | 294 | } |
Ibiltari |
7:98280cef1c4f | 295 | } |
Ibiltari |
7:98280cef1c4f | 296 | |
Ibiltari |
7:98280cef1c4f | 297 | |
Ibiltari |
7:98280cef1c4f | 298 | |
Ibiltari |
7:98280cef1c4f | 299 | int OSCData::getBlobLength(){ |
Ibiltari |
7:98280cef1c4f | 300 | if (type == 'b'){ |
Ibiltari |
7:98280cef1c4f | 301 | //jump over the first 4 bytes which encode the length |
Ibiltari |
7:98280cef1c4f | 302 | return bytes-4; |
Ibiltari |
7:98280cef1c4f | 303 | } |
Ibiltari |
7:98280cef1c4f | 304 | return -1; |
Ibiltari |
7:98280cef1c4f | 305 | } |
Ibiltari |
7:98280cef1c4f | 306 | */ |