GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
zfstream.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2005-2018 Ludwig Schwardt, Kevin Ruland
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 /*
24 
25  This file is adapted from the zlib 1.2.2 contrib/iostream3 code,
26  written by
27 
28  Ludwig Schwardt <schwardt@sun.ac.za>
29  original version by Kevin Ruland <kevin@rodin.wustl.edu>
30 
31 */
32 
33 #if defined (HAVE_CONFIG_H)
34 # include "config.h"
35 #endif
36 
37 #include <iostream>
38 
39 #include "zfstream.h"
40 
41 #if defined (HAVE_ZLIB)
42 
43 // For strcpy, strcat, strlen (mode strings).
44 #include <cstring>
45 // For BUFSIZ.
46 #include <cstdio>
47 
48 // Internal buffer sizes (default and "unbuffered" versions)
49 #define STASHED_CHARACTERS 16
50 #define BIGBUFSIZE (256 * 1024 + STASHED_CHARACTERS)
51 #define SMALLBUFSIZE 1
52 
53 // Default constructor
55  : file(nullptr), io_mode(std::ios_base::openmode(0)), own_fd(false),
56  buffer(nullptr), buffer_size(BIGBUFSIZE), own_buffer(true)
57 {
58  // No buffers to start with
59  this->disable_buffer ();
60 }
61 
62 // Destructor
64 {
65  // Sync output buffer and close only if responsible for file
66  // (i.e., attached streams should be left open at this stage)
67  this->sync ();
68  if (own_fd)
69  this->close ();
70  // Make sure internal buffer is deallocated
71  this->disable_buffer ();
72 }
73 
74 // Set compression level and strategy
75 int
76 gzfilebuf::setcompression (int comp_level, int comp_strategy)
77 {
78  return gzsetparams (file, comp_level, comp_strategy);
79 }
80 
81 // Open gzipped file
82 gzfilebuf*
83 gzfilebuf::open (const char *name, std::ios_base::openmode mode)
84 {
85  // Fail if file already open
86  if (this->is_open ())
87  return nullptr;
88  // Don't support simultaneous read/write access (yet)
89  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
90  return nullptr;
91 
92  // Build mode string for gzopen and check it [27.8.1.3.2]
93  char char_mode[6] = "\0\0\0\0\0";
94  if (! this->open_mode (mode, char_mode))
95  return nullptr;
96 
97  // Attempt to open file
98  if ((file = gzopen (name, char_mode)) == nullptr)
99  return nullptr;
100 
101  // On success, allocate internal buffer and set flags
102  this->enable_buffer ();
103  io_mode = mode;
104  own_fd = true;
105  return this;
106 }
107 
108 // Attach to gzipped file
109 gzfilebuf*
110 gzfilebuf::attach (int fd, std::ios_base::openmode mode)
111 {
112  // Fail if file already open
113  if (this->is_open ())
114  return nullptr;
115  // Don't support simultaneous read/write access (yet)
116  if ((mode & std::ios_base::in) && (mode & std::ios_base::out))
117  return nullptr;
118 
119  // Build mode string for gzdopen and check it [27.8.1.3.2]
120  char char_mode[6] = "\0\0\0\0\0";
121  if (! this->open_mode (mode, char_mode))
122  return nullptr;
123 
124  // Attempt to attach to file
125  if ((file = gzdopen (fd, char_mode)) == nullptr)
126  return nullptr;
127 
128  // On success, allocate internal buffer and set flags
129  this->enable_buffer ();
130  io_mode = mode;
131  own_fd = false;
132  return this;
133 }
134 
135 // Close gzipped file
136 gzfilebuf*
138 {
139  // Fail immediately if no file is open
140  if (! this->is_open ())
141  return nullptr;
142  // Assume success
143  gzfilebuf *retval = this;
144  // Attempt to sync and close gzipped file
145  if (this->sync () == -1)
146  retval = nullptr;
147  if (gzclose (file) < 0)
148  retval = nullptr;
149  // File is now gone anyway (postcondition [27.8.1.3.8])
150  file = nullptr;
151  own_fd = false;
152  // Destroy internal buffer if it exists
153  this->disable_buffer ();
154  return retval;
155 }
156 
157 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
158 
159 // Convert int open mode to mode string
160 bool
161 gzfilebuf::open_mode (std::ios_base::openmode mode, char *c_mode) const
162 {
163  // FIXME: do we need testb?
164  // bool testb = mode & std::ios_base::binary;
165  bool testi = mode & std::ios_base::in;
166  bool testo = mode & std::ios_base::out;
167  bool testt = mode & std::ios_base::trunc;
168  bool testa = mode & std::ios_base::app;
169 
170  // Check for valid flag combinations - see [27.8.1.3.2] (Table 92)
171  // Original zfstream hardcoded the compression level to maximum here...
172  // Double the time for less than 1% size improvement seems
173  // excessive though - keeping it at the default level
174  // To change back, just append "9" to the next three mode strings
175  if (! testi && testo && ! testt && ! testa)
176  strcpy (c_mode, "w");
177  if (! testi && testo && ! testt && testa)
178  strcpy (c_mode, "a");
179  if (! testi && testo && testt && ! testa)
180  strcpy (c_mode, "w");
181  if (testi && ! testo && ! testt && ! testa)
182  strcpy (c_mode, "r");
183  // No read/write mode yet
184  // if (testi && testo && ! testt && ! testa)
185  // strcpy(c_mode, "r+");
186  // if (testi && testo && testt && ! testa)
187  // strcpy(c_mode, "w+");
188 
189  // Mode string should be empty for invalid combination of flags
190  if (strlen (c_mode) == 0)
191  return false;
192 
193  strcat (c_mode, "b");
194 
195  return true;
196 }
197 
198 // Determine number of characters in internal get buffer
199 std::streamsize
201 {
202  // Calls to underflow will fail if file not opened for reading
203  if (! this->is_open () || !(io_mode & std::ios_base::in))
204  return -1;
205  // Make sure get area is in use
206  if (this->gptr () && (this->gptr () < this->egptr ()))
207  return std::streamsize (this->egptr () - this->gptr ());
208  else
209  return 0;
210 }
211 
212 // Puts back a character to the stream in two cases. Firstly, when there
213 // is no putback position available, and secondly when the character putback
214 // differs from the one in the file. We can only support the first case
215 // with gzipped files.
216 gzfilebuf::int_type
217 gzfilebuf::pbackfail (gzfilebuf::int_type c)
218 {
219  if (this->is_open ())
220  {
221  if (gzseek (file, this->gptr () - this->egptr () - 1, SEEK_CUR) < 0)
222  return traits_type::eof ();
223 
224  // Invalidates contents of the buffer
225  enable_buffer ();
226 
227  // Attempt to fill internal buffer from gzipped file
228  // (buffer must be guaranteed to exist...)
229  int bytes_read = gzread (file, buffer, buffer_size);
230  // Indicates error or EOF
231  if (bytes_read <= 0)
232  {
233  // Reset get area
234  this->setg (buffer, buffer, buffer);
235  return traits_type::eof ();
236  }
237 
238  // Make all bytes read from file available as get area
239  this->setg (buffer, buffer, buffer + bytes_read);
240 
241  // If next character in get area differs from putback character
242  // flag a failure
243  gzfilebuf::int_type ret = traits_type::to_int_type (*(this->gptr ()));
244  if (ret != c)
245  return traits_type::eof ();
246  else
247  return ret;
248  }
249  else
250  return traits_type::eof ();
251 }
252 
253 // Fill get area from gzipped file
254 gzfilebuf::int_type
256 {
257  // If something is left in the get area by chance, return it
258  // (this shouldn't normally happen, as underflow is only supposed
259  // to be called when gptr >= egptr, but it serves as error check)
260  if (this->gptr () && (this->gptr () < this->egptr ()))
261  return traits_type::to_int_type (*(this->gptr ()));
262 
263  // If the file hasn't been opened for reading, produce error
264  if (! this->is_open () || !(io_mode & std::ios_base::in))
265  return traits_type::eof ();
266 
267  // Copy the final characters to the front of the buffer
268  int stash = 0;
269  if (this->eback () && buffer && buffer_size > STASHED_CHARACTERS)
270  {
271  char_type *ptr1 = buffer;
272  char_type *ptr2 = this->egptr () - STASHED_CHARACTERS + 1;
273  if (ptr2 > this->eback ())
274  while (stash++ <= STASHED_CHARACTERS)
275  *ptr1++ = *ptr2++;
276  }
277 
278  // Attempt to fill internal buffer from gzipped file
279  // (buffer must be guaranteed to exist...)
280  int bytes_read = gzread (file, buffer + stash, buffer_size - stash);
281 
282  // Indicates error or EOF
283  if (bytes_read <= 0)
284  {
285  // Reset get area
286  this->setg (buffer, buffer, buffer);
287  return traits_type::eof ();
288  }
289  // Make all bytes read from file plus the stash available as get area
290  this->setg (buffer, buffer + stash, buffer + bytes_read + stash);
291 
292  // Return next character in get area
293  return traits_type::to_int_type (*(this->gptr ()));
294 }
295 
296 // Write put area to gzipped file
297 gzfilebuf::int_type
299 {
300  // Determine whether put area is in use
301  if (this->pbase ())
302  {
303  // Double-check pointer range
304  if (this->pptr () > this->epptr () || this->pptr () < this->pbase ())
305  return traits_type::eof ();
306  // Add extra character to buffer if not EOF
307  if (! traits_type::eq_int_type (c, traits_type::eof ()))
308  {
309  *(this->pptr ()) = traits_type::to_char_type (c);
310  this->pbump (1);
311  }
312  // Number of characters to write to file
313  int bytes_to_write = this->pptr () - this->pbase ();
314  // Overflow doesn't fail if nothing is to be written
315  if (bytes_to_write > 0)
316  {
317  // If the file hasn't been opened for writing, produce error
318  if (! this->is_open () || !(io_mode & std::ios_base::out))
319  return traits_type::eof ();
320  // If gzipped file won't accept all bytes written to it, fail
321  if (gzwrite (file, this->pbase (), bytes_to_write) != bytes_to_write)
322  return traits_type::eof ();
323  // Reset next pointer to point to pbase on success
324  this->pbump (-bytes_to_write);
325  }
326  }
327  // Write extra character to file if not EOF
328  else if (! traits_type::eq_int_type (c, traits_type::eof ()))
329  {
330  // If the file hasn't been opened for writing, produce error
331  if (! this->is_open () || !(io_mode & std::ios_base::out))
332  return traits_type::eof ();
333  // Impromptu char buffer (allows "unbuffered" output)
334  char_type last_char = traits_type::to_char_type (c);
335  // If gzipped file won't accept this character, fail
336  if (gzwrite (file, &last_char, 1) != 1)
337  return traits_type::eof ();
338  }
339 
340  // If you got here, you have succeeded (even if c was EOF)
341  // The return value should therefore be non-EOF
342  if (traits_type::eq_int_type (c, traits_type::eof ()))
343  return traits_type::not_eof (c);
344  else
345  return c;
346 }
347 
348 // Assign new buffer
349 std::streambuf*
350 gzfilebuf::setbuf (char_type *p, std::streamsize n)
351 {
352  // First make sure stuff is sync'ed, for safety
353  if (this->sync () == -1)
354  return nullptr;
355  // If buffering is turned off on purpose via setbuf(0,0), still allocate one.
356  // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at
357  // least a buffer of size 1 (very inefficient though, therefore make it
358  // bigger?). This follows from [27.5.2.4.3]/12 (gptr needs to point at
359  // something, it seems).
360  if (! p || ! n)
361  {
362  // Replace existing buffer (if any) with small internal buffer
363  this->disable_buffer ();
364  buffer = nullptr;
365  buffer_size = 0;
366  own_buffer = true;
367  this->enable_buffer ();
368  }
369  else
370  {
371  // Replace existing buffer (if any) with external buffer
372  this->disable_buffer ();
373  buffer = p;
374  buffer_size = n;
375  own_buffer = false;
376  this->enable_buffer ();
377  }
378  return this;
379 }
380 
381 // Write put area to gzipped file (i.e., ensures that put area is empty)
382 int
384 {
385  return traits_type::eq_int_type (this->overflow (),
386  traits_type::eof ()) ? -1 : 0;
387 }
388 
389 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
390 
391 // Allocate internal buffer
392 void
394 {
395  // If internal buffer required, allocate one
396  if (own_buffer && ! buffer)
397  {
398  // Check for buffered vs. "unbuffered"
399  if (buffer_size > 0)
400  {
401  // Allocate internal buffer
402  buffer = new char_type [buffer_size];
403  // Get area starts empty and will be expanded by underflow as needed
404  this->setg (buffer, buffer, buffer);
405  // Setup entire internal buffer as put area.
406  // The one-past-end pointer actually points to the last element of
407  // the buffer, so that overflow(c) can safely add the extra character
408  // c to the sequence. These pointers remain in place for the
409  // duration of the buffer
410  this->setp (buffer, buffer + buffer_size - 1);
411  }
412  else
413  {
414  // Even in "unbuffered" case, (small?) get buffer is still required
416  buffer = new char_type [buffer_size];
417  this->setg (buffer, buffer, buffer);
418  // "Unbuffered" means no put buffer
419  this->setp (nullptr, nullptr);
420  }
421  }
422  else
423  {
424  // If buffer already allocated, reset buffer pointers just to make sure no
425  // stale chars are lying around
426  this->setg (buffer, buffer, buffer);
427  this->setp (buffer, buffer + buffer_size - 1);
428  }
429 }
430 
431 // Destroy internal buffer
432 void
434 {
435  // If internal buffer exists, deallocate it
436  if (own_buffer && buffer)
437  {
438  // Preserve unbuffered status by zeroing size
439  if (! this->pbase ())
440  buffer_size = 0;
441  delete[] buffer;
442  buffer = nullptr;
443  this->setg (nullptr, nullptr, nullptr);
444  this->setp (nullptr, nullptr);
445  }
446  else
447  {
448  // Reset buffer pointers to initial state if external buffer exists
449  this->setg (buffer, buffer, buffer);
450  if (buffer)
451  this->setp (buffer, buffer + buffer_size - 1);
452  else
453  this->setp (nullptr, nullptr);
454  }
455 }
456 
457 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
458 
459 // Seek functions
460 gzfilebuf::pos_type
461 gzfilebuf::seekoff (off_type off, std::ios_base::seekdir way,
462  std::ios_base::openmode)
463 {
464  pos_type ret = pos_type (off_type (-1));
465 
466  if (this->is_open ())
467  {
468  off_type computed_off = off;
469 
470  if ((io_mode & std::ios_base::in) && way == std::ios_base::cur)
471  computed_off += this->gptr () - this->egptr ();
472 
473  // Handle tellg/tellp as a special case up front, no need to seek
474  // or invalidate get/put buffers
475  if (off == 0 && way == std::ios_base::cur)
476  return pos_type (gztell (file) + computed_off);
477 
478  if (way == std::ios_base::beg)
479  ret = pos_type (gzseek (file, computed_off, SEEK_SET));
480  else if (way == std::ios_base::cur)
481  ret = pos_type (gzseek (file, computed_off, SEEK_CUR));
482  else
483  // Can't seek from end of a gzipped file, so this will give -1
484  ret = pos_type (gzseek (file, computed_off, SEEK_END));
485 
486  if (io_mode & std::ios_base::in)
487  // Invalidates contents of the buffer
488  enable_buffer ();
489  else
490  // flush contents of buffer to file
491  overflow ();
492  }
493 
494  return ret;
495 }
496 
497 gzfilebuf::pos_type
498 gzfilebuf::seekpos (pos_type sp, std::ios_base::openmode)
499 {
500  pos_type ret = pos_type (off_type (-1));
501 
502  if (this->is_open ())
503  {
504  ret = pos_type (gzseek (file, sp, SEEK_SET));
505 
506  if (io_mode & std::ios_base::in)
507  // Invalidates contents of the buffer
508  enable_buffer ();
509  else
510  // flush contents of buffer to file
511  overflow ();
512  }
513 
514  return ret;
515 }
516 
517 // Default constructor initializes stream buffer
519  : std::istream (nullptr), sb ()
520 { this->init (&sb); }
521 
522 // Initialize stream buffer and open file
523 gzifstream::gzifstream (const char *name, std::ios_base::openmode mode)
524  : std::istream (nullptr), sb ()
525 {
526  this->init (&sb);
527  this->open (name, mode);
528 }
529 
530 // Initialize stream buffer and attach to file
531 gzifstream::gzifstream (int fd, std::ios_base::openmode mode)
532  : std::istream (nullptr), sb ()
533 {
534  this->init (&sb);
535  this->attach (fd, mode);
536 }
537 
538 // Open file and go into fail() state if unsuccessful
539 void
540 gzifstream::open (const char *name, std::ios_base::openmode mode)
541 {
542  if (! sb.open (name, mode | std::ios_base::in))
543  this->setstate (std::ios_base::failbit);
544  else
545  this->clear ();
546 }
547 
548 // Attach to file and go into fail() state if unsuccessful
549 void
550 gzifstream::attach (int fd, std::ios_base::openmode mode)
551 {
552  if (! sb.attach (fd, mode | std::ios_base::in))
553  this->setstate (std::ios_base::failbit);
554  else
555  this->clear ();
556 }
557 
558 // Close file
559 void
561 {
562  if (! sb.close ())
563  this->setstate (std::ios_base::failbit);
564 }
565 
566 // Default constructor initializes stream buffer
568  : std::ostream (nullptr), sb ()
569 { this->init (&sb); }
570 
571 // Initialize stream buffer and open file
572 gzofstream::gzofstream (const char *name, std::ios_base::openmode mode)
573  : std::ostream (nullptr), sb ()
574 {
575  this->init (&sb);
576  this->open (name, mode);
577 }
578 
579 // Initialize stream buffer and attach to file
580 gzofstream::gzofstream (int fd, std::ios_base::openmode mode)
581  : std::ostream (nullptr), sb ()
582 {
583  this->init (&sb);
584  this->attach (fd, mode);
585 }
586 
587 // Open file and go into fail() state if unsuccessful
588 void
589 gzofstream::open (const char *name, std::ios_base::openmode mode)
590 {
591  if (! sb.open (name, mode | std::ios_base::out))
592  this->setstate (std::ios_base::failbit);
593  else
594  this->clear ();
595 }
596 
597 // Attach to file and go into fail() state if unsuccessful
598 void
599 gzofstream::attach (int fd, std::ios_base::openmode mode)
600 {
601  if (! sb.attach (fd, mode | std::ios_base::out))
602  this->setstate (std::ios_base::failbit);
603  else
604  this->clear ();
605 }
606 
607 // Close file
608 void
610 {
611  if (! sb.close ())
612  this->setstate (std::ios_base::failbit);
613 }
614 
615 #endif
gzfilebuf * open(const char *name, std::ios_base::openmode mode)
Open gzipped file.
Definition: zfstream.cc:83
For example cd octave end example noindent changes the current working directory to file
Definition: dirfns.cc:124
void attach(int fd, std::ios_base::openmode mode=std::ios_base::out)
Attach to already open gzipped file.
Definition: zfstream.cc:599
virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Alters the stream positions.
Definition: zfstream.cc:461
gzfilebuf sb
Underlying stream buffer.
Definition: zfstream.h:356
void open(const char *name, std::ios_base::openmode mode=std::ios_base::in)
Open gzipped file.
Definition: zfstream.cc:540
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6348
#define SMALLBUFSIZE
Definition: zfstream.cc:51
virtual std::streambuf * setbuf(char_type *p, std::streamsize n)
Installs external stream buffer.
Definition: zfstream.cc:350
#define STASHED_CHARACTERS
Definition: zfstream.cc:49
void enable_buffer()
Allocate internal buffer.
Definition: zfstream.cc:393
STL namespace.
void init(void)
Definition: Range.cc:610
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
gzfilebuf()
Definition: zfstream.cc:54
virtual int_type overflow(int_type c=traits_type::eof())
Write put area to gzipped file.
Definition: zfstream.cc:298
#define SEEK_CUR
int setcompression(int comp_level, int comp_strategy=Z_DEFAULT_STRATEGY)
Set compression level and strategy on the fly.
Definition: zfstream.cc:76
gzfilebuf * close()
Close gzipped file.
Definition: zfstream.cc:137
std::ios_base::openmode io_mode
Mode in which file was opened.
Definition: zfstream.h:237
gzFile file
Underlying file pointer.
Definition: zfstream.h:232
bool is_open() const
Check if file is open.
Definition: zfstream.h:87
nd deftypefn *std::string name
Definition: sysdep.cc:647
virtual int_type pbackfail(int_type c=traits_type::eof())
Definition: zfstream.cc:217
Gzipped file stream buffer class.
Definition: zfstream.h:52
void open(const char *name, std::ios_base::openmode mode=std::ios_base::out)
Open gzipped file.
Definition: zfstream.cc:589
bool own_buffer
True if this object owns stream buffer.
Definition: zfstream.h:269
std::complex< T > trunc(const std::complex< T > &x)
Definition: lo-mappers.h:120
#define SEEK_END
is false
Definition: cellfun.cc:400
void attach(int fd, std::ios_base::openmode mode=std::ios_base::in)
Attach to already open gzipped file.
Definition: zfstream.cc:550
octave_value retval
Definition: data.cc:6246
void close()
Close gzipped file.
Definition: zfstream.cc:609
char_type * buffer
Stream buffer.
Definition: zfstream.h:253
virtual pos_type seekpos(pos_type sp, std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)
Alters the stream positions.
Definition: zfstream.cc:498
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:75
gzfilebuf sb
Underlying stream buffer.
Definition: zfstream.h:443
#define BIGBUFSIZE
Definition: zfstream.cc:50
void disable_buffer()
Destroy internal buffer.
Definition: zfstream.cc:433
std::streamsize buffer_size
Stream buffer size.
Definition: zfstream.h:261
gzfilebuf * attach(int fd, std::ios_base::openmode mode)
Attach to already open gzipped file.
Definition: zfstream.cc:110
bool open_mode(std::ios_base::openmode mode, char *c_mode) const
Convert ios open mode int to mode string used by zlib.
Definition: zfstream.cc:161
virtual std::streamsize showmanyc()
Number of characters available in stream buffer.
Definition: zfstream.cc:200
virtual ~gzfilebuf()
Definition: zfstream.cc:63
virtual int sync()
Flush stream buffer to file.
Definition: zfstream.cc:383
p
Definition: lu.cc:138
bool own_fd
True if this object owns file descriptor.
Definition: zfstream.h:245
#define SEEK_SET
void close()
Close gzipped file.
Definition: zfstream.cc:560
virtual int_type underflow()
Fill get area from gzipped file.
Definition: zfstream.cc:255