From: <ag...@us...> - 2011-11-30 14:57:43
|
Revision: 2625 http://zoolib.svn.sourceforge.net/zoolib/?rev=2625&view=rev Author: agreen Date: 2011-11-30 14:57:33 +0000 (Wed, 30 Nov 2011) Log Message: ----------- Add the ability to write the extended JSON notation I've been using. Modified Paths: -------------- trunk/zoolib/source/cxx/zoolib/ZYad_JSON.cpp trunk/zoolib/source/cxx/zoolib/ZYad_JSON.h Modified: trunk/zoolib/source/cxx/zoolib/ZYad_JSON.cpp =================================================================== --- trunk/zoolib/source/cxx/zoolib/ZYad_JSON.cpp 2011-11-26 03:10:49 UTC (rev 2624) +++ trunk/zoolib/source/cxx/zoolib/ZYad_JSON.cpp 2011-11-30 14:57:33 UTC (rev 2625) @@ -20,6 +20,7 @@ #include "zoolib/ZCompat_cmath.h" #include "zoolib/ZSetRestore_T.h" +#include "zoolib/ZStreamW_HexStrim.h" #include "zoolib/ZStrim_Escaped.h" #include "zoolib/ZTime.h" #include "zoolib/ZUnicode.h" @@ -31,6 +32,7 @@ namespace ZooLib { namespace ZYad_JSON { +using std::min; using std::string; /*! \namespace ZooLib::ZYad_JSON @@ -265,6 +267,42 @@ // ================================================================================================= #pragma mark - +#pragma mark * ReadOptions + +ReadOptions sReadOptions_Extended() + { + ReadOptions theRO; + theRO.fAllowUnquotedPropertyNames = true; + theRO.fAllowEquals = true; + theRO.fAllowSemiColons = true; + theRO.fAllowTerminators = true; + theRO.fLooseSeparators = true; + theRO.fAllowBinary = true; + + return theRO; + } + +// ================================================================================================= +#pragma mark - +#pragma mark * WriteOptions + +WriteOptions::WriteOptions() +: ZYadOptions() +, fUseExtendedNotation(false) + {} + +WriteOptions::WriteOptions(const ZYadOptions& iOther) +: ZYadOptions(iOther) +, fUseExtendedNotation(false) + {} + +WriteOptions::WriteOptions(const WriteOptions& iOther) +: ZYadOptions(iOther) +, fUseExtendedNotation(iOther.fUseExtendedNotation) + {} + +// ================================================================================================= +#pragma mark - #pragma mark * ParseException ParseException::ParseException(const string& iWhat) @@ -407,14 +445,14 @@ #pragma mark * Static writing functions static void spWriteIndent(const ZStrimW& iStrimW, - size_t iCount, const ZYadOptions& iOptions) + size_t iCount, const WriteOptions& iOptions) { while (iCount--) iStrimW.Write(iOptions.fIndentString); } static void spWriteLFIndent(const ZStrimW& iStrimW, - size_t iCount, const ZYadOptions& iOptions) + size_t iCount, const WriteOptions& iOptions) { iStrimW.Write(iOptions.fEOLString); spWriteIndent(iStrimW, iCount, iOptions); @@ -446,6 +484,45 @@ s.Write("\""); } +static bool spContainsProblemChars(const string& iString) + { + if (iString.empty()) + { + // An empty string can't be distinguished from no string at all, so + // we treat it as if it has problem chars, so it will be wrapped in quotes. + return true; + } + + for (string::const_iterator i = iString.begin(), end = iString.end();;) + { + UTF32 theCP; + if (not ZUnicode::sReadInc(i, end, theCP)) + break; + if (not ZUnicode::sIsAlphaDigit(theCP) && '_' != theCP) + return true; + } + + return false; + } + +static void spWritePropName(const ZStrimW& s, const string& iString) + { + ZStrimW_Escaped::Options theOptions; + theOptions.fQuoteQuotes = true; + theOptions.fEscapeHighUnicode = false; + + if (spContainsProblemChars(iString)) + { + s << "\""; + ZStrimW_Escaped(theOptions, s) << iString; + s << "\""; + } + else + { + ZStrimW_Escaped(theOptions, s) << iString; + } + } + static void spToStrim_SimpleValue(const ZStrimW& s, const ZAny& iAny) { if (false) @@ -483,12 +560,134 @@ } } +static void spToStrim_Stream(const ZStrimW& s, const ZStreamRPos& iStreamRPos, + size_t iLevel, const WriteOptions& iOptions, bool iMayNeedInitialLF) + { + uint64 theSize = iStreamRPos.GetSize(); + if (theSize == 0) + { + // we've got an empty Raw + s.Write("()"); + } + else + { + if (iOptions.DoIndentation() && theSize > iOptions.fRawChunkSize) + { + if (iMayNeedInitialLF) + spWriteLFIndent(s, iLevel, iOptions); + + uint64 countRemaining = theSize; + if (iOptions.fRawSizeCap) + countRemaining = min(countRemaining, iOptions.fRawSizeCap.Get()); + + s.Writef("( // %lld bytes", theSize); + + if (countRemaining < theSize) + s.Writef(" (truncated at %lld bytes)", iOptions.fRawSizeCap.Get()); + + spWriteLFIndent(s, iLevel, iOptions); + if (iOptions.fRawAsASCII) + { + for (;;) + { + uint64 lastPos = iStreamRPos.GetPosition(); + const size_t countToCopy = + min(iOptions.fRawChunkSize, ZStream::sClampedSize(countRemaining)); + uint64 countCopied; + ZStreamW_HexStrim(iOptions.fRawByteSeparator, string(), 0, s) + .CopyFrom(iStreamRPos, countToCopy, &countCopied, nullptr); + countRemaining -= countCopied; + if (countCopied == 0) + break; + + iStreamRPos.SetPosition(lastPos); + if (size_t extraSpaces = iOptions.fRawChunkSize - countCopied) + { + // We didn't write a complete line of bytes, so pad it out. + while (extraSpaces--) + { + // Two spaces for the two nibbles + s.Write(" "); + // And then the separator sequence + s.Write(iOptions.fRawByteSeparator); + } + } + + s.Write(" // "); + while (countCopied--) + { + char theChar = iStreamRPos.ReadInt8(); + if (theChar < 0x20 || theChar > 0x7E) + s.WriteCP('.'); + else + s.WriteCP(theChar); + } + spWriteLFIndent(s, iLevel, iOptions); + } + } + else + { + string eol = iOptions.fEOLString; + for (size_t x = 0; x < iLevel; ++x) + eol += iOptions.fIndentString; + + ZStreamW_HexStrim(iOptions.fRawByteSeparator, + eol, iOptions.fRawChunkSize, s).CopyAllFrom(iStreamRPos); + + spWriteLFIndent(s, iLevel, iOptions); + } + + s.Write(")"); + } + else + { + s.Write("("); + + ZStreamW_HexStrim(iOptions.fRawByteSeparator, string(), 0, s) + .CopyAllFrom(iStreamRPos); + + if (iOptions.fRawAsASCII) + { + iStreamRPos.SetPosition(0); + s.Write(" /* "); + while (theSize--) + { + char theChar = iStreamRPos.ReadInt8(); + if (theChar < 0x20 || theChar > 0x7E) + s.WriteCP('.'); + else + s.WriteCP(theChar); + } + s.Write(" */"); + } + s.Write(")"); + } + } + } + +static void spToStrim_Stream(const ZStrimW& s, const ZStreamR& iStreamR, + size_t iLevel, const WriteOptions& iOptions, bool iMayNeedInitialLF) + { + if (const ZStreamRPos* theStreamRPos = dynamic_cast<const ZStreamRPos*>(&iStreamR)) + { + spToStrim_Stream(s, *theStreamRPos, iLevel, iOptions, iMayNeedInitialLF); + } + else + { + s.Write("("); + + ZStreamW_HexStrim(iOptions.fRawByteSeparator, string(), 0, s) + .CopyAllFrom(iStreamR); + + s.Write(")"); + } + } // ================================================================================================= #pragma mark - #pragma mark * Visitor_Writer Visitor_Writer::Visitor_Writer - (size_t iIndent, const ZYadOptions& iOptions, const ZStrimW& iStrimW) + (size_t iIndent, const WriteOptions& iOptions, const ZStrimW& iStrimW) : fIndent(iIndent), fOptions(iOptions), fStrimW(iStrimW), @@ -499,18 +698,14 @@ { fStrimW << "null"; if (fOptions.fBreakStrings) - fStrimW << " /*!! Unhandled yad !!*/"; + fStrimW << " /*!! Unhandled yad: " << typeid(*iYadR.Get()).name() <<" !!*/"; } void Visitor_Writer::Visit_YadAtomR(const ZRef<ZYadAtomR>& iYadAtomR) { spToStrim_SimpleValue(fStrimW, iYadAtomR->AsAny()); } void Visitor_Writer::Visit_YadStreamR(const ZRef<ZYadStreamR>& iYadStreamR) - { - fStrimW << "null"; - if (fOptions.fBreakStrings) - fStrimW << " /*!! ZYadStreamR not representable in JSON !!*/"; - } + { spToStrim_Stream(fStrimW, iYadStreamR->GetStreamR(), fIndent, fOptions, fMayNeedInitialLF); } void Visitor_Writer::Visit_YadStrimR(const ZRef<ZYadStrimR>& iYadStrimR) { spWriteString(fStrimW, iYadStrimR->GetStrimR()); } @@ -547,6 +742,12 @@ { break; } + else if (fOptions.fUseExtendedNotation.DGet(false)) + { + spWriteLFIndent(fStrimW, fIndent, fOptions); + cur->Accept(*this); + fStrimW.Write(";"); + } else { if (not isFirst) @@ -569,6 +770,13 @@ { break; } + else if (fOptions.fUseExtendedNotation.DGet(false)) + { + if (not isFirst && fOptions.fBreakStrings) + fStrimW.Write(" "); + cur->Accept(*this); + fStrimW.Write(";"); + } else { if (not isFirst) @@ -609,6 +817,17 @@ { break; } + else if (fOptions.fUseExtendedNotation.DGet(false)) + { + spWriteLFIndent(fStrimW, fIndent, fOptions); + spWritePropName(fStrimW, curName); + fStrimW << " = "; + + ZSetRestore_T<size_t> theSR_Indent(fIndent, fIndent + 1); + ZSetRestore_T<bool> theSR_MayNeedInitialLF(fMayNeedInitialLF, true); + cur->Accept(*this); + fStrimW.Write(";"); + } else { if (not isFirst) @@ -635,6 +854,22 @@ { break; } + else if (fOptions.fUseExtendedNotation.DGet(false)) + { + if (not isFirst && fOptions.fBreakStrings) + fStrimW.Write(" "); + + spWritePropName(fStrimW, curName); + if (fOptions.fBreakStrings) + fStrimW.Write(" = "); + else + fStrimW.Write("="); + + ZSetRestore_T<size_t> theSR_Indent(fIndent, fIndent + 1); + ZSetRestore_T<bool> theSR_MayNeedInitialLF(fMayNeedInitialLF, true); + cur->Accept(*this); + fStrimW.Write(";"); + } else { if (not isFirst) @@ -648,8 +883,6 @@ ZSetRestore_T<size_t> theSR_Indent(fIndent, fIndent + 1); ZSetRestore_T<bool> theSR_MayNeedInitialLF(fMayNeedInitialLF, true); - fIndent = fIndent + 1; - fMayNeedInitialLF = true; cur->Accept(*this); } } @@ -670,9 +903,9 @@ { return spMakeYadR_JSON(iStrimmerU, iReadOptions); } void sToStrim(ZRef<ZYadR> iYadR, const ZStrimW& s) - { sToStrim(0, ZYadOptions(), iYadR, s); } + { sToStrim(0, WriteOptions(), iYadR, s); } -void sToStrim(size_t iInitialIndent, const ZYadOptions& iOptions, +void sToStrim(size_t iInitialIndent, const WriteOptions& iOptions, ZRef<ZYadR> iYadR, const ZStrimW& s) { if (iYadR) Modified: trunk/zoolib/source/cxx/zoolib/ZYad_JSON.h =================================================================== --- trunk/zoolib/source/cxx/zoolib/ZYad_JSON.h 2011-11-26 03:10:49 UTC (rev 2624) +++ trunk/zoolib/source/cxx/zoolib/ZYad_JSON.h 2011-11-30 14:57:33 UTC (rev 2625) @@ -40,10 +40,26 @@ ZQ<bool> fAllowSemiColons; ZQ<bool> fAllowTerminators; ZQ<bool> fLooseSeparators; + ZQ<bool> fAllowBinary; }; +ReadOptions sReadOptions_Extended(); + // ================================================================================================= #pragma mark - +#pragma mark * WriteOptions + +struct WriteOptions : ZYadOptions + { + WriteOptions(); + WriteOptions(const ZYadOptions& iOther); + WriteOptions(const WriteOptions& iOther); + + ZQ<bool> fUseExtendedNotation; + }; + +// ================================================================================================= +#pragma mark - #pragma mark * ParseException class ParseException : public ZYadParseException_Std @@ -116,7 +132,7 @@ { public: Visitor_Writer - (size_t iIndent, const ZYadOptions& iOptions, const ZStrimW& iStrimW); + (size_t iIndent, const WriteOptions& iOptions, const ZStrimW& iStrimW); // From ZVisitor_Yad virtual void Visit_YadR(const ZRef<ZYadR>& iYadR); @@ -128,7 +144,7 @@ private: size_t fIndent; - const ZYadOptions fOptions; + const WriteOptions fOptions; const ZStrimW& fStrimW; bool fMayNeedInitialLF; }; @@ -142,7 +158,7 @@ void sToStrim(ZRef<ZYadR> iYadR, const ZStrimW& s); -void sToStrim(size_t iInitialIndent, const ZYadOptions& iOptions, +void sToStrim(size_t iInitialIndent, const WriteOptions& iOptions, ZRef<ZYadR> iYadR, const ZStrimW& s); } // namespace ZYad_JSON This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |