/*! The type wxJSONTYPE_MEMORYBUFF is a \b wxJSON extension that is not correctly read by other JSON implementations. By default, the function writes such a type as an array of INTs as follows: \code [ 0,32,45,255,6,...] \endcode If the writer object was constructed using the \c wxJSONWRITER_MEMORYBUFF flag, then the output is much more compact and recognized by the \b wxJSON reader as a memory buffer type: \code '00203FFF06..' \endcode */ int wxJSONWriter::WriteMemoryBuff( wxOutputStream& os, const wxMemoryBuffer& buff ) { #define MAX_BYTES_PER_ROW 20 char str[16]; // if STYLED and SPLIT_STRING flags are set, the function writes 20 bytes on every row // the following is the counter of bytes written. // the string is splitted only for the special meory buffer type, not for array of INTs int bytesWritten = 0; bool splitString = false; if ( (m_style & wxJSONWRITER_STYLED) && (m_style & wxJSONWRITER_SPLIT_STRING)) { splitString = true; } size_t buffLen = buff.GetDataLen(); unsigned char* ptr = (unsigned char*) buff.GetData(); wxASSERT( ptr ); char openChar = '\''; char closeChar = '\''; bool asArray = false; if ( (m_style & wxJSONWRITER_MEMORYBUFF ) == 0 ) { // if the special flag is not specified, write as an array of INTs openChar = '['; closeChar = ']'; asArray = true; } // write the open character os.PutC( openChar ); for ( size_t i = 0; i < buffLen; i++ ) { unsigned char c = *ptr; ++ptr; if ( asArray ) { snprintf( str, 14, "%d", c ); size_t len = strlen( str ); wxASSERT( len <= 3 ); wxASSERT( len >= 1 ); str[len] = ','; // do not write the comma char for the last element if ( i < buffLen - 1 ) { ++len; } os.Write( str, len ); if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { return -1; } } else { // now convert the byte in two hex digits char c1 = c / 16; char c2 = c % 16; c1 += '0'; c2 += '0'; if ( c1 > '9' ) { c1 += 7; } if ( c2 > '9' ) { c2 += 7; } os.PutC( c1 ); os.PutC( c2 ); if ( os.GetLastError() != wxSTREAM_NO_ERROR ) { return -1; } if ( splitString ) { ++bytesWritten; } if (( bytesWritten >= MAX_BYTES_PER_ROW ) && ((buffLen - i ) >= 5 )) { // split the string if we wrote 20 bytes, but only is we have to // write at least 5 bytes os.Write( "\'\n", 2 ); int lastChar = WriteIndent( os, m_level + 2 ); // write indentation os.PutC( '\'' ); // reopen quotes if ( lastChar < 0 ) { return lastChar; } bytesWritten = 0; } } } // write the close character os.PutC( closeChar ); return closeChar; }
// helper functions for writing ASCII strings (even in Unicode build) static inline bool WriteAsciiChar(wxOutputStream& ostr, char ch) { ostr.PutC(ch); return ostr.IsOk(); }
static inline bool WriteAsciiString(wxOutputStream& ostr, const char *p) { return ostr.Write(p, strlen(p)).IsOk(); }
bool wxXPMHandler::SaveFile(wxImage * image, wxOutputStream& stream, bool WXUNUSED(verbose)) { wxString tmp; char tmp_c; // 1. count colours: #define MaxCixels 92 static const char Cixel[MaxCixels+1] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjk" "lzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; int chars_per_pixel; int cols; int i, j, k; cols = image->CountColours(); chars_per_pixel = 1; for ( k = MaxCixels; cols > k; k *= MaxCixels) chars_per_pixel++; // 2. write the header: wxString sName; if ( image->HasOption(wxIMAGE_OPTION_FILENAME) ) { wxSplitPath(image->GetOption(wxIMAGE_OPTION_FILENAME), NULL, &sName, NULL); sName << wxT("_xpm"); } if ( !sName.IsEmpty() ) sName = wxString(wxT("/* XPM */\nstatic char *")) + sName; else sName = wxT("/* XPM */\nstatic char *xpm_data"); stream.Write( (const char*) sName.ToAscii(), sName.Len() ); char tmpbuf[200]; // VS: 200b is safe upper bound for anything produced by sprintf below // (<101 bytes the string, neither %i can expand into more than 10 chars) sprintf(tmpbuf, "[] = {\n" "/* columns rows colors chars-per-pixel */\n" "\"%i %i %i %i\",\n", image->GetWidth(), image->GetHeight(), cols, chars_per_pixel); stream.Write(tmpbuf, strlen(tmpbuf)); // 3. create color symbols table: wxImageHistogram histogram; image->ComputeHistogram(histogram); char *symbols_data = new char[cols * (chars_per_pixel+1)]; char **symbols = new char*[cols]; // 2a. find mask colour: unsigned long mask_key = 0x1000000 /*invalid RGB value*/; if (image->HasMask()) mask_key = (image->GetMaskRed() << 16) | (image->GetMaskGreen() << 8) | image->GetMaskBlue(); // 2b. generate colour table: for (wxImageHistogram::iterator entry = histogram.begin(); entry != histogram.end(); ++entry ) { unsigned long index = entry->second.index; symbols[index] = symbols_data + index * (chars_per_pixel+1); char *sym = symbols[index]; k = index % MaxCixels; sym[0] = Cixel[k]; for (j = 1; j < chars_per_pixel; j++) { k = ((index - k) / MaxCixels) % MaxCixels; sym[j] = Cixel[k]; } sym[j] = '\0'; unsigned long key = entry->first; if (key == 0) sprintf( tmpbuf, "\"%s c Black\",\n", sym); else if (key == mask_key) sprintf( tmpbuf, "\"%s c None\",\n", sym); else { char rbuf[3]; DecToHex( (unsigned char)(key >> 16), rbuf ); char gbuf[3]; DecToHex( (unsigned char)(key >> 8), gbuf ); char bbuf[3]; DecToHex( (unsigned char)(key), bbuf ); sprintf( tmpbuf, "\"%s c #%s%s%s\",\n", sym, rbuf, gbuf, bbuf ); } stream.Write( tmpbuf, strlen(tmpbuf) ); } tmp = wxT("/* pixels */\n"); stream.Write( (const char*) tmp.ToAscii(), tmp.Length() ); unsigned char *data = image->GetData(); for (j = 0; j < image->GetHeight(); j++) { tmp_c = '\"'; stream.Write(&tmp_c, 1); for (i = 0; i < image->GetWidth(); i++, data += 3) { unsigned long key = (data[0] << 16) | (data[1] << 8) | (data[2]); stream.Write(symbols[histogram[key].index], chars_per_pixel); } tmp_c = '\"'; stream.Write(&tmp_c, 1); if ( j + 1 < image->GetHeight() ) { tmp_c = ','; stream.Write(&tmp_c, 1); } tmp_c = '\n'; stream.Write(&tmp_c, 1); } tmp = wxT("};\n"); stream.Write( (const char*) tmp.ToAscii(), 3 ); // Clean up: delete[] symbols; delete[] symbols_data; return true; }