Response PageBlobClient::GetPageRangesDiff()

in sdk/storage/azure-storage-blobs/src/rest_client.cpp [6577:6754]


    Response<Models::_detail::GetPageRangesDiffResult> PageBlobClient::GetPageRangesDiff(
        Core::Http::_internal::HttpPipeline& pipeline,
        const Core::Url& url,
        const GetPageBlobPageRangesDiffOptions& options,
        const Core::Context& context)
    {
      auto request = Core::Http::Request(Core::Http::HttpMethod::Get, url);
      request.GetUrl().AppendQueryParameter("comp", "pagelist");
      if (options.Snapshot.HasValue() && !options.Snapshot.Value().empty())
      {
        request.GetUrl().AppendQueryParameter(
            "snapshot", _internal::UrlEncodeQueryParameter(options.Snapshot.Value()));
      }
      if (options.Prevsnapshot.HasValue() && !options.Prevsnapshot.Value().empty())
      {
        request.GetUrl().AppendQueryParameter(
            "prevsnapshot", _internal::UrlEncodeQueryParameter(options.Prevsnapshot.Value()));
      }
      if (options.PrevSnapshotUrl.HasValue() && !options.PrevSnapshotUrl.Value().empty())
      {
        request.SetHeader("x-ms-previous-snapshot-url", options.PrevSnapshotUrl.Value());
      }
      if (options.Range.HasValue() && !options.Range.Value().empty())
      {
        request.SetHeader("x-ms-range", options.Range.Value());
      }
      if (options.LeaseId.HasValue() && !options.LeaseId.Value().empty())
      {
        request.SetHeader("x-ms-lease-id", options.LeaseId.Value());
      }
      if (options.IfModifiedSince.HasValue())
      {
        request.SetHeader(
            "If-Modified-Since",
            options.IfModifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123));
      }
      if (options.IfUnmodifiedSince.HasValue())
      {
        request.SetHeader(
            "If-Unmodified-Since",
            options.IfUnmodifiedSince.Value().ToString(Azure::DateTime::DateFormat::Rfc1123));
      }
      if (options.IfMatch.HasValue() && !options.IfMatch.ToString().empty())
      {
        request.SetHeader("If-Match", options.IfMatch.ToString());
      }
      if (options.IfNoneMatch.HasValue() && !options.IfNoneMatch.ToString().empty())
      {
        request.SetHeader("If-None-Match", options.IfNoneMatch.ToString());
      }
      if (options.IfTags.HasValue() && !options.IfTags.Value().empty())
      {
        request.SetHeader("x-ms-if-tags", options.IfTags.Value());
      }
      request.SetHeader("x-ms-version", "2024-08-04");
      if (options.Marker.HasValue() && !options.Marker.Value().empty())
      {
        request.GetUrl().AppendQueryParameter(
            "marker", _internal::UrlEncodeQueryParameter(options.Marker.Value()));
      }
      if (options.MaxResults.HasValue())
      {
        request.GetUrl().AppendQueryParameter(
            "maxresults", std::to_string(options.MaxResults.Value()));
      }
      auto pRawResponse = pipeline.Send(request, context);
      auto httpStatusCode = pRawResponse->GetStatusCode();
      if (httpStatusCode != Core::Http::HttpStatusCode::Ok)
      {
        throw StorageException::CreateFromResponse(std::move(pRawResponse));
      }
      Models::_detail::GetPageRangesDiffResult response;
      {
        const auto& responseBody = pRawResponse->GetBody();
        _internal::XmlReader reader(
            reinterpret_cast<const char*>(responseBody.data()), responseBody.size());
        enum class XmlTagEnum
        {
          kUnknown,
          kPageList,
          kPageRange,
          kStart,
          kEnd,
          kClearRange,
          kNextMarker,
        };
        const std::unordered_map<std::string, XmlTagEnum> XmlTagEnumMap{
            {"PageList", XmlTagEnum::kPageList},
            {"PageRange", XmlTagEnum::kPageRange},
            {"Start", XmlTagEnum::kStart},
            {"End", XmlTagEnum::kEnd},
            {"ClearRange", XmlTagEnum::kClearRange},
            {"NextMarker", XmlTagEnum::kNextMarker},
        };
        std::vector<XmlTagEnum> xmlPath;
        Core::Http::HttpRange vectorElement1;
        Core::Http::HttpRange vectorElement2;
        while (true)
        {
          auto node = reader.Read();
          if (node.Type == _internal::XmlNodeType::End)
          {
            break;
          }
          else if (node.Type == _internal::XmlNodeType::StartTag)
          {
            auto ite = XmlTagEnumMap.find(node.Name);
            xmlPath.push_back(ite == XmlTagEnumMap.end() ? XmlTagEnum::kUnknown : ite->second);
          }
          else if (node.Type == _internal::XmlNodeType::Text)
          {
            if (xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kPageRange && xmlPath[2] == XmlTagEnum::kStart)
            {
              vectorElement1.Offset = std::stoll(node.Value);
            }
            else if (
                xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kPageRange && xmlPath[2] == XmlTagEnum::kEnd)
            {
              vectorElement1.Length = std::stoll(node.Value);
            }
            else if (
                xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kClearRange && xmlPath[2] == XmlTagEnum::kStart)
            {
              vectorElement2.Offset = std::stoll(node.Value);
            }
            else if (
                xmlPath.size() == 3 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kClearRange && xmlPath[2] == XmlTagEnum::kEnd)
            {
              vectorElement2.Length = std::stoll(node.Value);
            }
            else if (
                xmlPath.size() == 2 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kNextMarker)
            {
              response.ContinuationToken = node.Value;
            }
          }
          else if (node.Type == _internal::XmlNodeType::Attribute)
          {
          }
          else if (node.Type == _internal::XmlNodeType::EndTag)
          {
            if (xmlPath.size() == 2 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kPageRange)
            {
              vectorElement1.Length = vectorElement1.Length.Value() - vectorElement1.Offset + 1;
              response.PageRanges.push_back(std::move(vectorElement1));
              vectorElement1 = Core::Http::HttpRange();
            }
            else if (
                xmlPath.size() == 2 && xmlPath[0] == XmlTagEnum::kPageList
                && xmlPath[1] == XmlTagEnum::kClearRange)
            {
              vectorElement2.Length = vectorElement2.Length.Value() - vectorElement2.Offset + 1;
              response.ClearRanges.push_back(std::move(vectorElement2));
              vectorElement2 = Core::Http::HttpRange();
            }
            xmlPath.pop_back();
          }
        }
      }
      if (pRawResponse->GetHeaders().count("Last-Modified") != 0)
      {
        response.LastModified = DateTime::Parse(
            pRawResponse->GetHeaders().at("Last-Modified"), Azure::DateTime::DateFormat::Rfc1123);
      }
      if (pRawResponse->GetHeaders().count("ETag") != 0)
      {
        response.ETag = ETag(pRawResponse->GetHeaders().at("ETag"));
      }
      response.BlobSize = std::stoll(pRawResponse->GetHeaders().at("x-ms-blob-content-length"));
      return Response<Models::_detail::GetPageRangesDiffResult>(
          std::move(response), std::move(pRawResponse));
    }