Ejemplo n.º 1
0
void
BJson::_Parse(BMessage& message, BString& JSON)
{
	BMessageBuilder builder(message);
	int32 pos = 0;
	int32 length = JSON.Length();
	
	/* Locals used by the parser. */
	// Keeps track of the hierarchy (e.g. "{[{{") that has
	// been read in. Allows the parser to verify that openbraces
	// match up to closebraces and so on and so forth.
	BString hierarchy("");
	// Stores the key that was just read by the string parser,
	// in the case that we are parsing a map.
	BString key("");
	
	// TODO: Check builder return codes and throw exception, or
	// change builder implementation/interface to throw exceptions
	// instead of returning errors.
	// TODO: Elimitate more duplicated code, for example by moving
	// more code into _ParseConstant().
	
	while (pos < length) {
		switch (JSON[pos]) {
		case '{':
			hierarchy += "{";
			
			if (hierarchy != "{") {
				if (builder.What() == JSON_TYPE_ARRAY)
					builder.PushObject(builder.CountNames());
				else {
					builder.PushObject(key.String());
					key = "";
				}
			}

			builder.SetWhat(JSON_TYPE_MAP);
			break;

		case '}':
			if (hierarchy.EndsWith("{") && hierarchy.Length() != 1) {
				hierarchy.Truncate(hierarchy.Length() - 1);
				builder.PopObject();
			} else if (hierarchy.Length() == 1)
				return; // End of the JSON data
			else
				throw ParseException(pos, "Unmatched closebrace }");

            break;

		case '[':
			hierarchy += "[";
			
			if (builder.What() == JSON_TYPE_ARRAY)
				builder.PushObject(builder.CountNames());
			else {
				builder.PushObject(key.String());
				key = "";
			}

			builder.SetWhat(JSON_TYPE_ARRAY);
			break;

		case ']':
			if (hierarchy.EndsWith("[")) {
				hierarchy.Truncate(hierarchy.Length() - 1);
				builder.PopObject();
			} else {
				BString error("Unmatched closebrace ] hierarchy: ");
				error << hierarchy;
				throw ParseException(pos, error);
			}

			break;

		case 't':
		{
			if (builder.What() != JSON_TYPE_ARRAY && key.Length() == 0) {
				throw ParseException(pos,
					"'true' cannot be a key, it can only be a value");
			}
			
			if (_ParseConstant(JSON, pos, "true")) {
				if (builder.What() == JSON_TYPE_ARRAY)
					key.SetToFormat("%" B_PRIu32, builder.CountNames());
				builder.AddBool(key.String(), true);
				key = "";
			} else
				throw ParseException(pos, "Unexpected 't'");

			break;
		}

		case 'f':
		{
			if (builder.What() != JSON_TYPE_ARRAY && key.Length() == 0) {
				throw ParseException(pos,
					"'false' cannot be a key, it can only be a value");
			}
			
			if (_ParseConstant(JSON, pos, "false")) {
				if (builder.What() == JSON_TYPE_ARRAY)
					key.SetToFormat("%" B_PRIu32, builder.CountNames());
				builder.AddBool(key.String(), false);
				key = "";
			} else
				throw ParseException(pos, "Unexpected 'f'");

			break;
		}

        case 'n':
        {
			if (builder.What() != JSON_TYPE_ARRAY && key.Length() == 0) {
				throw ParseException(pos,
					"'null' cannot be a key, it can only be a value");
			}
			
			if (_ParseConstant(JSON, pos, "null")) {
				if (builder.What() == JSON_TYPE_ARRAY)
					key.SetToFormat("%" B_PRIu32, builder.CountNames());
				builder.AddPointer(key.String(), (void*)NULL);
				key = "";
			} else
				throw ParseException(pos, "Unexpected 'n'");

			break;
		}

		case '"':
			if (builder.What() != JSON_TYPE_ARRAY && key.Length() == 0)
				key = _ParseString(JSON, pos);
			else if (builder.What() != JSON_TYPE_ARRAY && key.Length() > 0) {
				builder.AddString(key, _ParseString(JSON, pos));
				key = "";
			} else if (builder.What() == JSON_TYPE_ARRAY) {
				key << builder.CountNames();
				builder.AddString(key, _ParseString(JSON, pos));
				key = "";
			} else
				throw ParseException(pos, "Internal error at encountering \"");

			break;

		case '+':
		case '-':
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		{
			if (builder.What() != JSON_TYPE_ARRAY && key.Length() == 0) {
				throw ParseException(pos,
					"Numbers cannot be keys, they can only be values");
			}
			
			if (builder.What() == JSON_TYPE_ARRAY)
				key << builder.CountNames();

			double number = _ParseNumber(JSON, pos);
			builder.AddDouble(key.String(), number);

			key = "";
			break;
		}

		case ':':
		case ',':
		default:
			// No need to do anything here.
			break;
		}
		pos++;
	}

	throw ParseException(pos, "Unexpected end of document");
}
Ejemplo n.º 2
0
   IMAPResult
   IMAPFetchParser::ParseCommand(const String &sCommand)
   {
      String sStringToParse = sCommand;
      
      IMAPResult result = _ValidateSyntax(sStringToParse);
      if (result.GetResult() != IMAPResult::ResultOK)
         return result;
      
      std::vector<String> vecResult = _ParseString(sStringToParse);
      std::vector<String>::iterator iter = vecResult.begin();
      while (iter != vecResult.end())
      {
         String sPart = (*iter);

         
         ePartType iType = _GetPartType(sPart);

         switch (iType)
         {
            case BODYPEEK:
            {
               IMAPFetchParser::BodyPart oPart = _ParseBODYPEEK(sPart);
               m_vecPartsToLookAt.push_back(oPart);
               break;
            }
            
            case ENVELOPE:
            {
               m_bShowEnvelope = true;
               break;
            }
            
            case RFC822SIZE:
            {
               m_bShowRFCSize = true;
               break;
            }

            case UID:
            {
               m_bShowUID = true;
               break;
            }

            case FLAGS:
            {
               m_bShowFlags = true;
               break;
            }

            case INTERNALDATE:
            {
               m_bShowInternalDate = true;
               break;
            }

            case BODYSTRUCTURE:
            {
               m_bShowBodyStructure = true;
               break;
            }
            
            case BODYSTRUCTURENONEXTENSIBLE:
            {
               m_bShowBodyStructureNonExtensible = true;
               break;
            }

            case BODY:
            {
               IMAPFetchParser::BodyPart oPart = _ParseBODY(sPart);
               m_vecPartsToLookAt.push_back(oPart);
               break;
            }
            case RFC822:
            {
               // Same as:
               IMAPFetchParser::BodyPart oPart = _ParseBODY(sPart);
               oPart.SetDescription("RFC822");
               m_vecPartsToLookAt.push_back(oPart);
               break;

            }
            case ALL:
            {
               // ALL
               // Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE)

               m_bShowFlags = true;
               m_bShowInternalDate = true;
               m_bShowRFCSize = true;
               m_bShowEnvelope = true;
               break;
            }

            case FAST:
            {
               // FAST
               // Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE)

               m_bShowFlags = true;
               m_bShowInternalDate = true;
               m_bShowRFCSize = true;
               break;
            }

            case FULL:
            {
               // FULL
               // Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY)
               m_bShowFlags = true;
               m_bShowInternalDate = true;
               m_bShowRFCSize = true;
               m_bShowEnvelope = true;
               m_bShowBodyStructure = true;
               break;
            }
            case RFC822HEADER:
            {
               /* 
                  RFC822.HEADER
                  Functionally equivalent to BODY.PEEK[HEADER], differing in the
                  syntax of the resulting untagged FETCH data (RFC822.HEADER is
                  returned).
                  */
            
               IMAPFetchParser::BodyPart oPart = _ParseBODYPEEK("BODY[HEADER]");
               oPart.SetDescription("RFC822.HEADER");
               m_vecPartsToLookAt.push_back(oPart);
               break;
            }
            case RFC822TEXT:
               {
                  /* 
                  Functionally equivalent to BODY[TEXT], differing in the syntax
                  of the resulting untagged FETCH data (RFC822.TEXT is returned).
                  */

                  IMAPFetchParser::BodyPart oPart = _ParseBODY("BODY[TEXT]");
                  oPart.SetDescription("RFC822.TEXT");
                  m_vecPartsToLookAt.push_back(oPart);

                  break;
               }
         }

         iter++;
      }

      return IMAPResult();
   }